Merge remote-tracking branch 'origin/0.8.X' into 0.8.X
This commit is contained in:
@@ -473,3 +473,13 @@ export function excludeLock(coilId) {
|
|||||||
timeout: 600000,
|
timeout: 600000,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 轻量钢卷列表
|
||||||
|
export function listLightCoil(data) {
|
||||||
|
return request({
|
||||||
|
url: '/wms/materialCoil/listForReport',
|
||||||
|
method: 'get',
|
||||||
|
timeout: 600000,
|
||||||
|
params: data
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -167,3 +167,15 @@ export function restorePendingAction(actionId) {
|
|||||||
method: 'put'
|
method: 'put'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 轻量待操作列表
|
||||||
|
*/
|
||||||
|
export function listLightPendingAction(query) {
|
||||||
|
return request({
|
||||||
|
url: '/wms/coilPendingAction/actionCoilIdList',
|
||||||
|
method: 'get',
|
||||||
|
params: query,
|
||||||
|
timeout: 600000
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -430,6 +430,12 @@ export default {
|
|||||||
async handleRowClick(row) {
|
async handleRowClick(row) {
|
||||||
// 快速点击防重:每次点击递增版本号,旧的 sync 任务检测到版本号变更后自动放弃
|
// 快速点击防重:每次点击递增版本号,旧的 sync 任务检测到版本号变更后自动放弃
|
||||||
const clickRev = ++this._clickRev
|
const clickRev = ++this._clickRev
|
||||||
|
|
||||||
|
// 记录点击前的钢卷号,用于判断是否同一行重复点击
|
||||||
|
const prevExcoilId = this.selectedRow
|
||||||
|
? (this.selectedRow.EXCOILID || this.selectedRow.excoilid || null)
|
||||||
|
: null
|
||||||
|
|
||||||
this.selectedRow = row
|
this.selectedRow = row
|
||||||
this.segData = null
|
this.segData = null
|
||||||
this.gaugeRows = null
|
this.gaugeRows = null
|
||||||
@@ -450,8 +456,12 @@ export default {
|
|||||||
// 如果期间又点击了其他行则放弃后续操作
|
// 如果期间又点击了其他行则放弃后续操作
|
||||||
if (this._clickRev !== clickRev) return
|
if (this._clickRev !== clickRev) return
|
||||||
|
|
||||||
// 后台静默同步到规程(不阻塞 UI)
|
// 同一钢卷重复点击:跳过规程同步,避免重复写入
|
||||||
this.autoSyncToActiveSpec(excoilId || encoilId, clickRev)
|
const isSameCoil = excoilId && excoilId === prevExcoilId
|
||||||
|
if (!isSameCoil) {
|
||||||
|
// 后台静默同步到规程(不阻塞 UI)
|
||||||
|
this.autoSyncToActiveSpec(excoilId || encoilId, clickRev)
|
||||||
|
}
|
||||||
|
|
||||||
await this.$nextTick()
|
await this.$nextTick()
|
||||||
// 加载完成后自动选中第一个趋势参数
|
// 加载完成后自动选中第一个趋势参数
|
||||||
@@ -879,22 +889,34 @@ export default {
|
|||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
if (guard()) return
|
if (guard()) return
|
||||||
|
|
||||||
// 确保 plan 点位存在
|
// 确保 plan 点位存在(幂等:插入失败时降级重查,应对并发竞态)
|
||||||
let planId
|
let planId
|
||||||
const ep = planMap[item.pointCode]
|
const ep = planMap[item.pointCode]
|
||||||
if (ep) {
|
if (ep) {
|
||||||
planId = ep.planId
|
planId = ep.planId
|
||||||
} else {
|
} else {
|
||||||
const r = await addProcessPlan({
|
try {
|
||||||
versionId,
|
const r = await addProcessPlan({
|
||||||
segmentType: 'PROCESS',
|
versionId,
|
||||||
segmentName: item.groupLabel,
|
segmentType: 'PROCESS',
|
||||||
pointName: item.pointName,
|
segmentName: item.groupLabel,
|
||||||
pointCode: item.pointCode,
|
pointName: item.pointName,
|
||||||
sortOrder: 0
|
pointCode: item.pointCode,
|
||||||
})
|
sortOrder: 0
|
||||||
if (guard()) return
|
})
|
||||||
planId = r.data
|
if (guard()) return
|
||||||
|
planId = r.data
|
||||||
|
// 写入本地 map,同一次 sync 内不再重复插入
|
||||||
|
planMap[item.pointCode] = { planId }
|
||||||
|
} catch (_dupErr) {
|
||||||
|
// 唯一键冲突:该点位已由并发请求写入,重新查询获取真实 planId
|
||||||
|
const refetch = await listProcessPlan({ versionId, pageNum: 1, pageSize: 500 })
|
||||||
|
if (guard()) return
|
||||||
|
const found = (refetch.rows || []).find(p => p.pointCode === item.pointCode)
|
||||||
|
if (!found) continue // 极端情况:查不到则跳过本条目
|
||||||
|
planId = found.planId
|
||||||
|
planMap[item.pointCode] = found
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查已存储参数
|
// 查已存储参数
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="coil-table">
|
<div class="coil-table">
|
||||||
<div class="table-controls">
|
<div class="table-controls">
|
||||||
<div class="filter-section">
|
<!-- <div class="filter-section">
|
||||||
<el-input v-model="filterKeyword" placeholder="输入关键词筛选" clearable @input="handleFilterChange"
|
<el-input v-model="filterKeyword" placeholder="输入关键词筛选" clearable @input="handleFilterChange"
|
||||||
style="width: 200px; margin-right: 10px" />
|
style="width: 200px; margin-right: 10px" />
|
||||||
<el-select v-model="filterColumn" placeholder="选择筛选字段" @change="handleFilterChange"
|
<el-select v-model="filterColumn" placeholder="选择筛选字段" @change="handleFilterChange"
|
||||||
style="width: 200px; margin-right: 10px" multiple collapse-tags>
|
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-option v-for="column in columns" :key="column.prop" :label="column.title" :value="column.prop" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</div>
|
</div> -->
|
||||||
<div class="sort-section">
|
<!-- <div class="sort-section">
|
||||||
<el-select v-model="sortField" placeholder="选择排序字段" @change="handleSortChange"
|
<el-select v-model="sortField" placeholder="选择排序字段" @change="handleSortChange"
|
||||||
style="width: 150px; margin-right: 10px">
|
style="width: 150px; margin-right: 10px">
|
||||||
<el-option v-for="column in columns" :key="column.prop" :label="column.title" :value="column.prop" />
|
<el-option v-for="column in columns" :key="column.prop" :label="column.title" :value="column.prop" />
|
||||||
@@ -18,10 +18,10 @@
|
|||||||
<el-option label="升序" value="asc" />
|
<el-option label="升序" value="asc" />
|
||||||
<el-option label="降序" value="desc" />
|
<el-option label="降序" value="desc" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</div>
|
</div> -->
|
||||||
<el-pagination layout="total, sizes, prev, pager, next, jumper" :total="total" :page-size.sync="pageSize"
|
<el-pagination layout="total, sizes, prev, pager, next, jumper" :total="paginationTotal" :page-size="effectivePageSize"
|
||||||
:page-sizes="[10, 20, 50, 100, 200, 500, 1000]" @size-change="handleSizeChange"
|
:current-page="pageNum" :page-sizes="[10, 20, 50, 100, 200, 500, 1000]" @size-change="handleSizeChange"
|
||||||
@current-change="handleCurrentChange" />
|
@current-change="handleCurrentChange" />
|
||||||
|
|
||||||
<slot name="settings"></slot>
|
<slot name="settings"></slot>
|
||||||
</div>
|
</div>
|
||||||
@@ -107,13 +107,23 @@ export default {
|
|||||||
// 自定义高亮样式
|
// 自定义高亮样式
|
||||||
style: {}
|
style: {}
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
// 服务端分页总数(>0 时开启服务端分页模式)
|
||||||
|
total: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
// 服务端分页每页条数
|
||||||
|
pageSize: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dicts: ['coil_quality_status', 'coil_abnormal_code', 'coil_abnormal_degree'],
|
dicts: ['coil_quality_status', 'coil_abnormal_code', 'coil_abnormal_degree'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 1000,
|
innerPageSize: 1000,
|
||||||
// 排序相关
|
// 排序相关
|
||||||
sortField: '',
|
sortField: '',
|
||||||
sortDirection: 'asc',
|
sortDirection: 'asc',
|
||||||
@@ -133,8 +143,17 @@ export default {
|
|||||||
this.filterColumn = this.columns.map(column => column.prop)
|
this.filterColumn = this.columns.map(column => column.prop)
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
// 处理排序和筛选后的数据
|
isServerPagination() {
|
||||||
|
return this.total > 0
|
||||||
|
},
|
||||||
|
effectivePageSize() {
|
||||||
|
return this.pageSize > 0 ? this.pageSize : this.innerPageSize
|
||||||
|
},
|
||||||
|
// 处理排序和筛选后的数据(服务端分页模式下跳过筛选排序)
|
||||||
processedData() {
|
processedData() {
|
||||||
|
if (this.isServerPagination) {
|
||||||
|
return this.data
|
||||||
|
}
|
||||||
let result = [...this.data]
|
let result = [...this.data]
|
||||||
|
|
||||||
// 筛选逻辑
|
// 筛选逻辑
|
||||||
@@ -183,32 +202,48 @@ export default {
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
},
|
},
|
||||||
// 内部实现前端分页逻辑
|
// 内部实现前端分页逻辑(服务端分页模式下直接返回数据)
|
||||||
tableData() {
|
tableData() {
|
||||||
return this.processedData.slice((this.pageNum - 1) * this.pageSize, this.pageNum * this.pageSize)
|
if (this.isServerPagination) {
|
||||||
|
return this.data
|
||||||
|
}
|
||||||
|
return this.processedData.slice((this.pageNum - 1) * this.effectivePageSize, this.pageNum * this.effectivePageSize)
|
||||||
},
|
},
|
||||||
// 计算总页数
|
// 计算总页数
|
||||||
totalPage() {
|
totalPage() {
|
||||||
return Math.ceil(this.processedData.length / this.pageSize)
|
const total = this.isServerPagination ? this.total : this.processedData.length
|
||||||
|
return Math.ceil(total / this.effectivePageSize)
|
||||||
},
|
},
|
||||||
// 计算总条数
|
// 计算总条数
|
||||||
total() {
|
pageTotal() {
|
||||||
return this.processedData.length
|
return this.processedData.length
|
||||||
},
|
},
|
||||||
|
// 分页总条数(服务端优先)
|
||||||
|
paginationTotal() {
|
||||||
|
return this.isServerPagination ? this.total : this.pageTotal
|
||||||
|
},
|
||||||
// 是否展示分页组件
|
// 是否展示分页组件
|
||||||
showPagination() {
|
showPagination() {
|
||||||
|
if (this.isServerPagination) return true
|
||||||
return this.totalPage > 1
|
return this.totalPage > 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
// 分页大小改变时触发
|
// 分页大小改变时触发
|
||||||
handleSizeChange(val) {
|
handleSizeChange(val) {
|
||||||
this.pageSize = val
|
if (this.isServerPagination) {
|
||||||
|
this.$emit('size-change', val)
|
||||||
|
} else {
|
||||||
|
this.innerPageSize = val
|
||||||
|
}
|
||||||
this.pageNum = 1
|
this.pageNum = 1
|
||||||
},
|
},
|
||||||
// 分页当前页改变时触发
|
// 分页当前页改变时触发
|
||||||
handleCurrentChange(val) {
|
handleCurrentChange(val) {
|
||||||
this.pageNum = val
|
this.pageNum = val
|
||||||
|
if (this.isServerPagination) {
|
||||||
|
this.$emit('current-change', val)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
// 生产耗时,单位分钟,渲染为xx天xx小时xx分钟
|
// 生产耗时,单位分钟,渲染为xx天xx小时xx分钟
|
||||||
formatProductionDuration(duration) {
|
formatProductionDuration(duration) {
|
||||||
|
|||||||
@@ -55,7 +55,8 @@
|
|||||||
|
|
||||||
<el-descriptions title="明细信息" :column="3" border>
|
<el-descriptions title="明细信息" :column="3" border>
|
||||||
</el-descriptions>
|
</el-descriptions>
|
||||||
<coil-table :columns="deliveryColumns" :data="list"></coil-table>
|
<coil-table :columns="deliveryColumns" :data="list" :total="total" :page-size="pageSize"
|
||||||
|
@current-change="handlePageChange" @size-change="handleSizeChange"></coil-table>
|
||||||
|
|
||||||
<el-dialog title="列设置" :visible.sync="settingVisible" width="50%">
|
<el-dialog title="列设置" :visible.sync="settingVisible" width="50%">
|
||||||
<el-radio-group v-model="activeColumnConfig">
|
<el-radio-group v-model="activeColumnConfig">
|
||||||
@@ -67,7 +68,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { listCoilWithIds, listWithBindInfoCoil } from "@/api/wms/coil";
|
import { listWithBindInfoCoil, listLightCoil } from "@/api/wms/coil";
|
||||||
import ProductInfo from "@/components/KLPService/Renderer/ProductInfo";
|
import ProductInfo from "@/components/KLPService/Renderer/ProductInfo";
|
||||||
import RawMaterialInfo from "@/components/KLPService/Renderer/RawMaterialInfo";
|
import RawMaterialInfo from "@/components/KLPService/Renderer/RawMaterialInfo";
|
||||||
import CoilNo from "@/components/KLPService/Renderer/CoilNo.vue";
|
import CoilNo from "@/components/KLPService/Renderer/CoilNo.vue";
|
||||||
@@ -118,11 +119,10 @@ export default {
|
|||||||
activeColumnConfig: 'coil-report-delivery',
|
activeColumnConfig: 'coil-report-delivery',
|
||||||
settingVisible: false,
|
settingVisible: false,
|
||||||
list: [],
|
list: [],
|
||||||
|
lightList: [],
|
||||||
defaultStartTime: startTime,
|
defaultStartTime: startTime,
|
||||||
defaultEndTime: endTime,
|
defaultEndTime: endTime,
|
||||||
queryParams: {
|
queryParams: {
|
||||||
pageNum: 1,
|
|
||||||
pageSize: 99999,
|
|
||||||
status: 1,
|
status: 1,
|
||||||
dataType: 1,
|
dataType: 1,
|
||||||
selectType: 'product',
|
selectType: 'product',
|
||||||
@@ -133,8 +133,10 @@ export default {
|
|||||||
itemSpecification: '',
|
itemSpecification: '',
|
||||||
itemMaterial: '',
|
itemMaterial: '',
|
||||||
itemManufacturer: '',
|
itemManufacturer: '',
|
||||||
includeBindInfo: true,
|
|
||||||
},
|
},
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 100,
|
||||||
|
total: 0,
|
||||||
loading: false,
|
loading: false,
|
||||||
|
|
||||||
deliveryColumns: [],
|
deliveryColumns: [],
|
||||||
@@ -142,9 +144,9 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
summary() {
|
summary() {
|
||||||
// 总钢卷数量、总重、均重
|
// 总钢卷数量、总重、均重(基于轻量全量列表)
|
||||||
const totalCount = this.list.length
|
const totalCount = this.lightList.length
|
||||||
const totalWeight = this.list.reduce((acc, cur) => acc + parseFloat(cur.netWeight), 0)
|
const totalWeight = this.lightList.reduce((acc, cur) => acc + parseFloat(cur.netWeight), 0)
|
||||||
const avgWeight = totalCount > 0 ? (totalWeight / totalCount).toFixed(2) : 0
|
const avgWeight = totalCount > 0 ? (totalWeight / totalCount).toFixed(2) : 0
|
||||||
return {
|
return {
|
||||||
totalCount,
|
totalCount,
|
||||||
@@ -153,7 +155,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
coilIds() {
|
coilIds() {
|
||||||
return this.list.map(item => item.coilId).join(',')
|
return this.lightList.map(item => item.coilId).join(',')
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -167,11 +169,20 @@ export default {
|
|||||||
},
|
},
|
||||||
getList() {
|
getList() {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
listWithBindInfoCoil({
|
this.pageNum = 1
|
||||||
|
Promise.all([
|
||||||
|
this.fetchLightList(),
|
||||||
|
this.fetchDetailList()
|
||||||
|
]).finally(() => {
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 轻量全量接口,用于统计计算
|
||||||
|
fetchLightList() {
|
||||||
|
return listLightCoil({
|
||||||
...this.queryParams
|
...this.queryParams
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
this.list = res.rows.map(item => {
|
this.lightList = (res || []).map(item => {
|
||||||
// 计算宽度和厚度,将规格按照*分割,*前的是厚度,*后的是宽度
|
|
||||||
const [thickness, width] = item.specification?.split('*') || []
|
const [thickness, width] = item.specification?.split('*') || []
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
@@ -179,6 +190,41 @@ export default {
|
|||||||
computedWidth: parseFloat(width),
|
computedWidth: parseFloat(width),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 分页明细接口,用于表格展示
|
||||||
|
fetchDetailList() {
|
||||||
|
return listWithBindInfoCoil({
|
||||||
|
...this.queryParams,
|
||||||
|
includeBindInfo: true,
|
||||||
|
pageNum: this.pageNum,
|
||||||
|
pageSize: this.pageSize,
|
||||||
|
}).then(res => {
|
||||||
|
this.total = res.total || 0
|
||||||
|
this.list = (res.rows || []).map(item => {
|
||||||
|
const [thickness, width] = item.specification?.split('*') || []
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
computedThickness: parseFloat(thickness),
|
||||||
|
computedWidth: parseFloat(width),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 切换页码
|
||||||
|
handlePageChange(pageNum) {
|
||||||
|
this.pageNum = pageNum
|
||||||
|
this.loading = true
|
||||||
|
this.fetchDetailList().finally(() => {
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 切换每页条数
|
||||||
|
handleSizeChange(pageSize) {
|
||||||
|
this.pageSize = pageSize
|
||||||
|
this.pageNum = 1
|
||||||
|
this.loading = true
|
||||||
|
this.fetchDetailList().finally(() => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user