Merge remote-tracking branch 'origin/0.8.X' into 0.8.X

This commit is contained in:
2026-05-08 10:13:17 +08:00
36 changed files with 2460 additions and 262 deletions

View File

@@ -19,7 +19,7 @@ const service = axios.create({
// axios中请求配置有baseURL选项表示请求URL公共部分
baseURL: process.env.VUE_APP_BASE_API,
// 超时
timeout: 30000
timeout: 300000
})
// request拦截器

View File

@@ -96,8 +96,7 @@
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
<el-button icon="el-icon-download" size="mini" @click="handleNewExport" v-if="showNewExport">导出当前</el-button>
<el-button type="info" icon="el-icon-download" size="mini" @click="handleNewExportProps" v-if="showNewExport">导出全部</el-button>
<el-button icon="el-icon-download" size="mini" @click="handleNewExport" v-if="showNewExport">导出</el-button>
</el-form-item>
<!-- <el-form-item style="float: right;" v-if="showWaybill" v-loading="loading">

View File

@@ -1,25 +1,24 @@
<template>
<ComprehensiveTemplate
:actionTypes="actionTypes"
:actionQueryParams="actionQueryParams"
:baseQueryParams="baseQueryParams"
:warehouseOptions="warehouseOptions"
<ActionTemplate
:actionType="actionType"
:reportType="reportType"
:productionLine="productionLine"
/>
</template>
<script>
import ComprehensiveTemplate from '@/views/wms/report/template/comprehensive.vue'
import { lajiaoConfig } from '@/views/wms/report/js/config.js'
import ActionTemplate from '@/views/wms/report/template/action.vue'
export default {
name: 'ComprehensiveReport',
components: {
ComprehensiveTemplate,
ActionTemplate,
},
data() {
return {
...lajiaoConfig,
actionType: 503,
reportType: 'all',
productionLine: '拉矫线',
}
}
}

View File

@@ -1,25 +1,24 @@
<template>
<DayTemplate
:actionTypes="actionTypes"
:actionQueryParams="actionQueryParams"
:baseQueryParams="baseQueryParams"
:warehouseOptions="warehouseOptions"
<ActionTemplate
:actionType="actionType"
:reportType="reportType"
:productionLine="productionLine"
/>
</template>
<script>
import DayTemplate from '@/views/wms/report/template/day.vue'
import { lajiaoConfig } from '@/views/wms/report/js/config.js'
import ActionTemplate from '@/views/wms/report/template/action.vue'
export default {
name: 'DayReport',
components: {
DayTemplate,
ActionTemplate,
},
data() {
return {
...lajiaoConfig,
actionType: 503,
reportType: 'day',
productionLine: '拉矫线',
}
}
}

View File

