refactor(wms/report): 替换合计信息为差值显示 feat(wms/coil): 增加创建时间和创建人字段 feat(crm/contract): 添加合同导出按钮
294 lines
9.6 KiB
Vue
294 lines
9.6 KiB
Vue
<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> |