Files
klp-oa/klp-ui/src/views/wms/report/components/coilTable/index.vue
砂糖 0223102269 feat(wms/report): 添加差值计算和异常信息展示功能
refactor(wms/report): 替换合计信息为差值显示
feat(wms/coil): 增加创建时间和创建人字段
feat(crm/contract): 添加合同导出按钮
2026-03-31 18:37:17 +08:00

294 lines
9.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="coil-table">
<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">
<template slot-scope="scope">
<!-- 特殊 prop 渲染逻辑 -->
<template v-if="column.prop === 'enterCoilNo'">
<coil-no :coil-no="scope.row.enterCoilNo"></coil-no>
</template>
<template v-else-if="column.prop === 'currentCoilNo'">
<current-coil-no :current-coil-no="scope.row.currentCoilNo"></current-coil-no>
</template>
<template v-else-if="column.prop === 'itemId'">
<ProductInfo v-if="scope.row.itemType == 'product'" :product="scope.row" />
<RawMaterialInfo v-else-if="scope.row.itemType === 'raw_material'" :material="scope.row" />
</template>
<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-if="column.prop === 'qualityStatus'">
<div @click="handleQualityStatusClick(scope.row)" style="cursor: pointer; background-color: #f5f7fa;">
<dict-tag :options="dict.type.coil_quality_status" :value="scope.row.qualityStatus"></dict-tag>
</div>
</template>
<!-- 默认渲染 -->
<template v-else>
{{ scope.row[column.prop] }}
</template>
</template>
</el-table-column>
</el-table>
<el-dialog title="钢卷异常信息" :visible.sync="abmornal.visible" width="50%">
<el-table :data="abmornal.data" style="width: 100%" v-loading="abmornal.loading">
<el-table-column label="开始位置" prop="startPosition"></el-table-column>
<el-table-column label="结束位置" prop="endPosition"></el-table-column>
<el-table-column label="长度" prop="length"></el-table-column>
<el-table-column label="缺陷位置" prop="position"></el-table-column>
<el-table-column label="缺陷代码" prop="defectCode">
<template slot-scope="scope">
<dict-tag :options="dict.type.coil_abnormal_code" :value="scope.row.defectCode" />
</template>
</el-table-column>
<el-table-column label="程度" prop="degree">
<template slot-scope="scope">
<dict-tag :options="dict.type.coil_abnormal_degree" :value="scope.row.degree" />
</template>
</el-table-column>
<el-table-column label="产线" prop="productionLine"></el-table-column>
<el-table-column label="备注" prop="remark"></el-table-column>
</el-table>
</el-dialog>
</div>
</template>
<script>
import ProductInfo from "@/components/KLPService/Renderer/ProductInfo";
import RawMaterialInfo from "@/components/KLPService/Renderer/RawMaterialInfo";
import CoilNo from "@/components/KLPService/Renderer/CoilNo.vue";
import { listCoilAbnormal } from '@/api/wms/coilAbnormal'
export default {
name: 'CoilTable',
components: {
ProductInfo,
RawMaterialInfo,
CoilNo,
},
props: {
columns: {
type: Array,
default: () => [],
},
data: {
type: Array,
default: () => [],
},
},
dicts: ['coil_quality_status', 'coil_abnormal_code', 'coil_abnormal_degree'],
data() {
return {
pageNum: 1,
pageSize: 1000,
// 排序相关
sortField: '',
sortDirection: 'asc',
// 筛选相关
filterKeyword: '',
filterColumn: [],
abmornal: {
visible: false,
data: {},
loading: false,
}
}
},
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.processedData.slice((this.pageNum - 1) * this.pageSize, this.pageNum * this.pageSize)
},
// 计算总页数
totalPage() {
return Math.ceil(this.processedData.length / this.pageSize)
},
// 计算总条数
total() {
return this.processedData.length
},
// 是否展示分页组件
showPagination() {
return this.totalPage > 1
}
},
methods: {
// 分页大小改变时触发
handleSizeChange(val) {
this.pageSize = val
this.pageNum = 1
},
// 分页当前页改变时触发
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
},
handleQualityStatusClick(row) {
this.abmornal.visible = true
this.abmornal.loading = true
listCoilAbnormal({
coilId: row.coilId
}).then(response => {
this.abmornal.data = response.rows || []
}).catch(error => {
console.error('查询异常记录失败:', error)
this.$message.error('查询异常记录失败: ' + (error.message || error))
}).finally(() => {
this.abmornal.loading = false
})
}
}
}
</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>