@@ -1,26 +1,25 @@
<template>
<LossTemplate
:actionTypes="actionTypes"
:actionQueryParams="actionQueryParams"
:baseQueryParams="baseQueryParams"
:warehouseOptions="warehouseOptions"
<ActionTemplate
:actionType="actionType"
:reportType="reportType"
:productionLine="productionLine"
></LossTemplate>
/>
</template>
<script>
import LossTemplate from '@/views/wms/report/template/loss.vue'
import { lajiaoConfig } from '@/views/wms/report/js/config.js'
import ActionTemplate from '@/views/wms/report/template/action.vue'
export default {
name: 'LossReport',
components: {
LossTemplate,
},
data() {
return {
...lajiaoConfig,
}
export default {
name: 'DayReport',
components: {
ActionTemplate,
},
data() {
return {
actionType: 503,
reportType: 'loss',
productionLine: '拉矫线',
}
}
}
</script>

View File

@@ -1,25 +1,24 @@
<template>
<MonthTemplate
:actionTypes="actionTypes"
:actionQueryParams="actionQueryParams"
:baseQueryParams="baseQueryParams"
:warehouseOptions="warehouseOptions"
<ActionTemplate
:actionType="actionType"
:reportType="reportType"
:productionLine="productionLine"
/>
</template>
<script>
import MonthTemplate from '@/views/wms/report/template/month.vue'
import { lajiaoConfig } from '@/views/wms/report/js/config.js'
import ActionTemplate from '@/views/wms/report/template/action.vue'
export default {
name: 'MonthReport',
components: {
MonthTemplate,
ActionTemplate,
},
data() {
return {
...lajiaoConfig,
actionType: 503,
reportType: 'month',
productionLine: '拉矫线',
}
}
}

View File

@@ -1,23 +1,24 @@
<template>
<OutTemplate
:baseQueryParams="baseQueryParams"
:warehouseOptions="warehouseOptions"
<ActionTemplate
:actionType="actionType"
:reportType="reportType"
:productionLine="productionLine"
/>
</template>
<script>
import OutTemplate from "@/views/wms/report/template/out.vue";
import { lajiaoConfig } from '@/views/wms/report/js/config.js'
import ActionTemplate from '@/views/wms/report/template/action.vue'
export default {
name: 'ZhaTemplate',
name: 'DayReport',
components: {
OutTemplate,
ActionTemplate,
},
data() {
return {
...lajiaoConfig,
actionType: 503,
reportType: 'out',
productionLine: '拉矫线',
}
}
}

View File

@@ -1,25 +1,24 @@
<template>
<TeamTemplate
:actionTypes="actionTypes"
:actionQueryParams="actionQueryParams"
:baseQueryParams="baseQueryParams"
:warehouseOptions="warehouseOptions"
<ActionTemplate
:actionType="actionType"
:reportType="reportType"
:productionLine="productionLine"
/>
</template>
<script>
import TeamTemplate from '@/views/wms/report/template/team.vue'
import { lajiaoConfig } from '@/views/wms/report/js/config.js'
import ActionTemplate from '@/views/wms/report/template/action.vue'
export default {
name: 'TeamReport',
name: 'DayReport',
components: {
TeamTemplate,
ActionTemplate,
},
data() {
return {
...lajiaoConfig,
actionType: 503,
reportType: 'team',
productionLine: '拉矫线',
}
}
}

View File

@@ -1,25 +1,24 @@
<template>
<YearTemplate
:actionTypes="actionTypes"
:actionQueryParams="actionQueryParams"
:baseQueryParams="baseQueryParams"
:warehouseOptions="warehouseOptions"
<ActionTemplate
:actionType="actionType"
:reportType="reportType"
:productionLine="productionLine"
/>
</template>
<script>
import YearTemplate from '@/views/wms/report/template/year.vue'
import { lajiaoConfig } from '@/views/wms/report/js/config.js'
import ActionTemplate from '@/views/wms/report/template/action.vue'
export default {
name: 'YearReport',
components: {
YearTemplate,
ActionTemplate,
},
data() {
return {
...lajiaoConfig,
actionType: 503,
reportType: 'year',
productionLine: '拉矫线',
}
}
}

View File

@@ -0,0 +1,639 @@
<template>
<div class="app-container" v-loading="loading">
<el-row>
<el-form label-width="80px" inline>
<!-- 根据 reportType 显示不同的日期选择器 -->
<template v-if="['out', 'loss'].includes(reportType)">
<el-form-item label="时间范围" prop="timeRange">
<time-range-picker
v-model="queryParams"
start-key="startTime"
end-key="endTime"
:default-start-time="defaultStartTime"
:default-end-time="defaultEndTime"
@quick-select="handleQuery"
/>
</el-form-item>
</template>
<el-form-item v-else-if="reportType === 'day'" label="日期" prop="date">
<el-date-picker style="width: 200px;" v-model="dayDate" type="date"
value-format="yyyy-MM-dd" placeholder="选择日期" @change="handleDateChange"></el-date-picker>
</el-form-item>
<el-form-item v-else-if="reportType === 'month'" label="日期" prop="date">
<el-date-picker style="width: 200px;" v-model="monthDate" type="month"
value-format="yyyy-MM" placeholder="选择月份" @change="handleDateChange"></el-date-picker>
</el-form-item>
<el-form-item v-else-if="reportType === 'year'" label="日期" prop="date">
<el-date-picker style="width: 200px;" v-model="yearDate" type="year"
value-format="yyyy" placeholder="选择年份" @change="handleDateChange"></el-date-picker>
</el-form-item>
<template v-else-if="reportType === 'team'">
<el-form-item label="开始日期">
<el-date-picker style="width: 200px;" v-model="queryParams.byCreateTimeStart" type="date"
value-format="yyyy-MM-dd HH:mm:ss" placeholder="选择日期"></el-date-picker>
</el-form-item>
<el-form-item label="结束日期">
<el-date-picker style="width: 200px;" v-model="queryParams.byCreateTimeEnd" type="date"
value-format="yyyy-MM-dd HH:mm:ss" placeholder="选择日期"></el-date-picker>
</el-form-item>
<el-form-item label="班组">
<el-select v-model="queryParams.team" placeholder="请选择班组" style="width: 200px;">
<el-option label="甲" value="甲" />
<el-option label="乙" value="乙" />
</el-select>
</el-form-item>
</template>
<template v-else>
<el-form-item label="开始时间" prop="startTime">
<el-date-picker style="width: 200px;" v-model="queryParams.startTime" type="datetime"
value-format="yyyy-MM-dd HH:mm:ss" placeholder="选择开始日期"></el-date-picker>
</el-form-item>
<el-form-item label="结束时间" prop="endTime">
<el-date-picker style="width: 200px;" v-model="queryParams.endTime" type="datetime"
value-format="yyyy-MM-dd HH:mm:ss" placeholder="选择结束日期"></el-date-picker>
</el-form-item>
</template>
<el-form-item label="入场钢卷号" prop="enterCoilNo">
<el-input style="width: 200px; display: inline-block;" v-model="queryParams.enterCoilNo"
placeholder="请输入入场钢卷号" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="当前钢卷号" prop="currentCoilNo">
<el-input style="width: 200px;" v-model="queryParams.currentCoilNo" placeholder="请输入当前钢卷号" clearable
@keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="产品名称" prop="itemName">
<el-input style="width: 200px;" v-model="queryParams.itemName" placeholder="请输入产品名称" clearable
@keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="规格" prop="itemSpecification">
<memo-input style="width: 200px;" v-model="queryParams.itemSpecification" storageKey="coilSpec"
placeholder="请选择规格" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="材质" prop="itemMaterial">
<dict-select style="width: 200px;" v-model="queryParams.itemMaterial" dict-type="coil_material"
placeholder="请选择材质" clearable @keyup.enter.native="handleQuery" multiple />
</el-form-item>
<el-form-item label="厂家" prop="itemManufacturer">
<dict-select style="width: 200px;" v-model="queryParams.itemManufacturer" dict-type="coil_manufacturer"
placeholder="请选择厂家" clearable @keyup.enter.native="handleQuery" multiple />
</el-form-item>
<!-- 逻辑库位仅在 team, day, month, year, all 类型时显示 -->
<el-form-item v-if="['team', 'day', 'month', 'year', 'all'].includes(reportType)" label="逻辑库位" prop="warehouseIds">
<el-select v-model="warehouseIds" collapse-tags multiple placeholder="请选择逻辑库位" style="width: 200px;">
<el-option v-for="item in warehouseOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleQuery">查询</el-button>
<el-button v-if="['out', 'team', 'day', 'month', 'year', 'all'].includes(reportType)" type="primary" @click="exportData">导出产出钢卷</el-button>
<el-button v-if="['loss', 'team', 'day', 'month', 'year', 'all'].includes(reportType)" type="primary" @click="exportLossData">导出消耗钢卷</el-button>
<el-button type="primary" @click="settingVisible = true">列设置</el-button>
<el-button v-if="['out', 'team', 'day', 'month', 'year', 'all'].includes(reportType)" type="primary" @click="saveOutputReport">保存产出报表</el-button>
<el-button v-if="['loss', 'team', 'day', 'month', 'year', 'all'].includes(reportType)" type="primary" @click="saveLossReport">保存消耗报表</el-button>
</el-form-item>
</el-form>
</el-row>
<!-- out 类型的统计信息 -->
<el-descriptions v-if="reportType === 'out'" title="统计信息" :column="3" border>
<el-descriptions-item label="总钢卷数量">{{ outSummary.totalCount }}</el-descriptions-item>
<el-descriptions-item label="总重">{{ outSummary.totalWeight }}t</el-descriptions-item>
<el-descriptions-item label="均重">{{ outSummary.avgWeight }}t</el-descriptions-item>
</el-descriptions>
<!-- loss 类型的统计信息 -->
<el-descriptions v-else-if="reportType === 'loss'" title="统计信息" :column="3" border>
<el-descriptions-item label="总钢卷数量">{{ lossSummary.totalCount }}</el-descriptions-item>
<el-descriptions-item label="总重">{{ lossSummary.totalWeight }}t</el-descriptions-item>
<el-descriptions-item label="均重">{{ lossSummary.avgWeight }}t</el-descriptions-item>
</el-descriptions>
<!-- team, day, month, year, all 类型的统计信息 -->
<template v-else>
<el-descriptions title="统计信息" :column="3" border>
<el-descriptions-item label="产出数量">{{ summary.outCount }}</el-descriptions-item>
<el-descriptions-item label="产出总重">{{ summary.outTotalWeight }}t</el-descriptions-item>
<el-descriptions-item label="产出均重">{{ summary.outAvgWeight }}t</el-descriptions-item>
<el-descriptions-item label="消耗数量">{{ summary.lossCount }}</el-descriptions-item>
<el-descriptions-item label="消耗总重">{{ summary.lossTotalWeight }}t</el-descriptions-item>
<el-descriptions-item label="消耗均重">{{ summary.lossAvgWeight }}t</el-descriptions-item>
<el-descriptions-item label="数量差值">{{ summary.countDiff }}</el-descriptions-item>
<el-descriptions-item label="总重差值">{{ summary.weightDiff }}</el-descriptions-item>
<el-descriptions-item label="均重差值">{{ summary.avgWeightDiff }}t</el-descriptions-item>
<!-- 成品率 -->
<el-descriptions-item label="成品率">{{ summary.passRate }}</el-descriptions-item>
<el-descriptions-item label="损耗率">{{ summary.lossRate }}</el-descriptions-item>
<!-- 异常率 -->
<el-descriptions-item label="异常率">{{ summary.abRate }}</el-descriptions-item>
<!-- 正品率 -->
<el-descriptions-item label="正品率">{{ summary.passRate2 }}</el-descriptions-item>
</el-descriptions>
<!-- 已处理M统计信息 -->
<el-descriptions title="已处理M统计信息" :column="3" border>
<el-descriptions-item label="产出数量">{{ mSummary.outCount }}</el-descriptions-item>
<el-descriptions-item label="产出总重">{{ mSummary.outTotalWeight }}t</el-descriptions-item>
<el-descriptions-item label="产出均重">{{ mSummary.outAvgWeight }}t</el-descriptions-item>
<el-descriptions-item label="消耗数量">{{ mSummary.lossCount }}</el-descriptions-item>
<el-descriptions-item label="消耗总重">{{ mSummary.lossTotalWeight }}t</el-descriptions-item>
<el-descriptions-item label="消耗均重">{{ mSummary.lossAvgWeight }}t</el-descriptions-item>
<el-descriptions-item label="数量差值">{{ mSummary.countDiff }}</el-descriptions-item>
<el-descriptions-item label="总重差值">{{ mSummary.weightDiff }}</el-descriptions-item>
<el-descriptions-item label="均重差值">{{ mSummary.avgWeightDiff }}t</el-descriptions-item>
<!-- 成品率 -->
<el-descriptions-item label="成品率">{{ mSummary.passRate }}</el-descriptions-item>
<el-descriptions-item label="损耗率">{{ mSummary.lossRate }}</el-descriptions-item>
<!-- 异常率 -->
<el-descriptions-item label="异常率">{{ mSummary.abRate }}</el-descriptions-item>
<!-- 正品率 -->
<el-descriptions-item label="正品率">{{ mSummary.passRate2 }}</el-descriptions-item>
</el-descriptions>
<!-- 异常统计team 类型显示 -->
<el-descriptions v-if="reportType === 'team'" title="异常统计" :column="4" border>
<el-descriptions-item v-for="item in abSummary" :key="item.label" :label="item.label">{{ item.value
}}</el-descriptions-item>
</el-descriptions>
<!-- 班组统计信息team 类型显示 -->
<template v-if="reportType === 'team'">
<el-descriptions title="班组统计信息" :column="3" border>
</el-descriptions>
<el-table :data="teamSummary" border>
<el-table-column label="班组" align="center" prop="team" />
<el-table-column label="产出数量" align="center" prop="outCount" />
<el-table-column label="产出总重" align="center" prop="outWeight" />
</el-table>
</template>
</template>
<!-- 明细信息和标签页 -->
<el-descriptions title="明细信息" :column="3" border>
</el-descriptions>
<el-tabs v-if="reportType !== 'out' && reportType !== 'loss'" v-model="activeTab">
<el-tab-pane label="投入钢卷" name="loss">
<coil-table :data="lossList" :columns="lossColumns" :loading="loading" height="calc(100vh - 360px)" />
</el-tab-pane>
<el-tab-pane label="产出钢卷" name="output">
<coil-table :data="outList" :columns="outputColumns" :loading="loading" height="calc(100vh - 360px)" />
</el-tab-pane>
</el-tabs>
<!-- out 类型只显示产出钢卷 -->
<coil-table v-else-if="reportType === 'out'" :columns="outputColumns" :data="outList"></coil-table>
<!-- loss 类型只显示投入钢卷 -->
<coil-table v-else-if="reportType === 'loss'" :columns="lossColumns" :data="lossList"></coil-table>
<el-dialog title="列设置" :visible.sync="settingVisible" width="50%">
<el-radio-group v-model="activeColumnConfig">
<el-radio-button label="coil-report-loss">投入明细配置</el-radio-button>
<el-radio-button label="coil-report-output">产出明细配置</el-radio-button>
</el-radio-group>
<columns-setting :reportType="activeColumnConfig"></columns-setting>
</el-dialog>
</div>
</template>
<script>
import { listCoilWithIds } from "@/api/wms/coil";
import {
listPendingAction,
} from '@/api/wms/pendingAction';
import MemoInput from "@/components/MemoInput";
import MutiSelect from "@/components/MutiSelect";
import ProductInfo from "@/components/KLPService/Renderer/ProductInfo";
import RawMaterialInfo from "@/components/KLPService/Renderer/RawMaterialInfo";
import CoilNo from "@/components/KLPService/Renderer/CoilNo.vue";
import WarehouseSelect from "@/components/KLPService/WarehouseSelect";
import { calcSummary, calcAbSummary, calcTeamSummary, calcMSummary } from "@/views/wms/report/js/calc";
import CoilTable from "@/views/wms/report/components/coilTable";
import ColumnsSetting from "@/views/wms/report/components/setting/columns";
import TimeRangePicker from "@/views/wms/report/components/timeRangePicker.vue";
import { saveReportFile } from "@/views/wms/report/js/reportFile";
export default {
name: 'MergeTemplate',
props: {
actionType: {
type: Number,
required: true
},
productionLine: {
type: String,
default: '',
},
reportType: {
type: String,
default: 'day', // day | month | year | all | team | out | loss
}
},
components: {
MemoInput,
MutiSelect,
ProductInfo,
RawMaterialInfo,
CoilNo,
WarehouseSelect,
CoilTable,
ColumnsSetting,
TimeRangePicker
},
dicts: ['product_coil_status', 'coil_material', 'coil_itemname', 'coil_manufacturer'],
data() {
// 工具函数:个位数补零
const addZero = (num) => num.toString().padStart(2, '0')
// 获取当前日期
const now = new Date()
const currentYear = `${now.getFullYear()}`
const currentMonth = `${now.getFullYear()}-${addZero(now.getMonth() + 1)}`
const currentDay = `${now.getFullYear()}-${addZero(now.getMonth() + 1)}-${addZero(now.getDate())}`
// 获取昨天的日期(用于 out 和 loss 类型的默认时间)
const yesterday = new Date(now)
yesterday.setDate(yesterday.getDate() - 1)
const yesYear = yesterday.getFullYear()
const yesMonth = addZero(yesterday.getMonth() + 1)
const yesDay = addZero(yesterday.getDate())
const defaultStartTime = `${yesYear}-${yesMonth}-${yesDay} 07:00:00`
const defaultEndTime = `${now.getFullYear()}-${addZero(now.getMonth() + 1)}-${addZero(now.getDate())} 07:00:00`
/**
* 生成指定日期/月份/年份的时间范围字符串
* @param {string} dateStr - 支持格式yyyy年份、yyyy-MM月份或 yyyy-MM-dd具体日期
* @returns {object} 包含start开始时间和end结束时间的对象
*/
const getDayTimeRange = (dateStr) => {
// 先校验输入格式是否合法
const yearPattern = /^\d{4}$/; // yyyy 正则
const monthPattern = /^\d{4}-\d{2}$/; // yyyy-MM 正则
const dayPattern = /^\d{4}-\d{2}-\d{2}$/; // yyyy-MM-dd 正则
let startDate, endDate;
if (yearPattern.test(dateStr)) {
// 处理 yyyy 格式:获取本年第一天和最后一天
startDate = `${dateStr}-01-01`;
endDate = `${dateStr}-12-31`;
} else if (monthPattern.test(dateStr)) {
// 处理 yyyy-MM 格式:获取本月第一天和最后一天
const [year, month] = dateStr.split('-').map(Number);
// 第一天yyyy-MM-01
startDate = `${dateStr}-01`;
// 最后一天:通过 new Date(year, month, 0) 计算month是原始月份比如2代表2月传2则取3月0日=2月最后一天
const lastDayOfMonth = new Date(year, month, 0).getDate();
endDate = `${dateStr}-${lastDayOfMonth.toString().padStart(2, '0')}`;
} else if (dayPattern.test(dateStr)) {
// 处理 yyyy-MM-dd 格式:直接使用传入的日期
startDate = dateStr;
endDate = dateStr;
} else {
throw new Error('输入格式错误,请传入 yyyy、yyyy-MM 或 yyyy-MM-dd 格式的字符串');
}
// 拼接时间部分
return {
start: `${startDate} 00:00:00`,
end: `${endDate} 23:59:59`
};
};
const { start, end } = getDayTimeRange(currentMonth);
return {
lossList: [],
outList: [],
activeTab: 'loss',
activeColumnConfig: 'coil-report-loss',
settingVisible: false,
loading: false,
dayDate: currentDay,
monthDate: currentMonth,
yearDate: currentYear,
defaultStartTime,
defaultEndTime,
getDayTimeRange,
queryParams: {
startTime: start,
endTime: end,
// byCreateTimeStart: start,
// byCreateTimeEnd: end,
enterCoilNo: '',
currentCoilNo: '',
warehouseId: '',
itemName: '',
itemSpecification: '',
itemMaterial: '',
itemManufacturer: '',
team: '',
pageSize: 9999,
pageNum: 1,
},
warehouseIds: [
'1988150099140866050',
'1988150263284953089',
'1988150545175736322',
'1988150150521090049',
'2019583656787259393',
'2019583325311414274',
'2019583429955104769',
'2019583137616310273',
],
lossColumns: [],
outputColumns: [],
actionIds: ''
}
},
computed: {
summary() {
return calcSummary(this.outList, this.lossList)
},
mSummary() {
return calcMSummary(this.outList, this.lossList)
},
abSummary() {
return calcAbSummary(this.outList)
},
teamSummary() {
const teamOutSummary = calcTeamSummary(this.outList);
const allTeams = [...new Set(Object.keys(teamOutSummary))];
return allTeams.map(team => {
const outData = teamOutSummary[team] || { count: 0, weight: 0 };
const formatWeight = (weight) => Number(weight || 0).toFixed(2);
return {
team: team,
outCount: outData.count,
outWeight: formatWeight(outData.weight)
};
});
},
// out 类型的统计
outSummary() {
const totalCount = this.outList.length;
const totalWeight = this.outList.reduce((acc, cur) => acc + parseFloat(cur.netWeight), 0);
const avgWeight = totalCount > 0 ? (totalWeight / totalCount).toFixed(2) : 0;
return {
totalCount,
totalWeight: totalWeight.toFixed(2),
avgWeight,
};
},
// loss 类型的统计
lossSummary() {
const totalCount = this.lossList.length;
const totalWeight = this.lossList.reduce((acc, cur) => acc + parseFloat(cur.netWeight), 0);
const avgWeight = totalCount > 0 ? (totalWeight / totalCount).toFixed(2) : 0;
return {
totalCount,
totalWeight: totalWeight.toFixed(2),
avgWeight,
};
}
},
watch: {
warehouseOptions: {
handler(newVal) {
if (newVal) {
this.warehouseIds = newVal.map(item => item.value);
}
},
immediate: true
}
},
created() {
this.initDateByReportType()
this.handleQuery()
this.loadColumns()
},
methods: {
// 根据 reportType 初始化日期
initDateByReportType() {
if (this.reportType === 'out' || this.reportType === 'loss') {
// out 和 loss 类型使用默认时间
this.queryParams.startTime = this.defaultStartTime;
this.queryParams.endTime = this.defaultEndTime;
} else if (this.reportType === 'team') {
// team 类型初始化 byCreateTimeStart 和 byCreateTimeEnd
const { start, end } = this.getDayTimeRange(this.dayDate);
this.queryParams.byCreateTimeStart = start;
this.queryParams.byCreateTimeEnd = end;
} else {
let dateStr;
if (this.reportType === 'year') {
dateStr = this.yearDate;
} else if (this.reportType === 'month') {
dateStr = this.monthDate;
} else if (this.reportType === 'day') {
dateStr = this.dayDate;
} else {
// all 类型,默认使用当前月份
dateStr = this.monthDate;
}
const { start, end } = this.getDayTimeRange(dateStr);
this.queryParams.startTime = start;
this.queryParams.endTime = end;
}
},
// 日期变更处理
handleDateChange() {
let dateStr;
if (this.reportType === 'year') {
dateStr = this.yearDate;
} else if (this.reportType === 'month') {
dateStr = this.monthDate;
} else if (this.reportType === 'day') {
dateStr = this.dayDate;
}
if (dateStr) {
const { start, end } = this.getDayTimeRange(dateStr);
this.queryParams.startTime = start;
this.queryParams.endTime = end;
this.handleQuery();
}
},
handleQuery() {
this.getList()
},
async getList() {
this.loading = true;
// 所有报表类型都使用原始的 listPendingAction 方式获取数据
const res = await listPendingAction({ ...this.queryParams, actionType: this.actionType, actionStatus: 2 });
// 获取两层数据
const lossIds = res.rows.filter(item => item.coilId).map(item => item.coilId);
// 使用new Set去重
const outIds = [...new Set(res.rows.filter(item => item.processedCoilIds).map(item => item.processedCoilIds))];
if (lossIds.length === 0 || outIds.length === 0) {
this.$message({
message: '查询结果为空',
type: 'warning'
})
this.loading = false;
return
}
const [lossRes, outRes] = await Promise.all([
listCoilWithIds({ ...this.queryParams, coilIds: lossIds.join(',') || '', startTime: '', endTime: '' }),
listCoilWithIds({ ...this.queryParams, coilIds: outIds.join(',') || '', startTime: '', endTime: '' }),
]);
// 根据 reportType 决定填充哪些数据
if (this.reportType === 'out') {
// 产出报表模式:只填充产出数据
this.outList = outRes.rows.map(item => {
const [thickness, width] = item.specification?.split('*') || []
return {
...item,
computedThickness: parseFloat(thickness),
computedWidth: parseFloat(width),
}
});
this.lossList = []; // 清空消耗数据
} else if (this.reportType === 'loss') {
// 消耗报表模式:只填充消耗数据
this.lossList = lossRes.rows.map(item => {
const [thickness, width] = item.specification?.split('*') || []
return {
...item,
computedThickness: parseFloat(thickness),
computedWidth: parseFloat(width),
}
});
this.outList = []; // 清空产出数据
} else {
// team/day/month/year/all 类型:填充两者数据
this.lossList = lossRes.rows.map(item => {
const [thickness, width] = item.specification?.split('*') || []
return {
...item,
computedThickness: parseFloat(thickness),
computedWidth: parseFloat(width),
}
});
this.outList = outRes.rows.map(item => {
const [thickness, width] = item.specification?.split('*') || []
return {
...item,
computedThickness: parseFloat(thickness),
computedWidth: parseFloat(width),
}
});
}
this.loading = false;
},
// 导出
exportData() {
if (this.outList.length === 0) {
this.$message.warning('暂无数据可导出')
return
}
// 根据 reportType 调整文件名
let fileName = `materialCoil_${new Date().getTime()}.xlsx`;
if (['day', 'month', 'year'].includes(this.reportType)) {
fileName = `materialCoil_${this.queryParams.date || ''}_${new Date().getTime()}.xlsx`;
}
this.download('wms/materialCoil/export', {
coilIds: this.outList.map(item => item.coilId).join(',')
}, fileName)
},
exportLossData() {
if (this.lossList.length === 0) {
this.$message.warning('暂无数据可导出')
return
}
// 根据 reportType 调整文件名
let fileName = `materialCoil_${new Date().getTime()}.xlsx`;
if (['day', 'month', 'year'].includes(this.reportType)) {
fileName = `materialCoil_${this.queryParams.date || ''}_${new Date().getTime()}.xlsx`;
}
if (this.reportType === 'loss' || this.reportType === 'team') {
this.download('wms/materialCoil/export', {
actionIds: this.actionIds
}, fileName)
} else {
this.download('wms/materialCoil/export', {
coilIds: this.lossList.map(item => item.coilId).join(',')
}, fileName)
}
},
// 保存产出报表
saveOutputReport() {
this.loading = true
// 根据 reportType 调整报表类型
let reportTypeStr = '产出报表';
if (this.reportType === 'day') {
reportTypeStr = '产出报表,日报表';
} else if (this.reportType === 'month') {
reportTypeStr = '产出报表,月报表';
} else if (this.reportType === 'year') {
reportTypeStr = '产出报表,年报表';
} else if (this.reportType === 'team') {
reportTypeStr = '产出报表,班报表';
}
saveReportFile(this.outList.map(item => item.coilId).join(','), {
reportParams: this.queryParams,
reportType: reportTypeStr,
productionLine: this.productionLine,
}).then(res => {
this.$message({
message: '保存成功',
type: 'success',
})
}).catch(err => {
this.$message({
message: '保存失败',
type: 'error',
})
}).finally(() => {
this.loading = false
})
},
// 保存消耗报表
saveLossReport() {
this.loading = true
// 根据 reportType 调整报表类型
let reportTypeStr = '消耗报表';
if (this.reportType === 'day') {
reportTypeStr = '消耗报表,日报表';
} else if (this.reportType === 'month') {
reportTypeStr = '消耗报表,月报表';
} else if (this.reportType === 'year') {
reportTypeStr = '消耗报表,年报表';
} else if (this.reportType === 'team') {
reportTypeStr = '消耗报表,班报表';
}
saveReportFile(this.lossList.map(item => item.coilId).join(','), {
reportParams: this.queryParams,
reportType: reportTypeStr,
productionLine: this.productionLine,
}).then(res => {
this.$message({
message: '保存成功',
type: 'success',
})
}).catch(err => {
this.$message({
message: '保存失败',
type: 'error',
})
}).finally(() => {
this.loading = false
})
},
// 加载列设置
loadColumns() {
this.lossColumns = JSON.parse(localStorage.getItem('preference-tableColumns-coil-report-loss') || '[]') || []
this.outputColumns = JSON.parse(localStorage.getItem('preference-tableColumns-coil-report-output') || '[]') || []
}
}
}
</script>
<style></style>

View File

@@ -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.WmsBonusConfigVo;
import com.klp.domain.bo.WmsBonusConfigBo;
import com.klp.service.IWmsBonusConfigService;
import com.klp.common.core.page.TableDataInfo;
/**
* 奖金分配
*
* @author klp
* @date 2026-05-07
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/wms/bonusConfig")
public class WmsBonusConfigController extends BaseController {
private final IWmsBonusConfigService iWmsBonusConfigService;
/**
* 查询奖金分配列表
*/
@GetMapping("/list")
public TableDataInfo<WmsBonusConfigVo> list(WmsBonusConfigBo bo, PageQuery pageQuery) {
return iWmsBonusConfigService.queryPageList(bo, pageQuery);
}
/**
* 导出奖金分配列表
*/
@Log(title = "奖金分配", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(WmsBonusConfigBo bo, HttpServletResponse response) {
List<WmsBonusConfigVo> list = iWmsBonusConfigService.queryList(bo);
ExcelUtil.exportExcel(list, "奖金分配", WmsBonusConfigVo.class, response);
}
/**
* 获取奖金分配详细信息
*
* @param configId 主键
*/
@GetMapping("/{configId}")
public R<WmsBonusConfigVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long configId) {
return R.ok(iWmsBonusConfigService.queryById(configId));
}
/**
* 新增奖金分配
*/
@Log(title = "奖金分配", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody WmsBonusConfigBo bo) {
return toAjax(iWmsBonusConfigService.insertByBo(bo));
}
/**
* 修改奖金分配
*/
@Log(title = "奖金分配", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody WmsBonusConfigBo bo) {
return toAjax(iWmsBonusConfigService.updateByBo(bo));
}
/**
* 删除奖金分配
*
* @param configIds 主键串
*/
@Log(title = "奖金分配", businessType = BusinessType.DELETE)
@DeleteMapping("/{configIds}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] configIds) {
return toAjax(iWmsBonusConfigService.deleteWithValidByIds(Arrays.asList(configIds), true));
}
}

View File

@@ -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.WmsBonusPoolVo;
import com.klp.domain.bo.WmsBonusPoolBo;
import com.klp.service.IWmsBonusPoolService;
import com.klp.common.core.page.TableDataInfo;
/**
* 奖金池
*
* @author klp
* @date 2026-05-07
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/wms/bonusPool")
public class WmsBonusPoolController extends BaseController {
private final IWmsBonusPoolService iWmsBonusPoolService;
/**
* 查询奖金池列表
*/
@GetMapping("/list")
public TableDataInfo<WmsBonusPoolVo> list(WmsBonusPoolBo bo, PageQuery pageQuery) {
return iWmsBonusPoolService.queryPageList(bo, pageQuery);
}
/**
* 导出奖金池列表
*/
@Log(title = "奖金池", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(WmsBonusPoolBo bo, HttpServletResponse response) {
List<WmsBonusPoolVo> list = iWmsBonusPoolService.queryList(bo);
ExcelUtil.exportExcel(list, "奖金池", WmsBonusPoolVo.class, response);
}
/**
* 获取奖金池详细信息
*
* @param poolId 主键
*/
@GetMapping("/{poolId}")
public R<WmsBonusPoolVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long poolId) {
return R.ok(iWmsBonusPoolService.queryById(poolId));
}
/**
* 新增奖金池
*/
@Log(title = "奖金池", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody WmsBonusPoolBo bo) {
return toAjax(iWmsBonusPoolService.insertByBo(bo));
}
/**
* 修改奖金池
*/
@Log(title = "奖金池", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody WmsBonusPoolBo bo) {
return toAjax(iWmsBonusPoolService.updateByBo(bo));
}
/**
* 删除奖金池
*
* @param poolIds 主键串
*/
@Log(title = "奖金池", businessType = BusinessType.DELETE)
@DeleteMapping("/{poolIds}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] poolIds) {
return toAjax(iWmsBonusPoolService.deleteWithValidByIds(Arrays.asList(poolIds), true));
}
}

View File

@@ -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.WmsPostCoeffConfigVo;
import com.klp.domain.bo.WmsPostCoeffConfigBo;
import com.klp.service.IWmsPostCoeffConfigService;
import com.klp.common.core.page.TableDataInfo;
/**
* 岗位系数配置
*
* @author klp
* @date 2026-05-07
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/wms/postCoeffConfig")
public class WmsPostCoeffConfigController extends BaseController {
private final IWmsPostCoeffConfigService iWmsPostCoeffConfigService;
/**
* 查询岗位系数配置列表
*/
@GetMapping("/list")
public TableDataInfo<WmsPostCoeffConfigVo> list(WmsPostCoeffConfigBo bo, PageQuery pageQuery) {
return iWmsPostCoeffConfigService.queryPageList(bo, pageQuery);
}
/**
* 导出岗位系数配置列表
*/
@Log(title = "岗位系数配置", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(WmsPostCoeffConfigBo bo, HttpServletResponse response) {
List<WmsPostCoeffConfigVo> list = iWmsPostCoeffConfigService.queryList(bo);
ExcelUtil.exportExcel(list, "岗位系数配置", WmsPostCoeffConfigVo.class, response);
}
/**
* 获取岗位系数配置详细信息
*
* @param configId 主键
*/
@GetMapping("/{configId}")
public R<WmsPostCoeffConfigVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long configId) {
return R.ok(iWmsPostCoeffConfigService.queryById(configId));
}
/**
* 新增岗位系数配置
*/
@Log(title = "岗位系数配置", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody WmsPostCoeffConfigBo bo) {
return toAjax(iWmsPostCoeffConfigService.insertByBo(bo));
}
/**
* 修改岗位系数配置
*/
@Log(title = "岗位系数配置", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody WmsPostCoeffConfigBo bo) {
return toAjax(iWmsPostCoeffConfigService.updateByBo(bo));
}
/**
* 删除岗位系数配置
*
* @param configIds 主键串
*/
@Log(title = "岗位系数配置", businessType = BusinessType.DELETE)
@DeleteMapping("/{configIds}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] configIds) {
return toAjax(iWmsPostCoeffConfigService.deleteWithValidByIds(Arrays.asList(configIds), true));
}
}

