2 changed files with 673 additions and 0 deletions
@ -0,0 +1,4 @@ |
|||
import { createAPI } from '@/utils/httpRequest.js' |
|||
|
|||
export const manufacturingStructuresBatchSave = data => |
|||
createAPI(`/plm/manufacturingStructures/batchSave`, 'post', data) |
|||
@ -0,0 +1,669 @@ |
|||
<template> |
|||
<div class="mod-config manufacturing-structures" tabindex="-1" ref="pageRoot"> |
|||
<el-form |
|||
:inline="true" |
|||
label-position="top" |
|||
:model="searchData" |
|||
@keyup.enter.native="getDataList()"> |
|||
<el-form-item label="父件编码"> |
|||
<el-input v-model="searchData.parentPartNo" clearable style="width: 120px" /> |
|||
</el-form-item> |
|||
<el-form-item label="父件描述"> |
|||
<el-input v-model="searchData.parentPartDesc" clearable style="width: 150px" /> |
|||
</el-form-item> |
|||
<el-form-item label="父件零件类型"> |
|||
<el-select v-model="searchData.parentPartType" clearable style="width: 150px"> |
|||
<el-option label="Manufactured" value="Manufactured"></el-option> |
|||
<el-option label="Manufactured Recipe" value="Manufactured Recipe"></el-option> |
|||
<el-option label="Purchased (raw)" value="Purchased (raw)"></el-option> |
|||
<el-option label="Purchased" value="Purchased"></el-option> |
|||
</el-select> |
|||
</el-form-item> |
|||
<el-form-item> |
|||
<span style="cursor: pointer" slot="label" @click="openPartStatusChooser('parent')"><a href="javascript:void(0)">父件零件状态</a></span> |
|||
<el-input v-model="searchData.parentPartStatus" @change="partStatusBlur('parent')" clearable style="width: 100px"></el-input> |
|||
</el-form-item> |
|||
<el-form-item label="子件编码"> |
|||
<el-input v-model="searchData.componentPart" clearable style="width: 120px" /> |
|||
</el-form-item> |
|||
<el-form-item label="子件描述"> |
|||
<el-input v-model="searchData.componentPartDesc" clearable style="width: 150px" /> |
|||
</el-form-item> |
|||
<el-form-item label="子件零件类型"> |
|||
<el-select v-model="searchData.componentPartType" clearable style="width: 150px"> |
|||
<el-option label="Manufactured" value="Manufactured"></el-option> |
|||
<el-option label="Manufactured Recipe" value="Manufactured Recipe"></el-option> |
|||
<el-option label="Purchased (raw)" value="Purchased (raw)"></el-option> |
|||
<el-option label="Purchased" value="Purchased"></el-option> |
|||
</el-select> |
|||
</el-form-item> |
|||
<el-form-item> |
|||
<span style="cursor: pointer" slot="label" @click="openPartStatusChooser('component')"><a href="javascript:void(0)">子件零件状态</a></span> |
|||
<el-input v-model="searchData.componentPartStatus" @change="partStatusBlur('component')" clearable style="width: 100px"></el-input> |
|||
</el-form-item> |
|||
<el-form-item label=" "> |
|||
<el-button type="primary" :loading="queryLoading" @click="getDataList()">查询</el-button> |
|||
<el-button @click="openFindReplaceDialog">编辑</el-button> |
|||
<el-button type="success" :loading="saveLoading" :disabled="!hasAnyDirty" @click="saveModifications">保存</el-button> |
|||
</el-form-item> |
|||
</el-form> |
|||
|
|||
<div class="rq"> |
|||
<el-table |
|||
ref="dataTable" |
|||
:height="height" |
|||
:data="dataList" |
|||
border |
|||
v-loading="dataListLoading" |
|||
:cell-class-name="tableCellClassName" |
|||
@cell-click="onTableCellClick" |
|||
style="width: 100%;"> |
|||
<el-table-column |
|||
v-for="(item, index) in columnList" |
|||
:key="index" |
|||
:sortable="item.columnSortable" |
|||
:prop="item.columnProp" |
|||
:header-align="item.headerAlign" |
|||
:show-overflow-tooltip="item.showOverflowTooltip" |
|||
:align="item.align" |
|||
:fixed="item.fixed === '' ? false : item.fixed" |
|||
:min-width="item.columnWidth" |
|||
:label="item.columnLabel"> |
|||
<template slot-scope="scope"> |
|||
<template v-if="!item.columnHidden && isEditableProp(item.columnProp)"> |
|||
<el-input |
|||
v-if="item.columnProp === 'componentPart'" |
|||
v-model="scope.row[item.columnProp]" |
|||
size="mini" |
|||
@blur="onComponentPartBlur(scope.row)" |
|||
:class="['ms-cell-editor', { 'ms-modified': isCellDirty(scope.row, item.columnProp) }]" /> |
|||
<el-input-number |
|||
v-else |
|||
v-model="scope.row[item.columnProp]" |
|||
:controls="false" |
|||
:step="0" |
|||
:precision="item.columnProp === 'qtyPerAssembly' ? 16 : 10" |
|||
size="mini" |
|||
class="ms-num-input" |
|||
:class="{ 'ms-modified': isCellDirty(scope.row, item.columnProp) }" |
|||
style="width: 100%" /> |
|||
</template> |
|||
<template v-else-if="!item.columnHidden && ['qtyPerAssembly', 'componentScrap', 'shrinkageFactor'].includes(item.columnProp)"> |
|||
<span>{{ formatNumber(scope.row[item.columnProp]) }}</span> |
|||
</template> |
|||
<template v-else-if="!item.columnHidden"> |
|||
<span>{{ scope.row[item.columnProp] }}</span> |
|||
</template> |
|||
</template> |
|||
</el-table-column> |
|||
</el-table> |
|||
</div> |
|||
|
|||
<Chooselist ref="baseList" @getBaseData="getBaseData"></Chooselist> |
|||
|
|||
<el-dialog |
|||
title="查找和替换" |
|||
:visible.sync="findReplaceVisible" |
|||
width="450px" |
|||
v-drag |
|||
:modal="false" |
|||
custom-class="ms-find-replace-dialog" |
|||
append-to-body |
|||
:close-on-click-modal="false" |
|||
@closed="onFindReplaceClosed"> |
|||
<div class="fr-container"> |
|||
<div class="fr-form"> |
|||
<div class="fr-row"> |
|||
<span class="fr-label">查找内容:</span> |
|||
<el-input v-model="frFindWhat" ref="frFindInput" clearable class="fr-input" /> |
|||
</div> |
|||
<div class="fr-row"> |
|||
<span class="fr-label">替换为:</span> |
|||
<el-input v-model="frReplaceWith" clearable class="fr-input" /> |
|||
</div> |
|||
</div> |
|||
<div class="fr-buttons"> |
|||
<el-button size="small" @click="frFindNext">查找下一个</el-button> |
|||
<el-button size="small" @click="findReplaceVisible = false">取消</el-button> |
|||
<el-button size="small" type="primary" plain @click="frReplaceOne">替换</el-button> |
|||
<el-button size="small" type="primary" plain @click="frReplaceAll">全部替换</el-button> |
|||
</div> |
|||
</div> |
|||
</el-dialog> |
|||
|
|||
<el-pagination |
|||
style="margin-top: 0px" |
|||
@size-change="sizeChangeHandle" |
|||
@current-change="currentChangeHandle" |
|||
:current-page="pageIndex" |
|||
:page-sizes="[20, 50, 100, 200, 500]" |
|||
:page-size="pageSize" |
|||
:total="totalPage" |
|||
layout="total, sizes, prev, pager, next, jumper" /> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import { completeWhereUsedSearch } from '@/api/part/completeWhereUsed.js' |
|||
import { manufacturingStructuresBatchSave } from '@/api/part/manufacturingStructures.js' |
|||
import { partInformationSearch } from '@/api/part/partInformation' |
|||
import Chooselist from '@/views/modules/common/Chooselist' |
|||
import { verifyData } from '@/api/chooselist/chooselist.js' |
|||
|
|||
const EDITABLE_PROPS = ['componentPart', 'qtyPerAssembly', 'componentScrap', 'shrinkageFactor'] |
|||
|
|||
export default { |
|||
name: 'ManufacturingStructures', |
|||
components: { |
|||
Chooselist |
|||
}, |
|||
data () { |
|||
return { |
|||
height: 200, |
|||
pageIndex: 1, |
|||
pageSize: 50, |
|||
totalPage: 0, |
|||
queryLoading: false, |
|||
saveLoading: false, |
|||
dataListLoading: false, |
|||
dataList: [], |
|||
chooselistStatusTarget: 'component', |
|||
activeFindColumn: null, |
|||
lastFindRowIndex: -1, |
|||
findHighlightRowIndex: -1, |
|||
findHighlightColumnProp: '', |
|||
findReplaceVisible: false, |
|||
frFindWhat: '', |
|||
frReplaceWith: '', |
|||
searchData: { |
|||
site: this.$store.state.user.site, |
|||
parentPartNo: '', |
|||
parentPartDesc: '', |
|||
parentPartType: '', |
|||
parentPartStatus: '', |
|||
componentPart: '', |
|||
componentPartDesc: '', |
|||
componentPartType: '', |
|||
componentPartStatus: '', |
|||
page: 1, |
|||
limit: 50 |
|||
}, |
|||
columnList: [ |
|||
{ columnProp: 'parentPartNo', columnLabel: '父件编码', headerAlign: 'center', align: 'left', columnSortable: false, columnHidden: false, showOverflowTooltip: true, fixed: '', columnWidth: 120 }, |
|||
{ columnProp: 'parentPartDesc', columnLabel: '父件描述', headerAlign: 'center', align: 'left', columnSortable: false, columnHidden: false, showOverflowTooltip: true, fixed: '', columnWidth: 180 }, |
|||
{ columnProp: 'parentPartType', columnLabel: '父件零件类型', headerAlign: 'center', align: 'center', columnSortable: false, columnHidden: false, showOverflowTooltip: true, fixed: '', columnWidth: 120 }, |
|||
{ columnProp: 'parentPartStatus', columnLabel: '父件零件状态', headerAlign: 'center', align: 'center', columnSortable: false, columnHidden: false, showOverflowTooltip: true, fixed: '', columnWidth: 100 }, |
|||
{ columnProp: 'parentPartStatusDesc', columnLabel: '父件零件状态描述', headerAlign: 'center', align: 'left', columnSortable: false, columnHidden: false, showOverflowTooltip: true, fixed: '', columnWidth: 120 }, |
|||
{ columnProp: 'engChgLevel', columnLabel: 'BOM版本', headerAlign: 'center', align: 'center', columnSortable: false, columnHidden: false, showOverflowTooltip: true, fixed: '', columnWidth: 90 }, |
|||
{ columnProp: 'alternativeNo', columnLabel: '替代编码', headerAlign: 'center', align: 'center', columnSortable: false, columnHidden: false, showOverflowTooltip: true, fixed: '', columnWidth: 110 }, |
|||
{ columnProp: 'bomDetailStatus', columnLabel: '替代状态', headerAlign: 'center', align: 'center', columnSortable: false, columnHidden: false, showOverflowTooltip: true, fixed: '', columnWidth: 100 }, |
|||
{ columnProp: 'lineItemNo', columnLabel: '行号', headerAlign: 'center', align: 'center', columnSortable: false, columnHidden: false, showOverflowTooltip: true, fixed: '', columnWidth: 80 }, |
|||
{ columnProp: 'lineSequence', columnLabel: '行序', headerAlign: 'center', align: 'center', columnSortable: false, columnHidden: false, showOverflowTooltip: true, fixed: '', columnWidth: 80 }, |
|||
{ columnProp: 'componentPart', columnLabel: '子件编码', headerAlign: 'center', align: 'left', columnSortable: false, columnHidden: false, showOverflowTooltip: true, fixed: '', columnWidth: 120 }, |
|||
{ columnProp: 'componentPartDesc', columnLabel: '子件描述', headerAlign: 'center', align: 'left', columnSortable: false, columnHidden: false, showOverflowTooltip: true, fixed: '', columnWidth: 180 }, |
|||
{ columnProp: 'componentPartType', columnLabel: '子件零件类型', headerAlign: 'center', align: 'center', columnSortable: false, columnHidden: false, showOverflowTooltip: true, fixed: '', columnWidth: 120 }, |
|||
{ columnProp: 'issueType', columnLabel: '生产属性', headerAlign: 'center', align: 'center', columnSortable: false, columnHidden: false, showOverflowTooltip: true, fixed: '', columnWidth: 150 }, |
|||
{ columnProp: 'componentPartStatus', columnLabel: '子件零件状态', headerAlign: 'center', align: 'center', columnSortable: false, columnHidden: false, showOverflowTooltip: true, fixed: '', columnWidth: 100 }, |
|||
{ columnProp: 'componentPartStatusDesc', columnLabel: '子件零件状态描述', headerAlign: 'center', align: 'left', columnSortable: false, columnHidden: false, showOverflowTooltip: true, fixed: '', columnWidth: 120 }, |
|||
{ columnProp: 'bomType', columnLabel: '制造类型', headerAlign: 'center', align: 'center', columnSortable: false, columnHidden: false, showOverflowTooltip: true, fixed: '', columnWidth: 120 }, |
|||
{ columnProp: 'effPhaseInDate', columnLabel: '生效日期', headerAlign: 'center', align: 'center', columnSortable: false, columnHidden: false, showOverflowTooltip: true, fixed: '', columnWidth: 160 }, |
|||
{ columnProp: 'effPhaseOutDate', columnLabel: '失效日期', headerAlign: 'center', align: 'center', columnSortable: false, columnHidden: false, showOverflowTooltip: true, fixed: '', columnWidth: 160 }, |
|||
{ columnProp: 'qtyPerAssembly', columnLabel: '单位用量', headerAlign: 'center', align: 'right', columnSortable: false, columnHidden: false, showOverflowTooltip: true, fixed: '', columnWidth: 145 }, |
|||
{ columnProp: 'componentScrap', columnLabel: '调机量', headerAlign: 'center', align: 'right', columnSortable: false, columnHidden: false, showOverflowTooltip: true, fixed: '', columnWidth: 110 }, |
|||
{ columnProp: 'shrinkageFactor', columnLabel: '损耗率', headerAlign: 'center', align: 'right', columnSortable: false, columnHidden: false, showOverflowTooltip: true, fixed: '', columnWidth: 110 }, |
|||
{ columnProp: 'operationNo', columnLabel: '工序号', headerAlign: 'center', align: 'center', columnSortable: false, columnHidden: false, showOverflowTooltip: true, fixed: '', columnWidth: 90 }, |
|||
{ columnProp: 'issueToLoc', columnLabel: '发料库位', headerAlign: 'center', align: 'center', columnSortable: false, columnHidden: false, showOverflowTooltip: true, fixed: '', columnWidth: 110 }, |
|||
{ columnProp: 'noteText', columnLabel: '备注', headerAlign: 'center', align: 'left', columnSortable: false, columnHidden: false, showOverflowTooltip: true, fixed: '', columnWidth: 160 }, |
|||
{ columnProp: 'consumptionItem', columnLabel: '消耗项目', headerAlign: 'center', align: 'center', columnSortable: false, columnHidden: false, showOverflowTooltip: true, fixed: '', columnWidth: 110 }, |
|||
{ columnProp: 'printUnit', columnLabel: '单位', headerAlign: 'center', align: 'center', columnSortable: false, columnHidden: false, showOverflowTooltip: true, fixed: '', columnWidth: 80 } |
|||
] |
|||
} |
|||
}, |
|||
computed: { |
|||
hasAnyDirty () { |
|||
return this.dataList.some(row => EDITABLE_PROPS.some(p => this.isCellDirty(row, p))) |
|||
}, |
|||
findReplaceColumnLabel () { |
|||
if (!this.activeFindColumn) return '(未选择,请先单击可编辑单元格)' |
|||
const col = this.columnList.find(c => c.columnProp === this.activeFindColumn) |
|||
return col ? col.columnLabel : this.activeFindColumn |
|||
} |
|||
}, |
|||
watch: { |
|||
searchData: { |
|||
deep: true, |
|||
handler: function () { |
|||
if (typeof this.searchData.componentPart === 'string') { |
|||
this.searchData.componentPart = this.searchData.componentPart.toUpperCase() |
|||
} |
|||
if (typeof this.searchData.parentPartNo === 'string') { |
|||
this.searchData.parentPartNo = this.searchData.parentPartNo.toUpperCase() |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
mounted () { |
|||
this.$nextTick(() => { |
|||
this.height = window.innerHeight - 170 |
|||
}) |
|||
if (this.$refs.pageRoot && this.$refs.pageRoot.focus) { |
|||
this.$refs.pageRoot.focus() |
|||
} |
|||
}, |
|||
methods: { |
|||
isEditableProp (prop) { |
|||
return EDITABLE_PROPS.includes(prop) |
|||
}, |
|||
openFindReplaceDialog () { |
|||
if (!this.activeFindColumn) { |
|||
this.$message.warning('请先单击选择一个可编辑列中的单元格(子件编码、单位用量、调机量、损耗率)') |
|||
return |
|||
} |
|||
if (this.lastFindRowIndex >= 0 && this.lastFindRowIndex < this.dataList.length) { |
|||
const val = this.dataList[this.lastFindRowIndex][this.activeFindColumn] |
|||
this.frFindWhat = val === null || val === undefined ? '' : String(val) |
|||
} |
|||
this.findReplaceVisible = true |
|||
this.$nextTick(() => { |
|||
if (this.$refs.frFindInput && this.$refs.frFindInput.focus) { |
|||
this.$refs.frFindInput.focus() |
|||
} |
|||
}) |
|||
}, |
|||
onFindReplaceClosed () { |
|||
this.frFindWhat = '' |
|||
this.frReplaceWith = '' |
|||
}, |
|||
tableCellClassName ({ row, column, rowIndex }) { |
|||
if (rowIndex === this.findHighlightRowIndex && column.property === this.findHighlightColumnProp) { |
|||
return 'ms-find-highlight' |
|||
} |
|||
return '' |
|||
}, |
|||
onTableCellClick (row, column) { |
|||
const p = column.property |
|||
if (!this.isEditableProp(p)) return |
|||
this.activeFindColumn = p |
|||
const idx = this.dataList.indexOf(row) |
|||
this.lastFindRowIndex = idx |
|||
this.findHighlightRowIndex = idx |
|||
this.findHighlightColumnProp = p |
|||
}, |
|||
normalizeRowFromServer (raw) { |
|||
const row = { ...raw } |
|||
const qtyRaw = Number(row.qtyPerAssembly) |
|||
const productFlag = qtyRaw < 0 ? 'byProduct' : 'component' |
|||
row.productFlag = productFlag |
|||
row.qtyPerAssembly = productFlag === 'byProduct' ? Math.abs(qtyRaw) : qtyRaw |
|||
if (row.componentPart) { |
|||
row.componentPart = String(row.componentPart).trim().toUpperCase() |
|||
} |
|||
row.componentScrap = row.componentScrap === null || row.componentScrap === undefined ? null : Number(row.componentScrap) |
|||
row.shrinkageFactor = row.shrinkageFactor === null || row.shrinkageFactor === undefined ? null : Number(row.shrinkageFactor) |
|||
row._original = { |
|||
componentPart: row.componentPart, |
|||
qtyPerAssembly: row.qtyPerAssembly, |
|||
componentScrap: row.componentScrap, |
|||
shrinkageFactor: row.shrinkageFactor |
|||
} |
|||
return row |
|||
}, |
|||
snapshotOriginal (row) { |
|||
row._original = { |
|||
componentPart: row.componentPart, |
|||
qtyPerAssembly: row.qtyPerAssembly, |
|||
componentScrap: row.componentScrap, |
|||
shrinkageFactor: row.shrinkageFactor |
|||
} |
|||
}, |
|||
normalizeForCompare (val, prop) { |
|||
if (prop === 'componentPart') { |
|||
return (val == null ? '' : String(val)).trim().toUpperCase() |
|||
} |
|||
if (val === null || val === undefined || val === '') return '' |
|||
const n = Number(val) |
|||
if (Number.isNaN(n)) return String(val).trim() |
|||
return String(n) |
|||
}, |
|||
isCellDirty (row, prop) { |
|||
if (!row || !row._original) return false |
|||
return this.normalizeForCompare(row[prop], prop) !== this.normalizeForCompare(row._original[prop], prop) |
|||
}, |
|||
cellMatchesFind (val, findWhat) { |
|||
const needle = (findWhat || '').trim() |
|||
if (needle === '') return false |
|||
const col = this.activeFindColumn |
|||
if (!col) return false |
|||
if (col === 'componentPart') { |
|||
return this.normalizeForCompare(val, col) === needle.toUpperCase() |
|||
} |
|||
return this.normalizeForCompare(val, col) === this.normalizeForCompare(needle, col) |
|||
}, |
|||
coerceColumnValue (prop, strVal) { |
|||
if (prop === 'componentPart') { |
|||
return (strVal || '').trim().toUpperCase() |
|||
} |
|||
const n = parseFloat(strVal) |
|||
if (Number.isNaN(n)) return null |
|||
return n |
|||
}, |
|||
frFindNext () { |
|||
const col = this.activeFindColumn |
|||
const needle = (this.frFindWhat || '').trim() |
|||
if (!col) { |
|||
this.$message.warning('未选择列') |
|||
return |
|||
} |
|||
if (needle === '') { |
|||
this.$message.warning('请输入查找内容') |
|||
return |
|||
} |
|||
const n = this.dataList.length |
|||
if (n === 0) return |
|||
const start = this.lastFindRowIndex + 1 |
|||
for (let k = 0; k < n; k++) { |
|||
const i = (start + k) % n |
|||
const val = this.dataList[i][col] |
|||
if (this.cellMatchesFind(val, needle)) { |
|||
this.lastFindRowIndex = i |
|||
this.findHighlightRowIndex = i |
|||
this.findHighlightColumnProp = col |
|||
this.$nextTick(() => this.scrollToRow(i)) |
|||
return |
|||
} |
|||
} |
|||
this.$message.info('未找到匹配项') |
|||
}, |
|||
frReplaceOne () { |
|||
const col = this.findHighlightColumnProp |
|||
const rowIdx = this.findHighlightRowIndex |
|||
if (col == null || rowIdx < 0 || rowIdx >= this.dataList.length) { |
|||
this.$message.warning('请先使用「查找」定位单元格') |
|||
return |
|||
} |
|||
const row = this.dataList[rowIdx] |
|||
const nextVal = this.coerceColumnValue(col, this.frReplaceWith) |
|||
if (nextVal === null && col !== 'componentPart') { |
|||
this.$message.warning('替换为的数值无效') |
|||
return |
|||
} |
|||
this.$set(row, col, nextVal === null ? '' : nextVal) |
|||
}, |
|||
frReplaceAll () { |
|||
const col = this.activeFindColumn |
|||
const needle = (this.frFindWhat || '').trim() |
|||
if (!col) { |
|||
this.$message.warning('未选择列') |
|||
return |
|||
} |
|||
if (needle === '') { |
|||
this.$message.warning('请输入查找内容') |
|||
return |
|||
} |
|||
let cnt = 0 |
|||
this.dataList.forEach(row => { |
|||
if (this.cellMatchesFind(row[col], needle)) { |
|||
const nextVal = this.coerceColumnValue(col, this.frReplaceWith) |
|||
if (nextVal !== null || col === 'componentPart') { |
|||
this.$set(row, col, nextVal === null ? '' : nextVal) |
|||
cnt++ |
|||
} |
|||
} |
|||
}) |
|||
this.$message.success(`已替换 ${cnt} 处`) |
|||
}, |
|||
scrollToRow (rowIndex) { |
|||
const table = this.$refs.dataTable |
|||
if (!table || !table.$el) return |
|||
const rows = table.$el.querySelectorAll('.el-table__body-wrapper tbody tr') |
|||
if (rows[rowIndex]) { |
|||
rows[rowIndex].scrollIntoView({ block: 'nearest', behavior: 'smooth' }) |
|||
} |
|||
}, |
|||
onComponentPartBlur (row) { |
|||
if (row.componentPart) { |
|||
row.componentPart = String(row.componentPart).trim().toUpperCase() |
|||
} |
|||
}, |
|||
openPartStatusChooser (target) { |
|||
this.chooselistStatusTarget = target |
|||
this.$nextTick(() => { |
|||
const v = target === 'parent' ? this.searchData.parentPartStatus : this.searchData.componentPartStatus |
|||
this.$refs.baseList.init(125, v) |
|||
}) |
|||
}, |
|||
getBaseData (val) { |
|||
if (val && val.part_status) { |
|||
if (this.chooselistStatusTarget === 'parent') { |
|||
this.searchData.parentPartStatus = val.part_status |
|||
} else { |
|||
this.searchData.componentPartStatus = val.part_status |
|||
} |
|||
} |
|||
}, |
|||
partStatusBlur (target) { |
|||
const field = target === 'parent' ? 'parentPartStatus' : 'componentPartStatus' |
|||
const tempData = { |
|||
tagno: 125, |
|||
conditionSql: " and part_status = '" + this.searchData[field] + "'" + " and site = '" + this.searchData.site + "'" |
|||
} |
|||
verifyData(tempData).then(({ data }) => { |
|||
if (data && data.code === 0) { |
|||
if (data.baseListData.length > 0) { |
|||
this.searchData[field] = data.baseListData[0].part_status |
|||
} else { |
|||
this.searchData[field] = '' |
|||
} |
|||
} |
|||
}) |
|||
}, |
|||
formatNumber (value) { |
|||
if (value === null || value === undefined || value === '') return value |
|||
let numStr = String(value) |
|||
if (numStr.includes('e') || numStr.includes('E')) { |
|||
return Number(value).toLocaleString('fullwide', { useGrouping: false, maximumFractionDigits: 10 }) |
|||
} |
|||
return value |
|||
}, |
|||
sizeChangeHandle (val) { |
|||
this.pageSize = val |
|||
this.pageIndex = 1 |
|||
this.getDataList() |
|||
}, |
|||
currentChangeHandle (val) { |
|||
this.pageIndex = val |
|||
this.getDataList() |
|||
}, |
|||
hasSearchCondition () { |
|||
const s = this.searchData |
|||
return !!(s.componentPart || s.componentPartDesc || s.componentPartType || s.componentPartStatus || |
|||
s.parentPartNo || s.parentPartDesc || s.parentPartType || s.parentPartStatus) |
|||
}, |
|||
getDataList () { |
|||
if (!this.hasSearchCondition()) { |
|||
this.$message.warning('请至少填写一项查询条件') |
|||
return |
|||
} |
|||
this.searchData.limit = this.pageSize |
|||
this.searchData.page = this.pageIndex |
|||
this.queryLoading = true |
|||
this.dataListLoading = true |
|||
completeWhereUsedSearch(this.searchData) |
|||
.then(({ data }) => { |
|||
if (data.code === 0) { |
|||
const list = (data.page.list || []).map(r => this.normalizeRowFromServer(r)) |
|||
this.dataList = list |
|||
this.pageIndex = data.page.currPage |
|||
this.pageSize = data.page.pageSize |
|||
this.totalPage = data.page.totalCount |
|||
this.activeFindColumn = null |
|||
this.lastFindRowIndex = -1 |
|||
this.findHighlightRowIndex = -1 |
|||
this.findHighlightColumnProp = '' |
|||
} else { |
|||
this.$message.error(data.msg || '查询失败') |
|||
} |
|||
}) |
|||
.catch(() => { |
|||
this.$message.error('请求失败') |
|||
}) |
|||
.finally(() => { |
|||
this.queryLoading = false |
|||
this.dataListLoading = false |
|||
}) |
|||
}, |
|||
buildBomPayload (row) { |
|||
return { |
|||
site: row.site, |
|||
partNo: row.parentPartNo, |
|||
engChgLevel: row.engChgLevel, |
|||
bomType: row.bomType, |
|||
alternativeNo: row.alternativeNo == null ? '' : String(row.alternativeNo), |
|||
componentPart: row.componentPart, |
|||
qtyPerAssembly: row.qtyPerAssembly, |
|||
componentScrap: row.componentScrap, |
|||
shrinkageFactor: row.shrinkageFactor, |
|||
issueType: row.issueType, |
|||
operationNo: row.operationNo, |
|||
issueToLoc: row.issueToLoc, |
|||
noteText: row.noteText, |
|||
lineSequence: row.lineSequence, |
|||
consumptionItem: row.consumptionItem, |
|||
productFlag: row.productFlag || 'component', |
|||
lineItemNo: row.lineItemNo, |
|||
updateBy: this.$store.state.user.name |
|||
} |
|||
}, |
|||
verifyPartHasDrawing (partNo) { |
|||
return partInformationSearch({ |
|||
site: this.$store.state.user.site, |
|||
partNo, |
|||
limit: 1, |
|||
page: 1 |
|||
}).then(({ data }) => { |
|||
if (data && data.code === 0 && data.page.list.length > 0 && data.page.list[0].drawingNo) { |
|||
return true |
|||
} |
|||
this.$message.warning('子物料【' + partNo + '】未获取编码,不能保存!') |
|||
return false |
|||
}).catch(() => { |
|||
this.$message.error('验证子物料编码信息失败,请重试!') |
|||
return false |
|||
}) |
|||
}, |
|||
async saveModifications () { |
|||
const dirtyRows = this.dataList.filter(row => EDITABLE_PROPS.some(p => this.isCellDirty(row, p))) |
|||
if (dirtyRows.length === 0) { |
|||
this.$message.warning('没有需要保存的修改') |
|||
return |
|||
} |
|||
for (const row of dirtyRows) { |
|||
if (row.qtyPerAssembly === '' || row.qtyPerAssembly == null) { |
|||
this.$message.warning('单位用量不能为空') |
|||
return |
|||
} |
|||
if (Number(row.qtyPerAssembly) === 0) { |
|||
this.$message.warning('单位用量不能为0') |
|||
return |
|||
} |
|||
if (row.componentScrap === '' || row.componentScrap == null) { |
|||
this.$message.warning('调机量不能为空') |
|||
return |
|||
} |
|||
if (row.shrinkageFactor === '' || row.shrinkageFactor == null) { |
|||
this.$message.warning('损耗率不能为空') |
|||
return |
|||
} |
|||
if (row.productFlag === 'component' && (row.issueType === '' || row.issueType == null)) { |
|||
this.$message.warning('生产属性不能为空(子件行)') |
|||
return |
|||
} |
|||
} |
|||
const partNos = [...new Set(dirtyRows.map(r => r.componentPart).filter(Boolean))] |
|||
for (const p of partNos) { |
|||
const ok = await this.verifyPartHasDrawing(p) |
|||
if (!ok) return |
|||
} |
|||
const items = dirtyRows.map(r => this.buildBomPayload(r)) |
|||
this.saveLoading = true |
|||
manufacturingStructuresBatchSave({ items }) |
|||
.then(({ data }) => { |
|||
if (data && data.code === 0) { |
|||
this.$message.success('保存成功') |
|||
dirtyRows.forEach(r => this.snapshotOriginal(r)) |
|||
} else { |
|||
this.$alert((data && data.msg) || '保存失败', '错误', { confirmButtonText: '确定' }) |
|||
} |
|||
}) |
|||
.catch(() => { |
|||
this.$message.error('保存请求失败') |
|||
}) |
|||
.finally(() => { |
|||
this.saveLoading = false |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.ms-hint { |
|||
font-size: 12px; |
|||
color: #909399; |
|||
margin: 0 0 8px 0; |
|||
} |
|||
.ms-cell-editor.ms-modified >>> .el-input__inner { |
|||
color: #f56c6c; |
|||
} |
|||
.ms-num-input.ms-modified >>> .el-input__inner { |
|||
color: #f56c6c; |
|||
} |
|||
|
|||
/* 查找替换对话框样式 */ |
|||
.fr-container { |
|||
display: flex; |
|||
gap: 15px; |
|||
} |
|||
.fr-form { |
|||
flex: 1; |
|||
display: flex; |
|||
flex-direction: column; |
|||
gap: 15px; |
|||
margin-top: 5px; |
|||
} |
|||
.fr-row { |
|||
display: flex; |
|||
align-items: center; |
|||
} |
|||
.fr-label { |
|||
width: 70px; |
|||
font-size: 13px; |
|||
color: #606266; |
|||
} |
|||
.fr-input { |
|||
flex: 1; |
|||
} |
|||
.fr-buttons { |
|||
display: flex; |
|||
flex-direction: column; |
|||
gap: 10px; |
|||
width: 100px; |
|||
margin-top: -30px; |
|||
} |
|||
.fr-buttons .el-button { |
|||
margin-left: 0; |
|||
width: 100%; |
|||
} |
|||
</style> |
|||
|
|||
<style> |
|||
.manufacturing-structures .ms-find-highlight { |
|||
background-color: #fff3cd !important; |
|||
} |
|||
.ms-find-replace-dialog .el-dialog__body { |
|||
padding: 15px 20px 20px; |
|||
} |
|||
.ms-find-replace-dialog .el-dialog__header { |
|||
padding: 15px 20px 10px; |
|||
} |
|||
</style> |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue