Browse Source

固定列可以支持自定义

master
han\hanst 2 weeks ago
parent
commit
a51ba6dfb0
  1. 4
      src/api/sampleTracking/sampleTracking.js
  2. 488
      src/views/modules/sampleTracking/projectProofTracking.vue

4
src/api/sampleTracking/sampleTracking.js

@ -25,4 +25,8 @@ export const deleteProofTracking = data => createAPI('/sampleTracking/proofTrack
export const queryProofTrackingProcessHistory = data => createAPI('/sampleTracking/proofTracking/processHistory', 'POST', data)
export const queryProofTrackingBuProcessConfig = data => createAPI('/sampleTracking/proofTracking/buProcessConfig/list', 'POST', data)
export const saveProofTrackingBuProcessConfig = data => createAPI('/sampleTracking/proofTracking/buProcessConfig/save', 'POST', data)
export const deleteProofTrackingBuProcessConfig = data => createAPI('/sampleTracking/proofTracking/buProcessConfig/delete', 'POST', data)
export const queryProofTrackingProcessColumns = data => createAPI('/sampleTracking/proofTracking/processColumns/list', 'POST', data)
export const queryProofTrackingProcessColumnsManage = data => createAPI('/sampleTracking/proofTracking/processColumns/manageList', 'POST', data)
export const saveProofTrackingProcessColumnsManage = data => createAPI('/sampleTracking/proofTracking/processColumns/manageSave', 'POST', data)
export const deleteProofTrackingProcessColumnsManage = data => createAPI('/sampleTracking/proofTracking/processColumns/manageDelete', 'POST', data)

488
src/views/modules/sampleTracking/projectProofTracking.vue

@ -59,6 +59,7 @@
<el-button type="success" plain :loading="syncNpiLoading" @click="syncToNpi()">同步项目物料到NPI</el-button>
<el-button type="success" plain :loading="syncProofLoading" @click="syncProofToNpi()">同步打样到NPI</el-button>
<el-button type="info" v-if="isAuth('833001005:set')" plain @click="openBuProcessConfigDialog">事业部进度设置</el-button>
<el-button type="info" v-if="isAuth('833001005:set')" plain @click="openDefaultProcessConfigDialog">默认进度设置</el-button>
</el-row>
</el-form-item>
</el-form>
@ -285,6 +286,71 @@
</div>
</el-dialog>
<el-dialog
title="默认进度设置"
:visible.sync="defaultProcessConfigDialogVisible"
width="650px" class="zxClass"
:close-on-click-modal="false"
custom-class="default-process-config-dialog"
@opened="initDefaultProcessConfigSortable"
@closed="handleDefaultProcessConfigDialogClosed"
>
<div class="default-process-config-actions">
<el-button type="success" plain size="mini" @click="addDefaultProcessConfigRow">新增一行</el-button>
<el-button
type="danger"
plain
size="mini"
:disabled="defaultProcessConfigSelectionRows.length === 0 || defaultProcessConfigDeleteLoading"
:loading="defaultProcessConfigDeleteLoading"
@click="deleteDefaultProcessConfigRow"
>删除选中</el-button>
</div>
<el-table
ref="defaultProcessConfigTable"
:data="defaultProcessConfigRows"
row-key="_rowKey"
border
stripe
max-height="560"
@selection-change="handleDefaultProcessConfigSelectionChange"
>
<el-table-column type="selection" width="50" />
<el-table-column label="排序" width="90" align="center">
<template slot-scope="scope">
<i class="el-icon-rank default-process-drag-handle"></i>
<span class="default-process-order-index">{{ scope.$index + 1 }}</span>
</template>
</el-table-column>
<el-table-column label="工序编码" min-width="160">
<template slot-scope="scope">
<el-input v-model.trim="scope.row.code" size="mini" clearable placeholder="如: coating" />
</template>
</el-table-column>
<el-table-column label="工序名称" min-width="180">
<template slot-scope="scope">
<el-input v-model.trim="scope.row.label" size="mini" clearable placeholder="如: Coating" />
</template>
</el-table-column>
<el-table-column label="启用" width="100" align="center">
<template slot-scope="scope">
<el-select v-model="scope.row.activeFlag" size="mini" style="width: 80px;">
<el-option label="是" value="Y" />
<el-option label="否" value="N" />
</el-select>
</template>
</el-table-column>
</el-table>
<div v-if="defaultProcessConfigRows.length === 0" class="default-process-config-empty">
当前没有默认行请点击新增一行后填写并保存
</div>
<div slot="footer">
<el-button @click="defaultProcessConfigDialogVisible = false">关闭</el-button>
<el-button type="primary" @click="saveDefaultProcessConfig">保存设置</el-button>
</div>
</el-dialog>
<el-dialog :title="oneKeyDialogMode === 'edit' ? '修改项目/物料/打样' : '一键创建项目/物料/打样'" :visible.sync="oneKeyDialogVisible" :close-on-click-modal="false" width="1000px">
<el-form :model="oneKeyForm" label-position="top" class="one-key-grid-form">
<el-row :gutter="16">
@ -868,8 +934,11 @@ import {
oneKeyUpdateProofTracking,
queryProofTrackingBuProcessConfig,
queryProofTrackingProcessColumns,
deleteProofTrackingProcessColumnsManage,
queryProofTrackingProcessColumnsManage,
queryProofTrackingProcessHistory,
saveProofTrackingBuProcessConfig,
saveProofTrackingProcessColumnsManage,
searchProjectInfoTracking,
searchProjectPartTracking,
searchProofTracking,
@ -894,6 +963,7 @@ import {
} from '@/api/factory/site.js'
import { queryCustomerList } from '@/api/customer/customer'
import Chooselist from '@/views/modules/common/Chooselist_eam'
import Sortable from 'sortablejs'
function focusCommentsNativeInput (el, vnode) {
const doFocus = () => {
@ -978,6 +1048,12 @@ export default {
buProcessConfigDialogVisible: false,
buProcessConfigRows: [],
buProcessConfigMap: {},
defaultProcessConfigDialogVisible: false,
defaultProcessConfigRows: [],
defaultProcessConfigSelectionRows: [],
defaultProcessConfigDeleteLoading: false,
defaultProcessConfigRowSeed: 0,
defaultProcessConfigSortable: null,
processOrderDragState: {
buNo: '',
fromIndex: -1
@ -1137,6 +1213,9 @@ export default {
})
this.getDataList()
},
deactivated () {
this.destroyDefaultProcessConfigSortable()
},
computed: {
visibleProcessColumns () {
const searchBuNo = this.getSelectedSearchBuNo()
@ -1440,7 +1519,7 @@ export default {
site: this.$store.state.user.site,
userName: this.$store.state.user.name
}
queryProofTrackingBuProcessConfig(inData).then(({ data }) => {
return queryProofTrackingBuProcessConfig(inData).then(({ data }) => {
if (!(data && data.code === 0)) {
this.$message.error((data && data.msg) || '加载事业部进度展示配置失败')
return
@ -1528,6 +1607,345 @@ export default {
}
this.buProcessConfigDialogVisible = true
},
buildDefaultProcessConfigRow (item) {
const parsedSortNo = parseInt(item && item.sortNo, 10)
const activeFlag = item && item.activeFlag ? String(item.activeFlag).trim().toUpperCase() : 'Y'
const code = item && item.code ? String(item.code).trim() : ''
return {
_rowKey: `default_process_${Date.now()}_${this.defaultProcessConfigRowSeed++}`,
//
_persistedCode: code,
sortNo: Number.isNaN(parsedSortNo) || parsedSortNo <= 0 ? this.getNextDefaultProcessSortNo() : parsedSortNo,
code: code,
label: item && item.label ? String(item.label).trim() : '',
activeFlag: activeFlag === 'N' ? 'N' : 'Y'
}
},
getNextDefaultProcessSortNo () {
if (!Array.isArray(this.defaultProcessConfigRows) || this.defaultProcessConfigRows.length === 0) {
return 10
}
let maxSortNo = 0
this.defaultProcessConfigRows.forEach(row => {
const parsedSortNo = parseInt(row && row.sortNo, 10)
if (!Number.isNaN(parsedSortNo) && parsedSortNo > maxSortNo) {
maxSortNo = parsedSortNo
}
})
return maxSortNo > 0 ? maxSortNo + 10 : (this.defaultProcessConfigRows.length + 1) * 10
},
resetDefaultProcessConfigSortNoByOrder () {
if (!Array.isArray(this.defaultProcessConfigRows)) {
return
}
this.defaultProcessConfigRows.forEach((row, index) => {
if (!row) {
return
}
this.$set(row, 'sortNo', (index + 1) * 10)
})
},
clearDefaultProcessConfigSelection () {
this.defaultProcessConfigSelectionRows = []
this.$nextTick(() => {
const tableRef = this.$refs.defaultProcessConfigTable
if (tableRef && tableRef.clearSelection) {
tableRef.clearSelection()
}
})
},
destroyDefaultProcessConfigSortable () {
if (this.defaultProcessConfigSortable && typeof this.defaultProcessConfigSortable.destroy === 'function') {
this.defaultProcessConfigSortable.destroy()
}
this.defaultProcessConfigSortable = null
},
initDefaultProcessConfigSortable () {
this.$nextTick(() => {
this.destroyDefaultProcessConfigSortable()
if (!this.defaultProcessConfigDialogVisible || !Array.isArray(this.defaultProcessConfigRows) || this.defaultProcessConfigRows.length === 0) {
return
}
const tableRef = this.$refs.defaultProcessConfigTable
const tableBody = tableRef && tableRef.$el
? tableRef.$el.querySelector('.el-table__body-wrapper tbody')
: null
if (!tableBody) {
return
}
this.defaultProcessConfigSortable = Sortable.create(tableBody, {
animation: 150,
//
handle: 'tr',
draggable: 'tr',
ghostClass: 'default-process-sortable-ghost',
chosenClass: 'default-process-sortable-chosen',
dragClass: 'default-process-sortable-drag',
onEnd: (evt) => {
const oldIndex = evt && typeof evt.oldIndex === 'number' ? evt.oldIndex : -1
const newIndex = evt && typeof evt.newIndex === 'number' ? evt.newIndex : -1
if (oldIndex < 0 || newIndex < 0 || oldIndex === newIndex) {
return
}
const movedRow = this.defaultProcessConfigRows.splice(oldIndex, 1)[0]
this.defaultProcessConfigRows.splice(newIndex, 0, movedRow)
this.resetDefaultProcessConfigSortNoByOrder()
this.clearDefaultProcessConfigSelection()
}
})
})
},
handleDefaultProcessConfigDialogClosed () {
this.defaultProcessConfigDeleteLoading = false
this.clearDefaultProcessConfigSelection()
this.destroyDefaultProcessConfigSortable()
},
handleDefaultProcessConfigSelectionChange (rows) {
this.defaultProcessConfigSelectionRows = Array.isArray(rows) ? rows : []
},
normalizeDefaultProcessFieldBaseByCode (code) {
const rawCode = code == null ? '' : String(code).trim()
if (!rawCode) {
return ''
}
if (/^[A-Za-z_][A-Za-z0-9_]*$/.test(rawCode)) {
return rawCode
}
const parts = rawCode.split(/[^A-Za-z0-9]+/).filter(item => !!item)
if (parts.length === 0) {
return ''
}
const firstPart = parts[0].toLowerCase()
const remained = parts.slice(1).map(item => {
const lower = item.toLowerCase()
return `${lower.charAt(0).toUpperCase()}${lower.substring(1)}`
}).join('')
let fieldBase = `${firstPart}${remained}`
if (/^[0-9]/.test(fieldBase)) {
fieldBase = `p${fieldBase}`
}
return fieldBase
},
buildDefaultProcessFieldsByCode (code) {
const fieldBase = this.normalizeDefaultProcessFieldBaseByCode(code)
if (!fieldBase) {
return {
planField: '',
actualField: '',
statusField: ''
}
}
return {
planField: `${fieldBase}PlanDate`,
actualField: `${fieldBase}ActualDate`,
statusField: `${fieldBase}Status`
}
},
queryDefaultProcessConfig () {
const inData = {
site: '*',
buNo: '*',
userName: this.$store.state.user.name
}
return queryProofTrackingProcessColumnsManage(inData).then(({ data }) => {
if (!(data && data.code === 0)) {
this.$message.error((data && data.msg) || '加载默认工序配置失败')
this.defaultProcessConfigRows = []
this.defaultProcessConfigSelectionRows = []
return []
}
const rows = Array.isArray(data.rows) ? data.rows : []
const sortedRows = rows
.map((item, index) => {
const parsedSortNo = parseInt(item && item.sortNo, 10)
return {
sourceIndex: index,
sortNo: Number.isNaN(parsedSortNo) ? Number.MAX_SAFE_INTEGER : parsedSortNo,
item: item
}
})
.sort((a, b) => {
if (a.sortNo !== b.sortNo) {
return a.sortNo - b.sortNo
}
return a.sourceIndex - b.sourceIndex
})
this.defaultProcessConfigRows = sortedRows.map(({ item }) => this.buildDefaultProcessConfigRow(item))
this.resetDefaultProcessConfigSortNoByOrder()
this.clearDefaultProcessConfigSelection()
this.initDefaultProcessConfigSortable()
return this.defaultProcessConfigRows
}).catch(() => {
this.$message.error('加载默认工序配置异常')
this.defaultProcessConfigRows = []
this.defaultProcessConfigSelectionRows = []
this.destroyDefaultProcessConfigSortable()
return []
})
},
openDefaultProcessConfigDialog () {
this.defaultProcessConfigDeleteLoading = false
this.defaultProcessConfigDialogVisible = true
this.queryDefaultProcessConfig()
},
addDefaultProcessConfigRow () {
this.defaultProcessConfigRows.push(this.buildDefaultProcessConfigRow({
sortNo: this.getNextDefaultProcessSortNo(),
activeFlag: 'Y'
}))
this.resetDefaultProcessConfigSortNoByOrder()
this.initDefaultProcessConfigSortable()
},
deleteDefaultProcessConfigRow () {
if (!this.defaultProcessConfigSelectionRows || this.defaultProcessConfigSelectionRows.length === 0) {
this.$message.warning('请先勾选要删除的行')
return
}
const selectedRows = this.defaultProcessConfigSelectionRows.slice()
this.$confirm(`确认删除选中的 ${selectedRows.length} 条默认工序吗?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
const selectedKeyMap = {}
const persistedCodeMap = {}
selectedRows.forEach(item => {
if (item && item._rowKey) {
selectedKeyMap[item._rowKey] = true
}
const persistedCode = item && item._persistedCode ? String(item._persistedCode).trim() : ''
const persistedCodeKey = persistedCode.toLowerCase()
if (persistedCode && !persistedCodeMap[persistedCodeKey]) {
persistedCodeMap[persistedCodeKey] = persistedCode
}
})
const nextRows = this.defaultProcessConfigRows.filter(row => {
return !(row && row._rowKey && selectedKeyMap[row._rowKey])
})
const applyDeletedRowsToUi = () => {
this.defaultProcessConfigRows = nextRows
this.resetDefaultProcessConfigSortNoByOrder()
this.clearDefaultProcessConfigSelection()
this.initDefaultProcessConfigSortable()
}
const persistedCodes = Object.keys(persistedCodeMap).map(key => persistedCodeMap[key])
if (persistedCodes.length === 0) {
applyDeletedRowsToUi()
this.$message.success('删除成功')
return
}
const inData = {
site: '*',
buNo: '*',
updateBy: this.$store.state.user.name,
processCodes: persistedCodes
}
this.defaultProcessConfigDeleteLoading = true
deleteProofTrackingProcessColumnsManage(inData).then(({ data }) => {
if (!(data && data.code === 0)) {
this.$message.error((data && data.msg) || '删除默认工序失败')
return
}
applyDeletedRowsToUi()
this.$message.success(data.msg || '删除成功')
//
this.queryProcessColumns().then(() => {
this.queryBuProcessConfig()
this.getDataList()
this.refreshTrackingTableLayout()
})
}).catch(() => {
this.$message.error('删除默认工序异常')
}).finally(() => {
this.defaultProcessConfigDeleteLoading = false
})
}).catch(() => {
//
})
},
normalizeDefaultProcessConfigRowsForSave () {
const sourceRows = Array.isArray(this.defaultProcessConfigRows) ? this.defaultProcessConfigRows : []
const normalizedRows = []
const usedCodeMap = {}
for (let i = 0; i < sourceRows.length; i++) {
const row = sourceRows[i] || {}
const rowNo = i + 1
const code = row.code == null ? '' : String(row.code).trim()
const codeKey = code.toLowerCase()
const label = row.label == null ? '' : String(row.label).trim()
if (!code) {
this.$message.warning(`${rowNo}行的工序编码不能为空`)
return null
}
if (usedCodeMap[codeKey]) {
this.$message.warning(`工序编码【${code}】重复,请检查`)
return null
}
if (!label) {
this.$message.warning(`${rowNo}行的工序名称不能为空`)
return null
}
const fieldData = this.buildDefaultProcessFieldsByCode(code)
if (!fieldData.planField || !fieldData.actualField || !fieldData.statusField) {
this.$message.warning(`${rowNo}行的工序编码格式无法生成字段,请调整编码`)
return null
}
usedCodeMap[codeKey] = true
normalizedRows.push({
code: code,
label: label,
planField: fieldData.planField,
actualField: fieldData.actualField,
statusField: fieldData.statusField,
sortNo: rowNo * 10,
activeFlag: String(row.activeFlag || 'Y').toUpperCase() === 'N' ? 'N' : 'Y'
})
}
return normalizedRows
},
saveDefaultProcessConfig () {
const submitRows = this.normalizeDefaultProcessConfigRowsForSave()
if (!submitRows) {
return
}
const executeSave = () => {
const inData = {
site: '*',
buNo: '*',
updateBy: this.$store.state.user.name,
rows: submitRows
}
saveProofTrackingProcessColumnsManage(inData).then(({ data }) => {
if (!(data && data.code === 0)) {
this.$message.error((data && data.msg) || '默认工序配置保存失败')
return
}
this.$message.success(data.msg || '默认工序配置已保存')
this.queryDefaultProcessConfig()
// /
this.queryProcessColumns().then(() => {
this.queryBuProcessConfig()
this.getDataList()
this.refreshTrackingTableLayout()
})
}).catch(() => {
this.$message.error('默认工序配置保存异常')
})
}
if (submitRows.length === 0) {
this.$confirm('当前将清空默认工序配置,保存后页面会回退到系统兜底配置,是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
executeSave()
}).catch(() => {
//
})
return
}
executeSave()
},
refreshTrackingTableLayout () {
this.$nextTick(() => {
const tableRef = this.$refs.trackingTable
@ -3607,6 +4025,68 @@ export default {
color: #409eff;
}
.default-process-config-dialog .default-process-config-actions {
margin-bottom: 8px;
}
.default-process-config-dialog .bu-process-config-tip {
display: flex;
align-items: center;
gap: 6px;
margin-bottom: 8px;
padding: 6px 10px;
border-radius: 4px;
background: #f4f8ff;
color: #5f6b7a;
font-size: 12px;
}
.default-process-config-dialog .bu-process-config-tip i {
color: #409eff;
}
.default-process-config-dialog .default-process-config-empty {
margin: 12px 0;
padding: 12px;
border: 1px dashed #dcdfe6;
border-radius: 4px;
color: #909399;
text-align: center;
}
.default-process-config-dialog .default-process-drag-handle {
color: #909399;
cursor: move;
font-size: 15px;
margin-right: 6px;
}
.default-process-config-dialog .default-process-order-index {
color: #606266;
font-size: 12px;
}
.default-process-config-dialog .el-table__body-wrapper tbody tr {
cursor: move;
}
.default-process-config-dialog .el-table__body-wrapper tbody tr .el-input__inner {
cursor: text;
}
.default-process-config-dialog .el-table__body-wrapper tbody tr .el-checkbox__inner,
.default-process-config-dialog .el-table__body-wrapper tbody tr .el-select .el-input__inner {
cursor: pointer;
}
.default-process-sortable-ghost > td {
background: #f0f9ff !important;
}
.default-process-sortable-chosen > td {
background: #ecf5ff !important;
}
.button-col {
margin-bottom: 8px;
}
@ -3834,5 +4314,11 @@ export default {
.end-link {
color: #a303ff;
}
.zxClass .cell {
line-height: 24px;
font-size: 12px;
height: 24px;
}
</style>
Loading…
Cancel
Save