View File

@@ -0,0 +1,74 @@
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_bonus_config
*
* @author klp
* @date 2026-05-07
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("wms_bonus_config")
public class WmsBonusConfig extends BaseEntity {
private static final long serialVersionUID=1L;
/**
* 主键ID
*/
@TableId(value = "config_id")
private Long configId;
/**
* 奖金池ID关联bonus_pool.id
*/
private Long poolId;
/**
* 员工ID
*/
private Long empId;
/**
* 员工姓名
*/
private String empName;
/**
* 岗位
*/
private String postName;
/**
* 职务系数
*/
private BigDecimal dutyCoeff;
/**
* 基本系数
*/
private BigDecimal baseCoeff;
/**
* 主任加减系数
*/
private BigDecimal adjustCoeff;
/**
* 分配基数(底薪/元)
*/
private BigDecimal allocBase;
/**
* 分配奖金金额
*/
private BigDecimal bonusAmount;
/**
* 备注
*/
private String remark;
/**
* 删除标识 0正常 2删除
*/
@TableLogic
private Long delFlag;
}

View File

@@ -0,0 +1,52 @@
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_bonus_pool
*
* @author klp
* @date 2026-05-07
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("wms_bonus_pool")
public class WmsBonusPool extends BaseEntity {
private static final long serialVersionUID=1L;
/**
* 主键ID
*/
@TableId(value = "pool_id")
private Long poolId;
/**
* 产线
*/
private String productionLine;
/**
* 奖金时间/统计时间
*/
private Date bonusTime;
/**
* 奖金池总金额
*/
private BigDecimal totalBonus;
/**
* 备注
*/
private String remark;
/**
* 删除标识 0正常 2删除
*/
@TableLogic
private Long delFlag;
}

View File

@@ -0,0 +1,50 @@
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_post_coeff_config
*
* @author klp
* @date 2026-05-07
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("wms_post_coeff_config")
public class WmsPostCoeffConfig extends BaseEntity {
private static final long serialVersionUID=1L;
/**
* 主键ID
*/
@TableId(value = "config_id")
private Long configId;
/**
* 岗位名称
*/
private String postName;
/**
* 职务系数
*/
private BigDecimal dutyCoeff;
/**
* 基本系数
*/
private BigDecimal baseCoeff;
/**
* 备注
*/
private String remark;
/**
* 删除标识 0正常 2删除
*/
@TableLogic
private Long delFlag;
}

View File

