|
|
@ -2,15 +2,18 @@ |
|
|
<div class="exp-tri-confirm"> |
|
|
<div class="exp-tri-confirm"> |
|
|
<!-- 操作按钮 --> |
|
|
<!-- 操作按钮 --> |
|
|
<div class="toolbar"> |
|
|
<div class="toolbar"> |
|
|
<el-button @click="openAddDialog" type="primary" size="small">新增</el-button> |
|
|
|
|
|
|
|
|
<el-button @click="openAddDialog" type="primary" class="add-btn" size="small">新增</el-button> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<!-- 三方确认表格 --> |
|
|
<!-- 三方确认表格 --> |
|
|
<el-table |
|
|
<el-table |
|
|
|
|
|
ref="processTable" |
|
|
|
|
|
:key="tableKey" |
|
|
:data="processList" |
|
|
:data="processList" |
|
|
v-loading="loading" |
|
|
v-loading="loading" |
|
|
border |
|
|
border |
|
|
:height="height" |
|
|
:height="height" |
|
|
|
|
|
class="tri-confirm-table" |
|
|
style="width: 100%;"> |
|
|
style="width: 100%;"> |
|
|
|
|
|
|
|
|
<el-table-column |
|
|
<el-table-column |
|
|
@ -20,7 +23,8 @@ |
|
|
header-align="center"> |
|
|
header-align="center"> |
|
|
<template slot-scope="scope"> |
|
|
<template slot-scope="scope"> |
|
|
<el-tag :type="getSeqTagType(scope.row)" size="small"> |
|
|
<el-tag :type="getSeqTagType(scope.row)" size="small"> |
|
|
第{{ scope.row.processSeq }}道 |
|
|
|
|
|
|
|
|
<i class="el-icon-rank" style="margin-right: 4px; cursor: move;"></i> |
|
|
|
|
|
{{ scope.row.processSeq }} |
|
|
</el-tag> |
|
|
</el-tag> |
|
|
</template> |
|
|
</template> |
|
|
</el-table-column> |
|
|
</el-table-column> |
|
|
@ -262,7 +266,8 @@ |
|
|
</template> |
|
|
</template> |
|
|
|
|
|
|
|
|
<script> |
|
|
<script> |
|
|
import { getTriConfirmList, saveTriConfirmProcess, deleteTriConfirmProcess, confirmTriApproval } from '@/api/erf/erf' |
|
|
|
|
|
|
|
|
import { getTriConfirmList, saveTriConfirmProcess, deleteTriConfirmProcess, confirmTriApproval, updateProcessSequence } from '@/api/erf/erf' |
|
|
|
|
|
import Sortable from 'sortablejs' |
|
|
|
|
|
|
|
|
export default { |
|
|
export default { |
|
|
name: 'ExpTriConfirm', |
|
|
name: 'ExpTriConfirm', |
|
|
@ -282,6 +287,7 @@ export default { |
|
|
return { |
|
|
return { |
|
|
processList: [], |
|
|
processList: [], |
|
|
loading: false, |
|
|
loading: false, |
|
|
|
|
|
tableKey: 0, // 用于强制刷新表格 |
|
|
|
|
|
|
|
|
// 新增/修改工序弹框 |
|
|
// 新增/修改工序弹框 |
|
|
processDialogVisible: false, |
|
|
processDialogVisible: false, |
|
|
@ -304,7 +310,11 @@ export default { |
|
|
confirmLoading: false, |
|
|
confirmLoading: false, |
|
|
currentProcess: null, |
|
|
currentProcess: null, |
|
|
currentRoleType: '', |
|
|
currentRoleType: '', |
|
|
currentTime: '' |
|
|
|
|
|
|
|
|
currentTime: '', |
|
|
|
|
|
|
|
|
|
|
|
// 拖拽排序相关 |
|
|
|
|
|
sortableInstance: null, // Sortable实例 |
|
|
|
|
|
isDragging: false // 是否正在拖拽 |
|
|
} |
|
|
} |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
@ -319,18 +329,65 @@ export default { |
|
|
} |
|
|
} |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
mounted() { |
|
|
|
|
|
// 初始化表格行拖拽排序功能 |
|
|
|
|
|
this.$nextTick(() => { |
|
|
|
|
|
this.initTableRowDrag() |
|
|
|
|
|
}) |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
beforeDestroy() { |
|
|
|
|
|
// 销毁 Sortable 实例 |
|
|
|
|
|
if (this.sortableInstance) { |
|
|
|
|
|
this.sortableInstance.destroy() |
|
|
|
|
|
this.sortableInstance = null |
|
|
|
|
|
} |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
methods: { |
|
|
methods: { |
|
|
/** |
|
|
/** |
|
|
* 加载工序列表 |
|
|
* 加载工序列表 |
|
|
*/ |
|
|
*/ |
|
|
loadProcessList() { |
|
|
loadProcessList() { |
|
|
|
|
|
console.log('📥 === 开始加载工序列表 === applyNo:', this.applyNo) |
|
|
|
|
|
|
|
|
|
|
|
// 先销毁旧的 Sortable 实例 |
|
|
|
|
|
if (this.sortableInstance) { |
|
|
|
|
|
console.log('🗑️ 销毁旧的 Sortable 实例') |
|
|
|
|
|
this.sortableInstance.destroy() |
|
|
|
|
|
this.sortableInstance = null |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
this.loading = true |
|
|
this.loading = true |
|
|
getTriConfirmList({ applyNo: this.applyNo }).then(({data}) => { |
|
|
getTriConfirmList({ applyNo: this.applyNo }).then(({data}) => { |
|
|
this.loading = false |
|
|
this.loading = false |
|
|
if (data && data.code === 0) { |
|
|
if (data && data.code === 0) { |
|
|
|
|
|
console.log('📦 原始数据 (排序前):', data.list.map(item => |
|
|
|
|
|
`${item.processStep}(序号${item.processSeq})` |
|
|
|
|
|
).join(', ')) |
|
|
|
|
|
|
|
|
// 按工序顺序排序 |
|
|
// 按工序顺序排序 |
|
|
this.processList = (data.list || []).sort((a, b) => { |
|
|
this.processList = (data.list || []).sort((a, b) => { |
|
|
return (a.processSeq || 0) - (b.processSeq || 0) |
|
|
|
|
|
|
|
|
const result = (a.processSeq || 0) - (b.processSeq || 0) |
|
|
|
|
|
console.log(` 排序比较: ${a.processStep}(${a.processSeq}) vs ${b.processStep}(${b.processSeq}) = ${result}`) |
|
|
|
|
|
return result |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
console.log('✅ 工序列表加载完成 (排序后):', this.processList.map(item => |
|
|
|
|
|
`${item.processStep}(序号${item.processSeq})` |
|
|
|
|
|
).join(', ')) |
|
|
|
|
|
|
|
|
|
|
|
// 强制刷新表格 |
|
|
|
|
|
this.tableKey++ |
|
|
|
|
|
console.log('🔄 强制刷新表格,tableKey:', this.tableKey) |
|
|
|
|
|
|
|
|
|
|
|
// 等待表格完全重新渲染后再初始化拖拽功能 |
|
|
|
|
|
this.$nextTick(() => { |
|
|
|
|
|
console.log('⏳ 等待 DOM 更新完成...') |
|
|
|
|
|
setTimeout(() => { |
|
|
|
|
|
console.log('🎯 开始重新初始化拖拽功能') |
|
|
|
|
|
this.initTableRowDrag() |
|
|
|
|
|
}, 100) // 给表格渲染留出足够时间 |
|
|
}) |
|
|
}) |
|
|
} else { |
|
|
} else { |
|
|
this.processList = [] |
|
|
this.processList = [] |
|
|
@ -338,6 +395,7 @@ export default { |
|
|
} |
|
|
} |
|
|
}).catch(error => { |
|
|
}).catch(error => { |
|
|
this.loading = false |
|
|
this.loading = false |
|
|
|
|
|
console.error('❌ 加载工序列表异常:', error) |
|
|
this.$message.error('加载三方确认列表异常') |
|
|
this.$message.error('加载三方确认列表异常') |
|
|
}) |
|
|
}) |
|
|
}, |
|
|
}, |
|
|
@ -537,6 +595,138 @@ export default { |
|
|
const minutes = String(date.getMinutes()).padStart(2, '0') |
|
|
const minutes = String(date.getMinutes()).padStart(2, '0') |
|
|
const seconds = String(date.getSeconds()).padStart(2, '0') |
|
|
const seconds = String(date.getSeconds()).padStart(2, '0') |
|
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}` |
|
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}` |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 初始化表格行拖拽排序功能 |
|
|
|
|
|
* 拖拽后自动重新计算序号并保存到数据库 |
|
|
|
|
|
*/ |
|
|
|
|
|
initTableRowDrag() { |
|
|
|
|
|
console.log('🎯 开始初始化表格拖拽排序功能') |
|
|
|
|
|
|
|
|
|
|
|
// 如果正在拖拽,不重新初始化 |
|
|
|
|
|
if (this.isDragging) { |
|
|
|
|
|
console.log('⚠️ 正在拖拽中,跳过初始化') |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 销毁旧的 Sortable 实例 |
|
|
|
|
|
if (this.sortableInstance) { |
|
|
|
|
|
console.log('🗑️ 销毁旧的 Sortable 实例') |
|
|
|
|
|
this.sortableInstance.destroy() |
|
|
|
|
|
this.sortableInstance = null |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 使用 ref 获取表格元素,更可靠 |
|
|
|
|
|
const tableEl = this.$refs.processTable |
|
|
|
|
|
if (!tableEl || !tableEl.$el) { |
|
|
|
|
|
console.warn('⚠️ 表格 ref 不存在,拖拽功能初始化失败') |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const el = tableEl.$el.querySelector('.el-table__body-wrapper tbody') |
|
|
|
|
|
if (!el) { |
|
|
|
|
|
console.warn('⚠️ 未找到表格 tbody 元素,拖拽功能初始化失败') |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
console.log('✅ 找到表格 tbody,当前有', el.children.length, '行') |
|
|
|
|
|
|
|
|
|
|
|
// 创建新的 Sortable 实例 |
|
|
|
|
|
this.sortableInstance = Sortable.create(el, { |
|
|
|
|
|
animation: 150, |
|
|
|
|
|
handle: 'tr', // 整行可拖拽 |
|
|
|
|
|
ghostClass: 'sortable-ghost', |
|
|
|
|
|
chosenClass: 'sortable-chosen', |
|
|
|
|
|
dragClass: 'sortable-drag', |
|
|
|
|
|
onStart: () => { |
|
|
|
|
|
console.log('🖱️ 开始拖拽') |
|
|
|
|
|
this.isDragging = true |
|
|
|
|
|
}, |
|
|
|
|
|
onEnd: (evt) => { |
|
|
|
|
|
const { oldIndex, newIndex } = evt |
|
|
|
|
|
console.log(`🎬 拖拽结束: oldIndex=${oldIndex}, newIndex=${newIndex}`) |
|
|
|
|
|
this.isDragging = false |
|
|
|
|
|
|
|
|
|
|
|
if (oldIndex === newIndex) { |
|
|
|
|
|
console.log('位置未变化,无需更新') |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
console.log(`🔄 拖拽: 从位置 ${oldIndex} (${this.processList[oldIndex].processStep},序号${this.processList[oldIndex].processSeq}) 移动到位置 ${newIndex}`) |
|
|
|
|
|
|
|
|
|
|
|
// 1. 更新本地数据顺序 |
|
|
|
|
|
const movedItem = this.processList.splice(oldIndex, 1)[0] |
|
|
|
|
|
this.processList.splice(newIndex, 0, movedItem) |
|
|
|
|
|
|
|
|
|
|
|
// 2. 重新计算所有序号(从1开始)- 使用 Vue.set 确保响应式更新 |
|
|
|
|
|
this.processList.forEach((item, index) => { |
|
|
|
|
|
this.$set(item, 'processSeq', index + 1) |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
console.log('📝 拖拽后新序号:', this.processList.map((item, idx) => |
|
|
|
|
|
`位置${idx}: ${item.processStep} (序号${item.processSeq})` |
|
|
|
|
|
).join(', ')) |
|
|
|
|
|
|
|
|
|
|
|
// 4. 使用 nextTick 确保 DOM 更新后再保存 |
|
|
|
|
|
this.$nextTick(() => { |
|
|
|
|
|
// 5. 保存到数据库 |
|
|
|
|
|
this.saveProcessSequence() |
|
|
|
|
|
}) |
|
|
|
|
|
} |
|
|
|
|
|
}) |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 保存工序顺序到数据库 |
|
|
|
|
|
*/ |
|
|
|
|
|
saveProcessSequence() { |
|
|
|
|
|
if (this.processList.length === 0) { |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
console.log('💾 === 拖拽排序保存开始 ===') |
|
|
|
|
|
console.log('准备保存的工序顺序:') |
|
|
|
|
|
this.processList.forEach((item, index) => { |
|
|
|
|
|
console.log(` 位置${index}: ${item.processStep} → 新序号 ${item.processSeq}`) |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
// 构建保存数据:提取工序名称列表(按新顺序) |
|
|
|
|
|
const processSteps = this.processList.map(item => item.processStep) |
|
|
|
|
|
|
|
|
|
|
|
// 显示loading |
|
|
|
|
|
const loadingInstance = this.$loading({ |
|
|
|
|
|
lock: true, |
|
|
|
|
|
text: '正在保存排序...', |
|
|
|
|
|
spinner: 'el-icon-loading', |
|
|
|
|
|
background: 'rgba(0, 0, 0, 0.7)' |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
// 调用API保存 |
|
|
|
|
|
updateProcessSequence({ |
|
|
|
|
|
applyNo: this.applyNo, |
|
|
|
|
|
processSteps: processSteps |
|
|
|
|
|
}).then(({data}) => { |
|
|
|
|
|
loadingInstance.close() |
|
|
|
|
|
if (data && data.code === 0) { |
|
|
|
|
|
this.$message.success('排序保存成功') |
|
|
|
|
|
console.log('✅ === 拖拽排序保存完成 ===') |
|
|
|
|
|
// 保存成功后稍作延迟再重新加载列表,确保数据库事务已提交 |
|
|
|
|
|
setTimeout(() => { |
|
|
|
|
|
this.loadProcessList() |
|
|
|
|
|
}, 300) |
|
|
|
|
|
} else { |
|
|
|
|
|
this.$message.error(data.msg || '排序保存失败') |
|
|
|
|
|
// 保存失败,重新加载数据恢复原状 |
|
|
|
|
|
this.loadProcessList() |
|
|
|
|
|
} |
|
|
|
|
|
}).catch(error => { |
|
|
|
|
|
loadingInstance.close() |
|
|
|
|
|
this.$message.error('排序保存异常') |
|
|
|
|
|
console.error('保存排序异常:', error) |
|
|
|
|
|
// 保存异常,重新加载数据恢复原状 |
|
|
|
|
|
this.loadProcessList() |
|
|
|
|
|
}) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -566,4 +756,48 @@ export default { |
|
|
.el-table >>> .el-table__row td { |
|
|
.el-table >>> .el-table__row td { |
|
|
padding: 8px 0; |
|
|
padding: 8px 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* 新增按钮 - 绿色扁平 */ |
|
|
|
|
|
.exp-tri-confirm .add-btn { |
|
|
|
|
|
background-color: #F0F9FF; |
|
|
|
|
|
border-color: #C0E6C7; |
|
|
|
|
|
color: #67C23A; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.exp-tri-confirm .add-btn:hover { |
|
|
|
|
|
background-color: #67C23A; |
|
|
|
|
|
border-color: #67C23A; |
|
|
|
|
|
color: #FFFFFF; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* 拖拽排序样式 */ |
|
|
|
|
|
.tri-confirm-table >>> tbody tr { |
|
|
|
|
|
cursor: move; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.tri-confirm-table >>> tbody tr:hover { |
|
|
|
|
|
background-color: #f5f7fa !important; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* 拖拽时的样式 */ |
|
|
|
|
|
.sortable-ghost { |
|
|
|
|
|
opacity: 0.4; |
|
|
|
|
|
background-color: #e3f2fd !important; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.sortable-chosen { |
|
|
|
|
|
background-color: #e3f2fd !important; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.sortable-drag { |
|
|
|
|
|
background-color: #ffffff; |
|
|
|
|
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.3); |
|
|
|
|
|
opacity: 0.9; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* 拖拽图标提示 */ |
|
|
|
|
|
.tri-confirm-table >>> .el-tag .el-icon-rank { |
|
|
|
|
|
font-size: 12px; |
|
|
|
|
|
vertical-align: middle; |
|
|
|
|
|
} |
|
|
</style> |
|
|
</style> |