@@ -0,0 +1,77 @@
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_bonus_config
*
* @author klp
* @date 2026-05-07
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class WmsBonusConfigBo extends BaseEntity {
/**
* 主键ID
*/
private Long configId;
/**
* 奖金池ID关联bonus_pool.id
*/
private Long poolId;
/**
* 员工ID
*/
private Long empId;
/**
* 员工姓名
*/
private String empName;
/**
* 岗位
*/
private String postName;
/**
* 职务系数
*/
private BigDecimal dutyCoeff;
/**
* 基本系数
*/
private BigDecimal baseCoeff;
/**
* 主任加减系数
*/
private BigDecimal adjustCoeff;
/**
* 分配基数(底薪/元)
*/
private BigDecimal allocBase;
/**
* 分配奖金金额
*/
private BigDecimal bonusAmount;
/**
* 备注
*/
private String remark;
}

View File

@@ -0,0 +1,49 @@
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 com.fasterxml.jackson.annotation.JsonFormat;
/**
* 奖金池业务对象 wms_bonus_pool
*
* @author klp
* @date 2026-05-07
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class WmsBonusPoolBo extends BaseEntity {
/**
* 主键ID
*/
private Long poolId;
/**
* 产线
*/
private String productionLine;
/**
* 奖金时间/统计时间
*/
private Date bonusTime;
/**
* 奖金池总金额
*/
private BigDecimal totalBonus;
/**
* 备注
*/
private String remark;
}

View File

@@ -0,0 +1,47 @@
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_post_coeff_config
*
* @author klp
* @date 2026-05-07
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class WmsPostCoeffConfigBo extends BaseEntity {
/**
* 主键ID
*/
private Long configId;
/**
* 岗位名称
*/
private String postName;
/**
* 职务系数
*/
private BigDecimal dutyCoeff;
/**
* 基本系数
*/
private BigDecimal baseCoeff;
/**
* 备注
*/
private String remark;
}

View File

@@ -0,0 +1,91 @@
package com.klp.domain.vo;
import java.math.BigDecimal;
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_bonus_config
*
* @author klp
* @date 2026-05-07
*/
@Data
@ExcelIgnoreUnannotated
public class WmsBonusConfigVo {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ExcelProperty(value = "主键ID")
private Long configId;
/**
* 奖金池ID关联bonus_pool.id
*/
@ExcelProperty(value = "奖金池ID", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "关=联bonus_pool.id")
private Long poolId;
/**
* 员工ID
*/
@ExcelProperty(value = "员工ID")
private Long empId;
/**
* 员工姓名
*/
@ExcelProperty(value = "员工姓名")
private String empName;
/**
* 岗位
*/
@ExcelProperty(value = "岗位")
private String postName;
/**
* 职务系数
*/
@ExcelProperty(value = "职务系数")
private BigDecimal dutyCoeff;
/**
* 基本系数
*/
@ExcelProperty(value = "基本系数")
private BigDecimal baseCoeff;
/**
* 主任加减系数
*/
@ExcelProperty(value = "主任加减系数")
private BigDecimal adjustCoeff;
/**
* 分配基数(底薪/元)
*/
@ExcelProperty(value = "分配基数(底薪/元)")
private BigDecimal allocBase;
/**
* 分配奖金金额
*/
@ExcelProperty(value = "分配奖金金额")
private BigDecimal bonusAmount;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}

View File

@@ -0,0 +1,56 @@
package com.klp.domain.vo;
import java.math.BigDecimal;
import java.util.Date;
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_bonus_pool
*
* @author klp
* @date 2026-05-07
*/
@Data
@ExcelIgnoreUnannotated
public class WmsBonusPoolVo {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ExcelProperty(value = "主键ID")
private Long poolId;
/**
* 产线
*/
@ExcelProperty(value = "产线")
private String productionLine;
/**
* 奖金时间/统计时间
*/
@ExcelProperty(value = "奖金时间/统计时间")
private Date bonusTime;
/**
* 奖金池总金额
*/
@ExcelProperty(value = "奖金池总金额")
private BigDecimal totalBonus;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}

View File

@@ -0,0 +1,203 @@
package com.klp.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
/**
* 钢卷异常报表导出DTO - EasyExcel版本
* 使用EasyExcel注解实现O(n)复杂度的单元格合并
*
* @author Joshi
* @date 2026-05-07
*/
@Data
@ContentRowHeight(20)
@HeadRowHeight(24)
@ColumnWidth(15)
public class WmsCoilAbnormalExportVo {
// 钢卷基本信息前25列
@ExcelProperty("类型")
@ColumnWidth(12)
private String itemType;
@ExcelProperty("逻辑库区")
@ColumnWidth(12)
private String warehouseName;
@ExcelProperty("实际库区")
@ColumnWidth(12)
private String actualWarehouseName;
@ExcelProperty("入场卷号")
@ColumnWidth(15)
private String enterCoilNo;
@ExcelProperty("厂家卷号")
@ColumnWidth(15)
private String supplierCoilNo;
@ExcelProperty("成品卷号")
@ColumnWidth(15)
private String currentCoilNo;
@ExcelProperty("日期")
@ColumnWidth(20)
private String createTime;
@ExcelProperty("重量")
@ColumnWidth(12)
private String netWeight;
@ExcelProperty("用途")
@ColumnWidth(12)
private String businessPurpose;
@ExcelProperty("切边要求")
@ColumnWidth(12)
private String trimmingRequirement;
@ExcelProperty("包装种类")
@ColumnWidth(12)
private String packagingRequirement;
@ExcelProperty("产品质量")
@ColumnWidth(12)
private String qualityStatus;
@ExcelProperty("原料材质")
@ColumnWidth(12)
private String packingStatus;
@ExcelProperty("库存状态")
@ColumnWidth(12)
private String status;
@ExcelProperty("备注")
@ColumnWidth(20)
private String remark;
@ExcelProperty("名称")
@ColumnWidth(15)
private String itemName;
@ExcelProperty("规格")
@ColumnWidth(20)
private String specification;
@ExcelProperty("长度")
@ColumnWidth(12)
private String length;
@ExcelProperty("材质")
@ColumnWidth(12)
private String material;
@ExcelProperty("厂家")
@ColumnWidth(15)
private String manufacturer;
@ExcelProperty("表面处理")
@ColumnWidth(12)
private String surfaceTreatmentDesc;
@ExcelProperty("锌层")
@ColumnWidth(12)
private String zincLayer;
@ExcelProperty("物品ID")
@ColumnWidth(12)
private String itemId;
@ExcelProperty("操作完成时间")
@ColumnWidth(20)
private String actionCompleteTime;
@ExcelProperty("调拨类型")
@ColumnWidth(12)
private String transferType;
// 改判原因第26列
@ExcelProperty("改判原因")
@ColumnWidth(25)
private String rejudgeReason;
// 异常信息后17列
@ExcelProperty("产线")
@ColumnWidth(12)
private String productionLine;
@ExcelProperty("位置")
@ColumnWidth(12)
private String position;
@ExcelProperty("长度坐标")
@ColumnWidth(12)
private String abnormalLength;
@ExcelProperty("缺陷开始位置")
@ColumnWidth(15)
private String startPosition;
@ExcelProperty("缺陷结束位置")
@ColumnWidth(15)
private String endPosition;
@ExcelProperty("缺陷代码")
@ColumnWidth(12)
private String defectCode;
@ExcelProperty("缺陷类型")
@ColumnWidth(12)
private String defectType;
@ExcelProperty("缺陷率")
@ColumnWidth(12)
private String defectRate;
@ExcelProperty("缺陷重量")
@ColumnWidth(12)
private String defectWeight;
@ExcelProperty("程度")
@ColumnWidth(10)
private String degree;
@ExcelProperty("判级")
@ColumnWidth(10)
private String judgeLevel;
@ExcelProperty("判级人")
@ColumnWidth(12)
private String judgeBy;
@ExcelProperty("判级时间")
@ColumnWidth(20)
private String judgeTime;
@ExcelProperty("主标记")
@ColumnWidth(12)
private String mainMark;
@ExcelProperty("整卷标记")
@ColumnWidth(12)
private String wholeCoilMark;
@ExcelProperty("异常备注")
@ColumnWidth(20)
private String abnormalRemark;
@ExcelProperty("板面")
@ColumnWidth(10)
private String plateSurface;
/**
* 钢卷ID用于合并单元格的标识隐藏列
*/
@ExcelIgnore
private Long coilId;
}

View File

@@ -0,0 +1,54 @@
package com.klp.domain.vo;
import java.math.BigDecimal;
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_post_coeff_config
*
* @author klp
* @date 2026-05-07
*/
@Data
@ExcelIgnoreUnannotated
public class WmsPostCoeffConfigVo {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ExcelProperty(value = "主键ID")
private Long configId;
/**
* 岗位名称
*/
@ExcelProperty(value = "岗位名称")
private String postName;
/**
* 职务系数
*/
@ExcelProperty(value = "职务系数")
private BigDecimal dutyCoeff;
/**
* 基本系数
*/
@ExcelProperty(value = "基本系数")
private BigDecimal baseCoeff;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}

View File

@@ -0,0 +1,15 @@
package com.klp.mapper;
import com.klp.domain.WmsBonusConfig;
import com.klp.domain.vo.WmsBonusConfigVo;
import com.klp.common.core.mapper.BaseMapperPlus;
/**
* 奖金分配Mapper接口
*
* @author klp
* @date 2026-05-07
*/
public interface WmsBonusConfigMapper extends BaseMapperPlus<WmsBonusConfigMapper, WmsBonusConfig, WmsBonusConfigVo> {
}

View File

@@ -0,0 +1,15 @@
package com.klp.mapper;
import com.klp.domain.WmsBonusPool;
import com.klp.domain.vo.WmsBonusPoolVo;
import com.klp.common.core.mapper.BaseMapperPlus;
/**
* 奖金池Mapper接口
*
* @author klp
* @date 2026-05-07
*/
public interface WmsBonusPoolMapper extends BaseMapperPlus<WmsBonusPoolMapper, WmsBonusPool, WmsBonusPoolVo> {
}

View File

@@ -0,0 +1,15 @@
package com.klp.mapper;
import com.klp.domain.WmsPostCoeffConfig;
import com.klp.domain.vo.WmsPostCoeffConfigVo;
import com.klp.common.core.mapper.BaseMapperPlus;
/**
* 岗位系数配置Mapper接口
*
* @author klp
* @date 2026-05-07
*/
public interface WmsPostCoeffConfigMapper extends BaseMapperPlus<WmsPostCoeffConfigMapper, WmsPostCoeffConfig, WmsPostCoeffConfigVo> {
}

View File

@@ -0,0 +1,49 @@
package com.klp.service;
import com.klp.domain.WmsBonusConfig;
import com.klp.domain.vo.WmsBonusConfigVo;
import com.klp.domain.bo.WmsBonusConfigBo;
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-05-07
*/
public interface IWmsBonusConfigService {
/**
* 查询奖金分配
*/
WmsBonusConfigVo queryById(Long configId);
/**
* 查询奖金分配列表
*/
TableDataInfo<WmsBonusConfigVo> queryPageList(WmsBonusConfigBo bo, PageQuery pageQuery);
/**
* 查询奖金分配列表
*/
List<WmsBonusConfigVo> queryList(WmsBonusConfigBo bo);
/**
* 新增奖金分配
*/
Boolean insertByBo(WmsBonusConfigBo bo);
/**
* 修改奖金分配
*/
Boolean updateByBo(WmsBonusConfigBo bo);
/**
* 校验并批量删除奖金分配信息
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@@ -0,0 +1,49 @@
package com.klp.service;
import com.klp.domain.WmsBonusPool;
import com.klp.domain.vo.WmsBonusPoolVo;
import com.klp.domain.bo.WmsBonusPoolBo;
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-05-07
*/
public interface IWmsBonusPoolService {
/**
* 查询奖金池
*/
WmsBonusPoolVo queryById(Long poolId);
/**
* 查询奖金池列表
*/
TableDataInfo<WmsBonusPoolVo> queryPageList(WmsBonusPoolBo bo, PageQuery pageQuery);
/**
* 查询奖金池列表
*/
List<WmsBonusPoolVo> queryList(WmsBonusPoolBo bo);
/**
* 新增奖金池
*/
Boolean insertByBo(WmsBonusPoolBo bo);
/**
* 修改奖金池
*/
Boolean updateByBo(WmsBonusPoolBo bo);
/**
* 校验并批量删除奖金池信息
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@@ -0,0 +1,49 @@
package com.klp.service;
import com.klp.domain.WmsPostCoeffConfig;
import com.klp.domain.vo.WmsPostCoeffConfigVo;
import com.klp.domain.bo.WmsPostCoeffConfigBo;
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-05-07
*/
public interface IWmsPostCoeffConfigService {
/**
* 查询岗位系数配置
*/
WmsPostCoeffConfigVo queryById(Long configId);
/**
* 查询岗位系数配置列表
*/
TableDataInfo<WmsPostCoeffConfigVo> queryPageList(WmsPostCoeffConfigBo bo, PageQuery pageQuery);
/**
* 查询岗位系数配置列表
*/
List<WmsPostCoeffConfigVo> queryList(WmsPostCoeffConfigBo bo);
/**
* 新增岗位系数配置
*/
Boolean insertByBo(WmsPostCoeffConfigBo bo);
/**
* 修改岗位系数配置
*/
Boolean updateByBo(WmsPostCoeffConfigBo bo);
/**
* 校验并批量删除岗位系数配置信息
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@@ -0,0 +1,117 @@
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.WmsBonusConfigBo;
import com.klp.domain.vo.WmsBonusConfigVo;
import com.klp.domain.WmsBonusConfig;
import com.klp.mapper.WmsBonusConfigMapper;
import com.klp.service.IWmsBonusConfigService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 奖金分配Service业务层处理
*
* @author klp
* @date 2026-05-07
*/
@RequiredArgsConstructor
@Service
public class WmsBonusConfigServiceImpl implements IWmsBonusConfigService {
private final WmsBonusConfigMapper baseMapper;
/**
* 查询奖金分配
*/
@Override
public WmsBonusConfigVo queryById(Long configId){
return baseMapper.selectVoById(configId);
}
/**
* 查询奖金分配列表
*/
@Override
public TableDataInfo<WmsBonusConfigVo> queryPageList(WmsBonusConfigBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<WmsBonusConfig> lqw = buildQueryWrapper(bo);
Page<WmsBonusConfigVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询奖金分配列表
*/
@Override
public List<WmsBonusConfigVo> queryList(WmsBonusConfigBo bo) {
LambdaQueryWrapper<WmsBonusConfig> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<WmsBonusConfig> buildQueryWrapper(WmsBonusConfigBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<WmsBonusConfig> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getPoolId() != null, WmsBonusConfig::getPoolId, bo.getPoolId());
lqw.eq(bo.getEmpId() != null, WmsBonusConfig::getEmpId, bo.getEmpId());
lqw.like(StringUtils.isNotBlank(bo.getEmpName()), WmsBonusConfig::getEmpName, bo.getEmpName());
lqw.like(StringUtils.isNotBlank(bo.getPostName()), WmsBonusConfig::getPostName, bo.getPostName());
lqw.eq(bo.getDutyCoeff() != null, WmsBonusConfig::getDutyCoeff, bo.getDutyCoeff());
lqw.eq(bo.getBaseCoeff() != null, WmsBonusConfig::getBaseCoeff, bo.getBaseCoeff());
lqw.eq(bo.getAdjustCoeff() != null, WmsBonusConfig::getAdjustCoeff, bo.getAdjustCoeff());
lqw.eq(bo.getAllocBase() != null, WmsBonusConfig::getAllocBase, bo.getAllocBase());
lqw.eq(bo.getBonusAmount() != null, WmsBonusConfig::getBonusAmount, bo.getBonusAmount());
return lqw;
}
/**
* 新增奖金分配
*/
@Override
public Boolean insertByBo(WmsBonusConfigBo bo) {
WmsBonusConfig add = BeanUtil.toBean(bo, WmsBonusConfig.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setConfigId(add.getConfigId());
}
return flag;
}
/**
* 修改奖金分配
*/
@Override
public Boolean updateByBo(WmsBonusConfigBo bo) {
WmsBonusConfig update = BeanUtil.toBean(bo, WmsBonusConfig.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(WmsBonusConfig entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 批量删除奖金分配
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
}

View File

@@ -0,0 +1,111 @@
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.klp.common.utils.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.klp.domain.bo.WmsBonusPoolBo;
import com.klp.domain.vo.WmsBonusPoolVo;
import com.klp.domain.WmsBonusPool;
import com.klp.mapper.WmsBonusPoolMapper;
import com.klp.service.IWmsBonusPoolService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 奖金池Service业务层处理
*
* @author klp
* @date 2026-05-07
*/
@RequiredArgsConstructor
@Service
public class WmsBonusPoolServiceImpl implements IWmsBonusPoolService {
private final WmsBonusPoolMapper baseMapper;
/**
* 查询奖金池
*/
@Override
public WmsBonusPoolVo queryById(Long poolId){
return baseMapper.selectVoById(poolId);
}
/**
* 查询奖金池列表
*/
@Override
public TableDataInfo<WmsBonusPoolVo> queryPageList(WmsBonusPoolBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<WmsBonusPool> lqw = buildQueryWrapper(bo);
Page<WmsBonusPoolVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询奖金池列表
*/
@Override
public List<WmsBonusPoolVo> queryList(WmsBonusPoolBo bo) {
LambdaQueryWrapper<WmsBonusPool> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<WmsBonusPool> buildQueryWrapper(WmsBonusPoolBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<WmsBonusPool> lqw = Wrappers.lambdaQuery();
lqw.eq(StringUtils.isNotBlank(bo.getProductionLine()), WmsBonusPool::getProductionLine, bo.getProductionLine());
lqw.eq(bo.getBonusTime() != null, WmsBonusPool::getBonusTime, bo.getBonusTime());
lqw.eq(bo.getTotalBonus() != null, WmsBonusPool::getTotalBonus, bo.getTotalBonus());
return lqw;
}
/**
* 新增奖金池
*/
@Override
public Boolean insertByBo(WmsBonusPoolBo bo) {
WmsBonusPool add = BeanUtil.toBean(bo, WmsBonusPool.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setPoolId(add.getPoolId());
}
return flag;
}
/**
* 修改奖金池
*/
@Override
public Boolean updateByBo(WmsBonusPoolBo bo) {
WmsBonusPool update = BeanUtil.toBean(bo, WmsBonusPool.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(WmsBonusPool entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 批量删除奖金池
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
}

View File

@@ -45,11 +45,9 @@ import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import com.alibaba.excel.EasyExcel;
/**
* 钢卷物料表Service业务层处理
@@ -5333,7 +5331,7 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
" GROUP BY coil_id" +
") t2 ON t1.coil_id = t2.coil_id AND t1.create_time = t2.max_time " +
"WHERE t1.del_flag = '0' AND t1.rejudge_reason IS NOT NULL";
List<Map<String, Object>> results = wmsCoilQualityRejudgeMapper.selectMapsBySql(sql);
if (results != null) {
for (Map<String, Object> result : results) {
@@ -5346,212 +5344,129 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
}
}
// 5. 构建导出数据(扁平化:一个钢卷+一个异常 = 一行)
List<WmsCoilAbnormalExportRow> exportData = new ArrayList<>();
// 5. 构建EasyExcel导出数据 - O(n)复杂度
List<WmsCoilAbnormalExportVo> exportData = new ArrayList<>();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
for (WmsMaterialCoilVo coil : coilList) {
Long coilId = coil.getCoilId();
List<WmsCoilAbnormal> abnormalList = abnormalMap.getOrDefault(coilId, new ArrayList<>());
String rejudgeReason = rejudgeReasonMap.get(coilId);
if (abnormalList.isEmpty()) {
WmsCoilAbnormalExportRow row = new WmsCoilAbnormalExportRow();
row.setCoil(coil);
row.setRejudgeReason(rejudgeReason);
row.setAbnormal(null);
exportData.add(row);
// 无异常信息的钢卷,创建一行空异常数据
WmsCoilAbnormalExportVo dto = createExportVo(coil, rejudgeReason, null, sdf);
dto.setCoilId(coilId);
exportData.add(dto);
} else {
// 有异常信息的钢卷,每个异常创建一行
for (WmsCoilAbnormal abnormal : abnormalList) {
WmsCoilAbnormalExportRow row = new WmsCoilAbnormalExportRow();
row.setCoil(coil);
row.setRejudgeReason(rejudgeReason);
row.setAbnormal(abnormal);
exportData.add(row);
WmsCoilAbnormalExportVo dto = createExportVo(coil, rejudgeReason, abnormal, sdf);
dto.setCoilId(coilId);
exportData.add(dto);
}
}
}
// 6. 导出Excel
try (Workbook wb = new XSSFWorkbook()) {
Sheet sheet = wb.createSheet("异常报表");
int r = 0;
// 标题行
Row titleRow = sheet.createRow(r++);
titleRow.setHeightInPoints(36f);
Cell titleCell = titleRow.createCell(0);
titleCell.setCellValue("钢卷异常报表");
CellStyle titleStyle = wb.createCellStyle();
titleStyle.setAlignment(HorizontalAlignment.CENTER);
titleStyle.setVerticalAlignment(VerticalAlignment.CENTER);
Font titleFont = wb.createFont();
titleFont.setBold(true);
titleFont.setFontHeightInPoints((short) 15);
titleStyle.setFont(titleFont);
CellRangeAddress titleRegion = new CellRangeAddress(0, 0, 0, 41);
sheet.addMergedRegion(titleRegion);
for (int i = titleRegion.getFirstColumn(); i <= titleRegion.getLastColumn(); i++) {
Cell cell = titleRow.getCell(i);
if (cell == null) cell = titleRow.createCell(i);
cell.setCellStyle(titleStyle);
}
// 表头
String[] headers = {
"类型", "逻辑库区", "实际库区", "入场卷号", "厂家卷号", "成品卷号", "日期",
"重量", "用途", "切边要求", "包装种类", "产品质量", "原料材质",
"库存状态", "备注", "名称", "规格", "长度", "材质", "厂家",
"表面处理", "锌层", "物品ID", "操作完成时间", "调拨类型",
"改判原因",
"产线", "位置", "长度坐标", "缺陷开始位置", "缺陷结束位置",
"缺陷代码", "缺陷类型", "缺陷率", "缺陷重量", "程度", "判级",
"判级人", "判级时间", "主标记", "整卷标记", "异常备注", "板面"
};
CellStyle headStyle = wb.createCellStyle();
Font headFont = wb.createFont();
headFont.setBold(true);
headStyle.setFont(headFont);
headStyle.setAlignment(HorizontalAlignment.CENTER);
headStyle.setVerticalAlignment(VerticalAlignment.CENTER);
headStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
headStyle.setFillForegroundColor(IndexedColors.PALE_BLUE.getIndex());
headStyle.setWrapText(true);
Row headRow = sheet.createRow(r++);
headRow.setHeightInPoints(24);
for (int i = 0; i < headers.length; i++) {
Cell cell = headRow.createCell(i);
cell.setCellValue(headers[i]);
cell.setCellStyle(headStyle);
}
// 数据行样式
CellStyle centerStyle = wb.createCellStyle();
centerStyle.setAlignment(HorizontalAlignment.CENTER);
centerStyle.setVerticalAlignment(VerticalAlignment.CENTER);
// 填充数据
int dataStartRow = r;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
for (WmsCoilAbnormalExportRow rowData : exportData) {
WmsMaterialCoilVo coil = rowData.getCoil();
WmsCoilAbnormal abnormal = rowData.getAbnormal();
String rejudgeReason = rowData.getRejudgeReason();
Row row = sheet.createRow(r++);
int cc = 0;
// 钢卷信息前25列
row.createCell(cc++).setCellValue(coil.getItemType() != null ? coil.getItemType() : "");
row.createCell(cc++).setCellValue(coil.getWarehouseName() != null ? coil.getWarehouseName() : "");
row.createCell(cc++).setCellValue(coil.getActualWarehouseName() != null ? coil.getActualWarehouseName() : "");
row.createCell(cc++).setCellValue(coil.getEnterCoilNo() != null ? coil.getEnterCoilNo() : "");
row.createCell(cc++).setCellValue(coil.getSupplierCoilNo() != null ? coil.getSupplierCoilNo() : "");
row.createCell(cc++).setCellValue(coil.getCurrentCoilNo() != null ? coil.getCurrentCoilNo() : "");
row.createCell(cc++).setCellValue(coil.getCreateTime() != null ? sdf.format(coil.getCreateTime()) : "");
row.createCell(cc++).setCellValue(coil.getNetWeight() != null ? coil.getNetWeight().toString() : "");
row.createCell(cc++).setCellValue(coil.getBusinessPurpose() != null ? coil.getBusinessPurpose() : "");
row.createCell(cc++).setCellValue(coil.getTrimmingRequirement() != null ? coil.getTrimmingRequirement() : "");
row.createCell(cc++).setCellValue(coil.getPackagingRequirement() != null ? coil.getPackagingRequirement() : "");
row.createCell(cc++).setCellValue(coil.getQualityStatus() != null ? coil.getQualityStatus() : "");
row.createCell(cc++).setCellValue(coil.getPackingStatus() != null ? coil.getPackingStatus() : "");
row.createCell(cc++).setCellValue(coil.getStatus() != null ? coil.getStatus().toString() : "");
row.createCell(cc++).setCellValue(coil.getRemark() != null ? coil.getRemark() : "");
row.createCell(cc++).setCellValue(coil.getItemName() != null ? coil.getItemName() : "");
row.createCell(cc++).setCellValue(coil.getSpecification() != null ? coil.getSpecification() : "");
row.createCell(cc++).setCellValue(coil.getLength() != null ? coil.getLength().toString() : "");
row.createCell(cc++).setCellValue(coil.getMaterial() != null ? coil.getMaterial() : "");
row.createCell(cc++).setCellValue(coil.getManufacturer() != null ? coil.getManufacturer() : "");
row.createCell(cc++).setCellValue(coil.getSurfaceTreatmentDesc() != null ? coil.getSurfaceTreatmentDesc() : "");
row.createCell(cc++).setCellValue(coil.getZincLayer() != null ? coil.getZincLayer() : "");
row.createCell(cc++).setCellValue(coil.getItemId() != null ? coil.getItemId().toString() : "");
row.createCell(cc++).setCellValue(coil.getActionCompleteTime() != null ? sdf.format(coil.getActionCompleteTime()) : "");
row.createCell(cc++).setCellValue(coil.getTransferType() != null ? coil.getTransferType() : "");
// 改判原因
row.createCell(cc++).setCellValue(rejudgeReason != null ? rejudgeReason : "");
// 异常信息
if (abnormal != null) {
row.createCell(cc++).setCellValue(abnormal.getProductionLine() != null ? abnormal.getProductionLine() : "");
row.createCell(cc++).setCellValue(abnormal.getPosition() != null ? abnormal.getPosition() : "");
row.createCell(cc++).setCellValue(abnormal.getLength() != null ? abnormal.getLength().toString() : "");
row.createCell(cc++).setCellValue(abnormal.getStartPosition() != null ? abnormal.getStartPosition().toString() : "");
row.createCell(cc++).setCellValue(abnormal.getEndPosition() != null ? abnormal.getEndPosition().toString() : "");
row.createCell(cc++).setCellValue(abnormal.getDefectCode() != null ? abnormal.getDefectCode() : "");
row.createCell(cc++).setCellValue(abnormal.getDefectType() != null ? abnormal.getDefectType() : "");
row.createCell(cc++).setCellValue(abnormal.getDefectRate() != null ? abnormal.getDefectRate().toString() : "");
row.createCell(cc++).setCellValue(abnormal.getDefectWeight() != null ? abnormal.getDefectWeight().toString() : "");
row.createCell(cc++).setCellValue(abnormal.getDegree() != null ? abnormal.getDegree() : "");
row.createCell(cc++).setCellValue(abnormal.getJudgeLevel() != null ? abnormal.getJudgeLevel() : "");
row.createCell(cc++).setCellValue(abnormal.getJudgeBy() != null ? abnormal.getJudgeBy() : "");
row.createCell(cc++).setCellValue(abnormal.getJudgeTime() != null ? sdf.format(abnormal.getJudgeTime()) : "");
row.createCell(cc++).setCellValue(abnormal.getMainMark() != null ? abnormal.getMainMark().toString() : "");
row.createCell(cc++).setCellValue(abnormal.getWholeCoilMark() != null ? abnormal.getWholeCoilMark().toString() : "");
row.createCell(cc++).setCellValue(abnormal.getRemark() != null ? abnormal.getRemark() : "");
row.createCell(cc++).setCellValue(abnormal.getPlateSurface() != null ? abnormal.getPlateSurface() : "");
} else {
for (int j = 0; j < 17; j++) row.createCell(cc++).setCellValue("");
}
}
// 合并钢卷信息列前26列25列钢卷信息 + 1列改判原因
int currentRow = dataStartRow;
while (currentRow < r) {
Long currentCoilId = exportData.get(currentRow - dataStartRow).getCoil().getCoilId();
int startRow = currentRow;
int endRow = currentRow;
while (endRow < r && exportData.get(endRow - dataStartRow).getCoil().getCoilId().equals(currentCoilId)) {
endRow++;
}
if (endRow - startRow > 1) {
for (int col = 0; col < 26; col++) {
sheet.addMergedRegion(new CellRangeAddress(startRow, endRow - 1, col, col));
}
}
// 设置居中样式
for (int rowIdx = startRow; rowIdx < endRow; rowIdx++) {
Row row = sheet.getRow(rowIdx);
if (row != null) {
for (int col = 0; col < 26; col++) {
Cell cell = row.getCell(col);
if (cell != null) cell.setCellStyle(centerStyle);
}
}
}
currentRow = endRow;
}
// 自适应列宽
for (int i = 0; i < headers.length; i++) {
sheet.autoSizeColumn(i, true);
int w = sheet.getColumnWidth(i);
sheet.setColumnWidth(i, Math.min(Math.max(w, 3000), 12000));
}
// 输出
// 6. 使用EasyExcel导出 - O(n)复杂度,瞬间完成
try {
// 设置响应头
String filename = "abnormal_report_" + System.currentTimeMillis() + ".xlsx";
String encoded = URLEncoder.encode(filename, StandardCharsets.UTF_8.name());
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + encoded);
try (ServletOutputStream os = response.getOutputStream()) {
wb.write(os);
os.flush();
}
// 使用EasyExcel写入正常导出
EasyExcel.write(response.getOutputStream(), WmsCoilAbnormalExportVo.class)
.sheet("异常报表")
.doWrite(exportData);
} catch (IOException e) {
throw new RuntimeException("导出失败:" + e.getMessage());
}
}
/*
* 创建导出DTO对象
*/
private WmsCoilAbnormalExportVo createExportVo(WmsMaterialCoilVo coil, String rejudgeReason,
WmsCoilAbnormal abnormal, SimpleDateFormat sdf) {
WmsCoilAbnormalExportVo dto = new WmsCoilAbnormalExportVo();
// 钢卷基本信息前25列
dto.setItemType(coil.getItemType() != null ? coil.getItemType() : "");
dto.setWarehouseName(coil.getWarehouseName() != null ? coil.getWarehouseName() : "");
dto.setActualWarehouseName(coil.getActualWarehouseName() != null ? coil.getActualWarehouseName() : "");
dto.setEnterCoilNo(coil.getEnterCoilNo() != null ? coil.getEnterCoilNo() : "");
dto.setSupplierCoilNo(coil.getSupplierCoilNo() != null ? coil.getSupplierCoilNo() : "");
dto.setCurrentCoilNo(coil.getCurrentCoilNo() != null ? coil.getCurrentCoilNo() : "");
dto.setCreateTime(coil.getCreateTime() != null ? sdf.format(coil.getCreateTime()) : "");
dto.setNetWeight(coil.getNetWeight() != null ? coil.getNetWeight().toString() : "");
dto.setBusinessPurpose(coil.getBusinessPurpose() != null ? coil.getBusinessPurpose() : "");
dto.setTrimmingRequirement(coil.getTrimmingRequirement() != null ? coil.getTrimmingRequirement() : "");
dto.setPackagingRequirement(coil.getPackagingRequirement() != null ? coil.getPackagingRequirement() : "");
dto.setQualityStatus(coil.getQualityStatus() != null ? coil.getQualityStatus() : "");
dto.setPackingStatus(coil.getPackingStatus() != null ? coil.getPackingStatus() : "");
dto.setStatus(coil.getStatus() != null ? coil.getStatus().toString() : "");
dto.setRemark(coil.getRemark() != null ? coil.getRemark() : "");
dto.setItemName(coil.getItemName() != null ? coil.getItemName() : "");
dto.setSpecification(coil.getSpecification() != null ? coil.getSpecification() : "");
dto.setLength(coil.getLength() != null ? coil.getLength().toString() : "");
dto.setMaterial(coil.getMaterial() != null ? coil.getMaterial() : "");
dto.setManufacturer(coil.getManufacturer() != null ? coil.getManufacturer() : "");
dto.setSurfaceTreatmentDesc(coil.getSurfaceTreatmentDesc() != null ? coil.getSurfaceTreatmentDesc() : "");
dto.setZincLayer(coil.getZincLayer() != null ? coil.getZincLayer() : "");
dto.setItemId(coil.getItemId() != null ? coil.getItemId().toString() : "");
dto.setActionCompleteTime(coil.getActionCompleteTime() != null ? sdf.format(coil.getActionCompleteTime()) : "");
dto.setTransferType(coil.getTransferType() != null ? coil.getTransferType() : "");
// 改判原因第26列
dto.setRejudgeReason(rejudgeReason != null ? rejudgeReason : "");
// 异常信息后17列
if (abnormal != null) {
dto.setProductionLine(abnormal.getProductionLine() != null ? abnormal.getProductionLine() : "");
dto.setPosition(abnormal.getPosition() != null ? abnormal.getPosition() : "");
dto.setAbnormalLength(abnormal.getLength() != null ? abnormal.getLength().toString() : "");
dto.setStartPosition(abnormal.getStartPosition() != null ? abnormal.getStartPosition().toString() : "");
dto.setEndPosition(abnormal.getEndPosition() != null ? abnormal.getEndPosition().toString() : "");
dto.setDefectCode(abnormal.getDefectCode() != null ? abnormal.getDefectCode() : "");
dto.setDefectType(abnormal.getDefectType() != null ? abnormal.getDefectType() : "");
dto.setDefectRate(abnormal.getDefectRate() != null ? abnormal.getDefectRate().toString() : "");
dto.setDefectWeight(abnormal.getDefectWeight() != null ? abnormal.getDefectWeight().toString() : "");
dto.setDegree(abnormal.getDegree() != null ? abnormal.getDegree() : "");
dto.setJudgeLevel(abnormal.getJudgeLevel() != null ? abnormal.getJudgeLevel() : "");
dto.setJudgeBy(abnormal.getJudgeBy() != null ? abnormal.getJudgeBy() : "");
dto.setJudgeTime(abnormal.getJudgeTime() != null ? sdf.format(abnormal.getJudgeTime()) : "");
dto.setMainMark(abnormal.getMainMark() != null ? abnormal.getMainMark().toString() : "");
dto.setWholeCoilMark(abnormal.getWholeCoilMark() != null ? abnormal.getWholeCoilMark().toString() : "");
dto.setAbnormalRemark(abnormal.getRemark() != null ? abnormal.getRemark() : "");
dto.setPlateSurface(abnormal.getPlateSurface() != null ? abnormal.getPlateSurface() : "");
} else {
// 空异常信息
dto.setProductionLine("");
dto.setPosition("");
dto.setAbnormalLength("");
dto.setStartPosition("");
dto.setEndPosition("");
dto.setDefectCode("");
dto.setDefectType("");
dto.setDefectRate("");
dto.setDefectWeight("");
dto.setDegree("");
dto.setJudgeLevel("");
dto.setJudgeBy("");
dto.setJudgeTime("");
dto.setMainMark("");
dto.setWholeCoilMark("");
dto.setAbnormalRemark("");
dto.setPlateSurface("");
}
return dto;
}
}

View File

@@ -0,0 +1,111 @@
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.WmsPostCoeffConfigBo;
import com.klp.domain.vo.WmsPostCoeffConfigVo;
import com.klp.domain.WmsPostCoeffConfig;
import com.klp.mapper.WmsPostCoeffConfigMapper;
import com.klp.service.IWmsPostCoeffConfigService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 岗位系数配置Service业务层处理
*
* @author klp
* @date 2026-05-07
*/
@RequiredArgsConstructor
@Service
public class WmsPostCoeffConfigServiceImpl implements IWmsPostCoeffConfigService {
private final WmsPostCoeffConfigMapper baseMapper;
/**
* 查询岗位系数配置
*/
@Override
public WmsPostCoeffConfigVo queryById(Long configId){
return baseMapper.selectVoById(configId);
}
/**
* 查询岗位系数配置列表
*/
@Override
public TableDataInfo<WmsPostCoeffConfigVo> queryPageList(WmsPostCoeffConfigBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<WmsPostCoeffConfig> lqw = buildQueryWrapper(bo);
Page<WmsPostCoeffConfigVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询岗位系数配置列表
*/
@Override
public List<WmsPostCoeffConfigVo> queryList(WmsPostCoeffConfigBo bo) {
LambdaQueryWrapper<WmsPostCoeffConfig> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<WmsPostCoeffConfig> buildQueryWrapper(WmsPostCoeffConfigBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<WmsPostCoeffConfig> lqw = Wrappers.lambdaQuery();
lqw.like(StringUtils.isNotBlank(bo.getPostName()), WmsPostCoeffConfig::getPostName, bo.getPostName());
lqw.eq(bo.getDutyCoeff() != null, WmsPostCoeffConfig::getDutyCoeff, bo.getDutyCoeff());
lqw.eq(bo.getBaseCoeff() != null, WmsPostCoeffConfig::getBaseCoeff, bo.getBaseCoeff());
return lqw;
}
/**
* 新增岗位系数配置
*/
@Override
public Boolean insertByBo(WmsPostCoeffConfigBo bo) {
WmsPostCoeffConfig add = BeanUtil.toBean(bo, WmsPostCoeffConfig.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setConfigId(add.getConfigId());
}
return flag;
}
/**
* 修改岗位系数配置
*/
@Override
public Boolean updateByBo(WmsPostCoeffConfigBo bo) {
WmsPostCoeffConfig update = BeanUtil.toBean(bo, WmsPostCoeffConfig.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(WmsPostCoeffConfig entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 批量删除岗位系数配置
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
}

View File

@@ -0,0 +1,27 @@
<?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.WmsBonusConfigMapper">
<resultMap type="com.klp.domain.WmsBonusConfig" id="WmsBonusConfigResult">
<result property="configId" column="config_id"/>
<result property="poolId" column="pool_id"/>
<result property="empId" column="emp_id"/>
<result property="empName" column="emp_name"/>
<result property="postName" column="post_name"/>
<result property="dutyCoeff" column="duty_coeff"/>
<result property="baseCoeff" column="base_coeff"/>
<result property="adjustCoeff" column="adjust_coeff"/>
<result property="allocBase" column="alloc_base"/>
<result property="bonusAmount" column="bonus_amount"/>
<result property="remark" column="remark"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
<result property="delFlag" column="del_flag"/>
</resultMap>
</mapper>

View File

@@ -0,0 +1,21 @@
<?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.WmsBonusPoolMapper">
<resultMap type="com.klp.domain.WmsBonusPool" id="WmsBonusPoolResult">
<result property="poolId" column="pool_id"/>
<result property="productionLine" column="production_line"/>
<result property="bonusTime" column="bonus_time"/>
<result property="totalBonus" column="total_bonus"/>
<result property="remark" column="remark"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
<result property="delFlag" column="del_flag"/>
</resultMap>
</mapper>

View File

@@ -0,0 +1,21 @@
<?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.WmsPostCoeffConfigMapper">
<resultMap type="com.klp.domain.WmsPostCoeffConfig" id="WmsPostCoeffConfigResult">
<result property="configId" column="config_id"/>
<result property="postName" column="post_name"/>
<result property="dutyCoeff" column="duty_coeff"/>
<result property="baseCoeff" column="base_coeff"/>
<result property="remark" column="remark"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
<result property="delFlag" column="del_flag"/>
</resultMap>
</mapper>