You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3040 lines
113 KiB
3040 lines
113 KiB
<template>
|
|
<div class="mod-config">
|
|
<el-form :inline="true" :model="searchData" label-position="top" class="search-form">
|
|
<el-form-item label="BU">
|
|
<el-select v-model="searchData.buNo" clearable filterable placeholder="全部" style="width: 130px" @change="handleSearchBuChange">
|
|
<el-option
|
|
v-for="item in userBuList"
|
|
:key="`searchBu_${item.buNo}`"
|
|
:label="item.buDesc ? `${normalizeBuNo(item.buNo, searchData.site)}-${item.buDesc}` : normalizeBuNo(item.buNo, searchData.site)"
|
|
:value="normalizeBuNo(item.buNo, searchData.site)"
|
|
/>
|
|
</el-select>
|
|
</el-form-item>
|
|
<el-form-item label="项目编码">
|
|
<el-input v-model="searchData.projectNo" clearable placeholder="请输入项目编码" style="width: 140px" />
|
|
</el-form-item>
|
|
<el-form-item label="项目描述">
|
|
<el-input v-model="searchData.projectDesc" clearable placeholder="请输入项目描述" style="width: 160px" />
|
|
</el-form-item>
|
|
<el-form-item label="项目物料">
|
|
<el-input v-model="searchData.testPartNo" clearable placeholder="请输入项目物料" style="width: 140px" />
|
|
</el-form-item>
|
|
<el-form-item label="料号描述">
|
|
<el-input v-model="searchData.partDesc" clearable placeholder="请输入料号描述" style="width: 160px" />
|
|
</el-form-item>
|
|
<el-form-item label="客户编码">
|
|
<el-input v-model="searchData.customerNo" clearable placeholder="请输入客户编码" style="width: 120px" />
|
|
</el-form-item>
|
|
<el-form-item label="打样单号">
|
|
<el-input v-model="searchData.proofingNo" clearable placeholder="请输入打样单号" style="width: 150px" />
|
|
</el-form-item>
|
|
<el-form-item label="项目/物料同步">
|
|
<el-select v-model="searchData.projectPartSyncFlag" clearable placeholder="全部" style="width: 120px">
|
|
<el-option label="已同步" value="Y" />
|
|
<el-option label="未同步" value="N" />
|
|
</el-select>
|
|
</el-form-item>
|
|
<el-form-item label="打样单同步">
|
|
<el-select v-model="searchData.proofSyncFlag" clearable placeholder="全部" style="width: 120px">
|
|
<el-option label="已同步" value="Y" />
|
|
<el-option label="未同步" value="N" />
|
|
</el-select>
|
|
</el-form-item>
|
|
<el-form-item label="打样状态">
|
|
<el-select v-model="searchData.proofingStatus" clearable placeholder="全部" style="width: 120px">
|
|
<el-option label="进行中" value="进行中" />
|
|
<el-option label="打样完成" value="打样完成" />
|
|
<el-option label="草稿" value="草稿" />
|
|
</el-select>
|
|
<el-button type="primary" @click="getDataList('Y')">查询</el-button>
|
|
<el-button @click="resetSearch">重置</el-button>
|
|
</el-form-item>
|
|
<el-form-item class="button-group-col">
|
|
<el-row :gutter="8" type="flex" class="button-row" >
|
|
<el-button type="primary" @click="openOneKeyDialog">一键创建</el-button>
|
|
<!-- <el-button type="warning" @click="toggleBatchEdit">{{ batchEditMode ? '取消修改' : '批量修改' }}</el-button>
|
|
<el-button v-if="batchEditMode" type="success" @click="saveBatchPlan">保存修改</el-button>-->
|
|
<el-button type="warning" @click="openCreateProofDialog()">新增打样</el-button>
|
|
<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-row>
|
|
</el-form-item>
|
|
</el-form>
|
|
|
|
<el-table
|
|
ref="trackingTable"
|
|
:data="dataList"
|
|
border class="data-table"
|
|
stripe highlight-current-row
|
|
height="700"
|
|
v-loading="dataListLoading"
|
|
@selection-change="selectionChange"
|
|
@row-click="rowClick"
|
|
style="width: 100%; margin-top: 8px"
|
|
>
|
|
<!-- <el-table-column type="selection" width="45" />-->
|
|
<el-table-column prop="projectNo" label="项目编码" width="90" show-overflow-tooltip>
|
|
<template slot-scope="scope">
|
|
<span :class="getProjectPartSyncTextClass(scope.row)">{{ scope.row.projectNo || '-' }}</span>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="projectDesc" label="项目描述" width="120" show-overflow-tooltip>
|
|
<template slot-scope="scope">
|
|
<span :class="getProjectPartSyncTextClass(scope.row)">{{ scope.row.projectDesc || '-' }}</span>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="testPartNo" label="项目物料" width="90" show-overflow-tooltip>
|
|
<template slot-scope="scope">
|
|
<span :class="getProjectPartSyncTextClass(scope.row)">{{ scope.row.testPartNo || '-' }}</span>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="partDesc" label="物料描述" :fixed="'left'" width="150" show-overflow-tooltip>
|
|
<template slot-scope="scope">
|
|
<span :class="getProjectPartSyncTextClass(scope.row)">{{ scope.row.partDesc || '-' }}</span>
|
|
</template>
|
|
</el-table-column>
|
|
<!-- <el-table-column prop="customerNo" label="客户编码" width="110" show-overflow-tooltip />
|
|
<el-table-column prop="customerDesc" label="客户名称" width="130" show-overflow-tooltip />-->
|
|
<el-table-column prop="proofingNo" label="打样单号" width="90" show-overflow-tooltip>
|
|
<template slot-scope="scope">
|
|
<span :class="getProofSyncTextClass(scope.row)">{{ scope.row.proofingNo || '-' }}</span>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="proofingStatus" label="打样状态" width="60">
|
|
<template slot-scope="scope">
|
|
<a :style="{color: (scope.row.proofingStatus === '打样完成' || scope.row.proofingStatus === '打样结束') ? '#67c23a' : '#046e97'}">
|
|
{{ scope.row.proofingStatus || '进行中' }}</a>
|
|
</template>
|
|
</el-table-column>
|
|
|
|
<el-table-column
|
|
v-for="item in visibleProcessColumns"
|
|
:key="item.code"
|
|
:label="item.label"
|
|
width="120"
|
|
align="center"
|
|
header-align="center"
|
|
>
|
|
<template slot-scope="scope">
|
|
<div
|
|
v-if="isProcessColumnVisibleForRow(scope.row, item)"
|
|
:class="['process-cell', isProcessComplete(scope.row, item) ? 'is-complete' : '']"
|
|
>
|
|
<el-date-picker
|
|
v-if="batchEditMode"
|
|
v-model="scope.row[item.actualField]"
|
|
type="date"
|
|
value-format="yyyy-MM-dd"
|
|
format="yyyy-MM-dd"
|
|
placeholder="实际完成日期"
|
|
style="width: 120px"
|
|
/>
|
|
<div
|
|
v-else
|
|
class="process-content"
|
|
@mouseenter="handleProcessTooltipMouseEnter(scope.row, item, $event)"
|
|
@mousemove="handleProcessTooltipMouseMove($event)"
|
|
@mouseleave="handleProcessTooltipMouseLeave"
|
|
>
|
|
<el-date-picker
|
|
v-model="scope.row[item.actualField]"
|
|
type="date"
|
|
value-format="yyyy-MM-dd"
|
|
format="yyyy-MM-dd"
|
|
placeholder=""
|
|
style="width: 122px"
|
|
@change="handleProcessDateChange(scope.row, item, $event)"
|
|
/>
|
|
<el-button
|
|
class="process-complete-btn"
|
|
type="success"
|
|
size="mini"
|
|
plain v-show="!isProcessComplete(scope.row, item)"
|
|
:disabled="isProcessComplete(scope.row, item)"
|
|
@click.stop="markProcessComplete(scope.row, item)"
|
|
>√</el-button>
|
|
</div>
|
|
</div>
|
|
<div v-else class="process-cell process-cell--masked"></div>
|
|
</template>
|
|
</el-table-column>
|
|
|
|
<el-table-column label="Comments" width="220">
|
|
<template slot-scope="scope">
|
|
<div class="comments-cell" @dblclick.stop="startCommentsEdit(scope.row)">
|
|
<template v-if="batchEditMode">
|
|
<el-input
|
|
v-model="scope.row.comments"
|
|
class="comments-edit-input"
|
|
size="mini"
|
|
clearable
|
|
placeholder="请输入Comments"
|
|
/>
|
|
</template>
|
|
<template v-else-if="isCommentsEditing(scope.row)">
|
|
<el-input
|
|
v-model="commentsDraft"
|
|
v-focus-comments-input="isCommentsEditing(scope.row)"
|
|
:ref="'commentsInput_' + scope.row.trackingId"
|
|
:id="'commentsInput_' + scope.row.trackingId"
|
|
class="comments-edit-input"
|
|
size="mini"
|
|
clearable
|
|
placeholder="请输入,回车也可保存"
|
|
@keydown.enter.native.prevent="saveCommentsEdit(scope.row)"
|
|
@keyup.esc.native="cancelCommentsEdit"
|
|
@blur="handleCommentsBlur(scope.row)"
|
|
/>
|
|
<el-button
|
|
class="comments-save-btn"
|
|
type="success"
|
|
size="mini"
|
|
plain
|
|
:loading="commentsSaveLoading"
|
|
@mousedown.native.prevent
|
|
@click.stop="saveCommentsEdit(scope.row)"
|
|
>√</el-button>
|
|
</template>
|
|
<span v-else class="comments-text" :title="scope.row.comments || ''">{{ scope.row.comments || '-' }}</span>
|
|
</div>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column label="操作" fixed="right" width="150" align="center">
|
|
<template slot-scope="scope">
|
|
<!-- <a class="action-link" @click="syncToNpi(scope.row)">同步NPI</a>-->
|
|
<!-- <a class="action-link" @click="openCreateProofDialog(scope.row)">新增打样</a>-->
|
|
<a @click="openOneKeyDialog('edit', scope.row)">修改</a>
|
|
<a class="action-link delete-link" @click="deleteProof(scope.row)">删除</a>
|
|
<a class="action-link end-link" v-if="scope.row.proofingStatus !== '打样完成'" @click="finishProof(scope.row)">打样完成</a>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
|
|
<el-pagination
|
|
@size-change="sizeChangeHandle"
|
|
@current-change="currentChangeHandle"
|
|
:current-page="pageIndex"
|
|
:page-sizes="[10, 20, 50, 100]"
|
|
:page-size="pageSize"
|
|
:total="totalPage"
|
|
layout="total, sizes, prev, pager, next, jumper"
|
|
style="margin-top: 12px; text-align: right"
|
|
/>
|
|
|
|
<div
|
|
v-show="processTooltip.visible"
|
|
class="process-history-tooltip"
|
|
:style="{
|
|
left: `${processTooltip.left}px`,
|
|
top: `${processTooltip.top}px`
|
|
}"
|
|
>{{ processTooltip.content }}</div>
|
|
|
|
<el-dialog
|
|
title="事业部进度展示设置"
|
|
:visible.sync="buProcessConfigDialogVisible"
|
|
width="900px"
|
|
:close-on-click-modal="false"
|
|
custom-class="bu-process-config-dialog"
|
|
>
|
|
<el-table :data="buProcessConfigRows" border stripe max-height="560">
|
|
<el-table-column prop="buDesc" label="事业部名称" width="100" show-overflow-tooltip />
|
|
<el-table-column label="可见进度列表" min-width="450" class-name="bu-process-list-column">
|
|
<template slot-scope="scope">
|
|
<el-checkbox-group
|
|
v-model="scope.row.processCodes"
|
|
@change="handleBuProcessCodesChange(scope.row)"
|
|
>
|
|
<el-checkbox
|
|
v-for="column in processColumns"
|
|
:key="`${scope.row.buNo}_${column.code}`"
|
|
:label="column.code"
|
|
>{{ column.label }}</el-checkbox>
|
|
</el-checkbox-group>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
|
|
<div slot="footer">
|
|
<el-button @click="buProcessConfigDialogVisible = false">取消</el-button>
|
|
<el-button type="primary" @click="saveBuProcessConfig">保存设置</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">
|
|
<el-col :span="6" v-show="isOneKeyCreateFieldVisible('buNo')">
|
|
<el-form-item label="BU" required>
|
|
<el-select v-model="oneKeyForm.buNo" placeholder="请选择" style="width: 100%">
|
|
<el-option v-for="item in userBuList" :key="item.buNo" :label="item.buDesc" :value="item.buNo"></el-option>
|
|
</el-select>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="6" v-show="isOneKeyCreateFieldVisible('projectNo')">
|
|
<el-form-item label="项目编码">
|
|
<el-input v-model="oneKeyForm.projectNo" style="width: 100%"></el-input>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="12" v-show="isOneKeyCreateFieldVisible('projectDesc')">
|
|
<el-form-item label="项目名称">
|
|
<el-input v-model="oneKeyForm.projectDesc" style="width: 100%"></el-input>
|
|
</el-form-item>
|
|
</el-col>
|
|
</el-row>
|
|
|
|
<el-row :gutter="16">
|
|
<el-col :span="6" v-show="isOneKeyCreateFieldVisible('customerNo')">
|
|
<el-form-item>
|
|
<span slot="label" class="big-label">
|
|
<a href="javascript:void(0)" @click="getBaseList(509)">客户编码</a>
|
|
<a href="javascript:void(0)" @click="newCustomer">(新客户)</a>
|
|
</span>
|
|
<el-input v-model="oneKeyForm.customerNo" @blur="customerNoBlur" style="width: 100%"></el-input>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="12" v-show="isOneKeyCreateFieldVisible('customerDesc')">
|
|
<el-form-item label="客户名称">
|
|
<el-input v-model="oneKeyForm.customerDesc" disabled style="width: 100%"></el-input>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="6" v-show="isOneKeyCreateFieldVisible('cProjectRegion')">
|
|
<el-form-item label="区域">
|
|
<el-select v-model="oneKeyForm.cProjectRegion" placeholder="请选择" clearable style="width: 100%">
|
|
<el-option
|
|
v-for="i in cProjectRegionList"
|
|
:key="i.cProjectRegion"
|
|
:label="i.cProjectRegion"
|
|
:value="i.cProjectRegion">
|
|
</el-option>
|
|
</el-select>
|
|
</el-form-item>
|
|
</el-col>
|
|
</el-row>
|
|
|
|
<el-row :gutter="16">
|
|
<el-col :span="6" v-show="isOneKeyCreateFieldVisible('projectCreationDate')">
|
|
<el-form-item label="立项日期">
|
|
<el-date-picker
|
|
v-model="oneKeyForm.projectCreationDate"
|
|
type="date"
|
|
value-format="yyyy-MM-dd"
|
|
placeholder="选择日期"
|
|
style="width: 100%">
|
|
</el-date-picker>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="6" v-show="isOneKeyCreateFieldVisible('needDate')">
|
|
<el-form-item label="预计完成日期">
|
|
<el-date-picker
|
|
v-model="oneKeyForm.needDate"
|
|
type="date"
|
|
value-format="yyyy-MM-dd"
|
|
placeholder="选择日期"
|
|
style="width: 100%">
|
|
</el-date-picker>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="6" v-show="isOneKeyCreateFieldVisible('projectCategory')">
|
|
<el-form-item label="项目分类">
|
|
<el-select v-model="oneKeyForm.projectCategory" placeholder="请选择" clearable style="width: 100%">
|
|
<el-option v-for="item in projectCategoryList" :key="item" :label="item" :value="item"></el-option>
|
|
</el-select>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="6" v-show="isOneKeyCreateFieldVisible('priorityLevel')">
|
|
<el-form-item label="优先级">
|
|
<el-select v-model="oneKeyForm.priorityLevel" placeholder="请选择" clearable style="width: 100%">
|
|
<el-option v-for="item in priorityList" :key="item" :label="item" :value="item"></el-option>
|
|
</el-select>
|
|
</el-form-item>
|
|
</el-col>
|
|
</el-row>
|
|
|
|
<el-row :gutter="16">
|
|
<el-col :span="6" v-show="isOneKeyCreateFieldVisible('testPartNo')">
|
|
<el-form-item label="项目料号">
|
|
<el-input v-model="oneKeyForm.testPartNo" style="width: 100%"></el-input>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="12" v-show="isOneKeyCreateFieldVisible('partDesc')">
|
|
<el-form-item label="料号描述">
|
|
<el-input v-model="oneKeyForm.partDesc" style="width: 100%"></el-input>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="6" v-show="isOneKeyCreateFieldVisible('partType')">
|
|
<el-form-item label="料号状态">
|
|
<el-select v-model="oneKeyForm.partType" placeholder="请选择" clearable style="width: 100%">
|
|
<el-option v-for="item in partTypeList" :key="item" :label="item" :value="item"></el-option>
|
|
</el-select>
|
|
</el-form-item>
|
|
</el-col>
|
|
</el-row>
|
|
|
|
<el-row :gutter="16">
|
|
<el-col :span="6" v-show="isOneKeyCreateFieldVisible('projectManager')">
|
|
<el-form-item>
|
|
<span slot="label" class="big-label"><a href="javascript:void(0)" @click="openRoleDialog('projectManager')">PM/Sales</a></span>
|
|
<el-input v-model="oneKeyForm.projectManagerName" disabled style="width: 100%"></el-input>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="6" v-show="isOneKeyCreateFieldVisible('projectOwner')">
|
|
<el-form-item>
|
|
<span slot="label" class="big-label"><a href="javascript:void(0)" @click="openRoleDialog('projectOwner')">PjM</a></span>
|
|
<el-input v-model="oneKeyForm.projectOwnerName" disabled style="width: 100%"></el-input>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="6" v-show="isOneKeyCreateFieldVisible('engineer')">
|
|
<el-form-item>
|
|
<span slot="label" class="big-label"><a href="javascript:void(0)" @click="openRoleDialog('engineer')">Engineer</a></span>
|
|
<el-input v-model="oneKeyForm.engineerName" disabled style="width: 100%"></el-input>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="6" v-show="isOneKeyCreateFieldVisible('cManufactureEngineer')">
|
|
<el-form-item>
|
|
<span slot="label" class="big-label"><a href="javascript:void(0)" @click="openRoleDialog('cManufactureEngineer')">MFG</a></span>
|
|
<el-input v-model="oneKeyForm.cManufactureEngineerName" disabled style="width: 100%"></el-input>
|
|
</el-form-item>
|
|
</el-col>
|
|
</el-row>
|
|
|
|
<el-row :gutter="16">
|
|
<el-col :span="6" v-show="isOneKeyCreateFieldVisible('cQualityEngineer6')">
|
|
<el-form-item>
|
|
<span slot="label" class="big-label"><a href="javascript:void(0)" @click="openRoleDialog('cQualityEngineer6')">IQC</a></span>
|
|
<el-input v-model="oneKeyForm.cQualityEngineer6Name" disabled style="width: 100%"></el-input>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="6" v-show="isOneKeyCreateFieldVisible('cQualityEngineer1')">
|
|
<el-form-item>
|
|
<span slot="label" class="big-label"><a href="javascript:void(0)" @click="openRoleDialog('cQualityEngineer1')">IPQC-Lam/Pri/Etch/Slit</a></span>
|
|
<el-input v-model="oneKeyForm.cQualityEngineer1Name" disabled style="width: 100%"></el-input>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="6" v-show="isOneKeyCreateFieldVisible('cQualityEngineer2')">
|
|
<el-form-item>
|
|
<span slot="label" class="big-label"><a href="javascript:void(0)" @click="openRoleDialog('cQualityEngineer2')">IPQC-Converting</a></span>
|
|
<el-input v-model="oneKeyForm.cQualityEngineer2Name" disabled style="width: 100%"></el-input>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="6" v-show="isOneKeyCreateFieldVisible('cQualityEngineer4')">
|
|
<el-form-item>
|
|
<span slot="label" class="big-label"><a href="javascript:void(0)" @click="openRoleDialog('cQualityEngineer4')">SQE</a></span>
|
|
<el-input v-model="oneKeyForm.cQualityEngineer4Name" disabled style="width: 100%"></el-input>
|
|
</el-form-item>
|
|
</el-col>
|
|
</el-row>
|
|
|
|
<el-row :gutter="16">
|
|
<el-col :span="6" v-show="isOneKeyCreateFieldVisible('cQualityEngineer3')">
|
|
<el-form-item>
|
|
<span slot="label" class="big-label"><a href="javascript:void(0)" @click="openRoleDialog('cQualityEngineer3')">FQC1</a></span>
|
|
<el-input v-model="oneKeyForm.cQualityEngineer3Name" disabled style="width: 100%"></el-input>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="6" v-show="isOneKeyCreateFieldVisible('cQualityEngineer5')">
|
|
<el-form-item>
|
|
<span slot="label" class="big-label"><a href="javascript:void(0)" @click="openRoleDialog('cQualityEngineer5')">FQC2</a></span>
|
|
<el-input v-model="oneKeyForm.cQualityEngineer5Name" disabled style="width: 100%"></el-input>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="6" v-show="isOneKeyCreateFieldVisible('ipqcHardTag')">
|
|
<el-form-item>
|
|
<span slot="label" class="big-label"><a href="javascript:void(0)" @click="openRoleDialog('ipqcHardTag')">IPQC-Hardtag</a></span>
|
|
<el-input v-model="oneKeyForm.ipqcHardTagName" disabled style="width: 100%"></el-input>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="6" v-show="isOneKeyCreateFieldVisible('cQualityEngineer7')">
|
|
<el-form-item>
|
|
<span slot="label" class="big-label"><a href="javascript:void(0)" @click="openRoleDialog('cQualityEngineer7')">前道工程师</a></span>
|
|
<el-input v-model="oneKeyForm.cQualityEngineer7Name" disabled style="width: 100%"></el-input>
|
|
</el-form-item>
|
|
</el-col>
|
|
</el-row>
|
|
|
|
<el-row :gutter="16">
|
|
<el-col :span="6" v-show="isOneKeyCreateFieldVisible('docEngineer')">
|
|
<el-form-item>
|
|
<span slot="label" class="big-label"><a href="javascript:void(0)" @click="openRoleDialog('docEngineer')">文档工程师</a></span>
|
|
<el-input v-model="oneKeyForm.docEngineerName" disabled style="width: 100%"></el-input>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="6" v-show="isOneKeyCreateFieldVisible('docEngineer2')">
|
|
<el-form-item>
|
|
<span slot="label" class="big-label"><a href="javascript:void(0)" @click="openRoleDialog('docEngineer2')">文档工程师2</a></span>
|
|
<el-input v-model="oneKeyForm.docEngineer2Name" disabled style="width: 100%"></el-input>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="6" v-show="isOneKeyCreateFieldVisible('projectStatus')">
|
|
<el-form-item label="项目状态">
|
|
<el-select v-model="oneKeyForm.projectStatus" clearable style="width: 100%">
|
|
<el-option v-for="item in projectStatusList" :key="item" :label="item" :value="item" />
|
|
</el-select>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="6" v-show="isOneKeyCreateFieldVisible('projectPhase')">
|
|
<el-form-item label="项目阶段">
|
|
<el-select v-model="oneKeyForm.projectPhase" clearable style="width: 100%">
|
|
<el-option
|
|
v-for="item in proofProjectPhaseList"
|
|
:key="item.projectPhase"
|
|
:label="item.projectPhase"
|
|
:value="item.projectPhase"
|
|
/>
|
|
</el-select>
|
|
</el-form-item>
|
|
</el-col>
|
|
</el-row>
|
|
|
|
<el-row :gutter="16">
|
|
<el-col :span="6" v-show="isOneKeyCreateFieldVisible('proofingNo')">
|
|
<el-form-item label="打样单号">
|
|
<el-input v-model="oneKeyForm.proofingNo" style="width: 100%"></el-input>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="6" v-show="isOneKeyCreateFieldVisible('proofingStatus')">
|
|
<el-form-item label="打样状态">
|
|
<el-select v-model="oneKeyForm.proofingStatus" clearable style="width: 100%">
|
|
<el-option label="草稿" value="草稿" />
|
|
<el-option label="进行中" value="进行中" />
|
|
<el-option label="打样完成" value="打样完成" />
|
|
<el-option label="打样结束" value="打样结束" />
|
|
</el-select>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="6" v-show="isOneKeyCreateFieldVisible('proofingNumber')">
|
|
<el-form-item label="数量">
|
|
<el-input v-model.number="oneKeyForm.proofingNumber" style="width: 100%"></el-input>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="6" v-show="isOneKeyCreateFieldVisible('planStartDate')">
|
|
<el-form-item label="打样开始日期">
|
|
<el-date-picker
|
|
v-model="oneKeyForm.planStartDate"
|
|
type="date"
|
|
value-format="yyyy-MM-dd"
|
|
placeholder="选择日期"
|
|
style="width: 100%">
|
|
</el-date-picker>
|
|
</el-form-item>
|
|
</el-col>
|
|
</el-row>
|
|
|
|
<el-row :gutter="16">
|
|
<el-col :span="6" v-show="isOneKeyCreateFieldVisible('requiredDeliveryDate')">
|
|
<el-form-item label="预计交付日期">
|
|
<el-date-picker
|
|
v-model="oneKeyForm.requiredDeliveryDate"
|
|
type="date"
|
|
value-format="yyyy-MM-dd"
|
|
placeholder="选择日期"
|
|
style="width: 100%">
|
|
</el-date-picker>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="isOneKeyCreateFieldVisible('requiredDeliveryDate') ? 18 : 24" v-show="isOneKeyCreateFieldVisible('remark')">
|
|
<el-form-item label="备注">
|
|
<el-input type="textarea" :rows="2" v-model="oneKeyForm.remark" style="width: 100%"></el-input>
|
|
</el-form-item>
|
|
</el-col>
|
|
</el-row>
|
|
</el-form>
|
|
<el-footer style="height: 40px; margin-top: 40px; text-align: center">
|
|
<el-button @click="oneKeyDialogVisible = false">取消</el-button>
|
|
<el-button type="primary" :loading="saveOneKeyLoading" @click="submitOneKey">{{ oneKeyDialogMode === 'edit' ? '保存修改' : '保存' }}</el-button>
|
|
</el-footer>
|
|
</el-dialog>
|
|
|
|
<el-dialog title="新增打样" :visible.sync="proofDialogVisible" width="768px" :close-on-click-modal="false">
|
|
<el-form :model="proofDialogData" label-position="top" class="proof-grid-form">
|
|
<el-row :gutter="16">
|
|
<el-col :span="6">
|
|
<el-form-item label="项目编码">
|
|
<el-input v-model="proofDialogData.projectNo" disabled style="width: 100%" />
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="12">
|
|
<el-form-item label="项目名称">
|
|
<el-input v-model="proofDialogData.projectDesc" disabled style="width: 100%" />
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="6">
|
|
<el-form-item label="BU">
|
|
<el-input v-model="proofDialogData.buNo" disabled style="width: 100%" />
|
|
</el-form-item>
|
|
</el-col>
|
|
</el-row>
|
|
|
|
<el-row :gutter="16">
|
|
<el-col :span="6">
|
|
<el-form-item label="客户编码">
|
|
<el-input v-model="proofDialogData.customerNo" disabled style="width: 100%" />
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="12">
|
|
<el-form-item label="客户名称">
|
|
<el-input v-model="proofDialogData.customerDesc" disabled style="width: 100%" />
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="6">
|
|
<el-form-item label="项目料号">
|
|
<el-input v-model="proofDialogData.testPartNo" disabled style="width: 100%" />
|
|
</el-form-item>
|
|
</el-col>
|
|
</el-row>
|
|
|
|
<el-row :gutter="16">
|
|
<el-col :span="12">
|
|
<el-form-item label="料号描述">
|
|
<el-input v-model="proofDialogData.partDesc" disabled style="width: 100%" />
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="6">
|
|
<el-form-item label="项目分类" required>
|
|
<el-select v-model="proofDialogData.cProjectTypeDb" placeholder="请选择" clearable style="width: 100%">
|
|
<el-option
|
|
v-for="item in cProjectTypeDbList"
|
|
:key="item.cProjectTypeDb"
|
|
:label="item.cProjectTypeDb"
|
|
:value="item.cProjectTypeDb">
|
|
</el-option>
|
|
</el-select>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="6">
|
|
<el-form-item label="项目阶段" required>
|
|
<el-select v-model="proofDialogData.projectPhase" placeholder="请选择" clearable style="width: 100%">
|
|
<el-option
|
|
v-for="item in proofProjectPhaseList"
|
|
:key="item.projectPhase"
|
|
:label="item.projectPhase"
|
|
:value="item.projectPhase">
|
|
</el-option>
|
|
</el-select>
|
|
</el-form-item>
|
|
</el-col>
|
|
</el-row>
|
|
|
|
<el-row :gutter="16">
|
|
<el-col :span="6">
|
|
<el-form-item label="打样单号" required>
|
|
<el-input v-model="proofDialogData.proofingNo" style="width: 100%" />
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="6">
|
|
<el-form-item label="数量" required>
|
|
<el-input v-model="proofDialogData.proofingNumber" style="width: 100%" />
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="6">
|
|
<el-form-item label="打样状态">
|
|
<el-select v-model="proofDialogData.proofingStatus" placeholder="请选择" clearable style="width: 100%">
|
|
<el-option label="草稿" value="草稿"></el-option>
|
|
<el-option label="进行中" value="进行中"></el-option>
|
|
</el-select>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="6">
|
|
<el-form-item label="实际完成日期">
|
|
<el-date-picker
|
|
v-model="proofDialogData.actualityDeliveryDate"
|
|
type="date"
|
|
value-format="yyyy-MM-dd"
|
|
placeholder="选择日期"
|
|
style="width: 100%">
|
|
</el-date-picker>
|
|
</el-form-item>
|
|
</el-col>
|
|
</el-row>
|
|
|
|
<el-row :gutter="16">
|
|
<el-col :span="6">
|
|
<el-form-item label="打样开始日期" required>
|
|
<el-date-picker
|
|
v-model="proofDialogData.planStartDate"
|
|
type="date"
|
|
value-format="yyyy-MM-dd"
|
|
placeholder="选择日期"
|
|
style="width: 100%">
|
|
</el-date-picker>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="6">
|
|
<el-form-item label="预计完成日期" required>
|
|
<el-date-picker
|
|
v-model="proofDialogData.requiredDeliveryDate"
|
|
type="date"
|
|
value-format="yyyy-MM-dd"
|
|
placeholder="选择日期"
|
|
style="width: 100%">
|
|
</el-date-picker>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="12">
|
|
<el-form-item label="备注">
|
|
<el-input v-model="proofDialogData.remark" style="width: 100%" type="textarea" :rows="2"></el-input>
|
|
</el-form-item>
|
|
</el-col>
|
|
</el-row>
|
|
</el-form>
|
|
|
|
<el-footer style="height: 40px; margin-top: 40px; text-align: center">
|
|
<el-button @click="proofDialogVisible = false">取 消</el-button>
|
|
<el-button type="primary" :loading="proofSaveLoading" @click="saveProofRecord">保 存</el-button>
|
|
</el-footer>
|
|
</el-dialog>
|
|
|
|
<el-dialog title="更新工序状态" :visible.sync="processDialogVisible" width="620px" :close-on-click-modal="false">
|
|
<el-form :model="processForm" label-position="top" label-width="120px" :inline="true">
|
|
<el-form-item label="工序">
|
|
<el-input v-model="processForm.processName" disabled style="width: 180px" />
|
|
</el-form-item>
|
|
<el-form-item label="状态" required>
|
|
<el-select v-model="processForm.status" style="width: 180px">
|
|
<el-option label="未完成" value="未完成" />
|
|
<el-option label="进行中" value="进行中" />
|
|
<el-option label="已完成" value="已完成" />
|
|
</el-select>
|
|
</el-form-item>
|
|
<el-form-item label="实际完成日期">
|
|
<el-date-picker v-model="processForm.actualDate" type="date" value-format="yyyy-MM-dd" format="yyyy-MM-dd" style="width: 180px" />
|
|
</el-form-item>
|
|
<el-form-item label="备注">
|
|
<el-input type="textarea" :rows="2" v-model="processForm.remark" style="width: 570px" />
|
|
</el-form-item>
|
|
</el-form>
|
|
|
|
<el-table :data="processHistoryRows" border stripe height="220" style="margin-top: 32px">
|
|
<el-table-column prop="changedDate" label="修改时间" width="120" />
|
|
<el-table-column prop="changedBy" label="修改人" width="70" />
|
|
<el-table-column prop="oldStatus" label="原状态" width="60" />
|
|
<el-table-column prop="newStatus" label="新状态" width="60" />
|
|
<el-table-column prop="oldActualDate" label="原实际" width="90" />
|
|
<el-table-column prop="newActualDate" label="新实际" width="90" />
|
|
<el-table-column prop="remark" label="备注" show-overflow-tooltip />
|
|
</el-table>
|
|
|
|
<div slot="footer">
|
|
<el-button @click="processDialogVisible = false">取消</el-button>
|
|
<el-button type="primary" :loading="saveProcessLoading" @click="submitProcessUpdate">保存</el-button>
|
|
</div>
|
|
</el-dialog>
|
|
|
|
<el-dialog
|
|
title="打样完成"
|
|
:visible.sync="finishDialogVisible"
|
|
width="260px"
|
|
:close-on-click-modal="false"
|
|
custom-class="finish-proof-dialog">
|
|
<div class="finish-dialog-tip">
|
|
<i class="el-icon-info"></i>
|
|
<span>确认后将直接标记为<strong class="finish-tip-highlight">打样完成</strong></span>
|
|
</div>
|
|
<el-form :model="finishForm" label-width="100px" class="finish-form">
|
|
<el-form-item label="实际完成日期" required>
|
|
<el-date-picker
|
|
v-model="finishForm.actualityDeliveryDate"
|
|
type="date"
|
|
value-format="yyyy-MM-dd"
|
|
format="yyyy-MM-dd"
|
|
placeholder="选择日期"
|
|
style="width: 100%"
|
|
/>
|
|
</el-form-item>
|
|
</el-form>
|
|
<div slot="footer">
|
|
<el-button @click="finishDialogVisible = false">取消</el-button>
|
|
<el-button type="primary" :loading="finishSaveLoading" @click="submitFinishProof">确认完成</el-button>
|
|
</div>
|
|
</el-dialog>
|
|
|
|
<el-dialog :title="roleDialogTitle" :visible.sync="roleDialogVisible" width="559px" :close-on-click-modal="false">
|
|
<el-form :inline="true" label-position="top" :model="roleSearchData" style="margin-left: 7px; margin-top: -5px;">
|
|
<el-form-item label="用户账号">
|
|
<el-input v-model="roleSearchData.username" clearable style="width: 110px"></el-input>
|
|
</el-form-item>
|
|
<el-form-item label="用户名">
|
|
<el-input v-model="roleSearchData.userDisplay" clearable style="width: 110px"></el-input>
|
|
</el-form-item>
|
|
<el-form-item label="是否在用">
|
|
<el-select filterable v-model="roleSearchData.active" clearable style="width: 140px">
|
|
<el-option label="是" value="Y"></el-option>
|
|
<el-option label="否" value="N"></el-option>
|
|
</el-select>
|
|
</el-form-item>
|
|
<el-form-item label=" ">
|
|
<el-button type="primary" style="padding: 3px 12px" @click="queryRoleDialogList">查询</el-button>
|
|
</el-form-item>
|
|
</el-form>
|
|
<el-table
|
|
:data="roleDialogList"
|
|
stripe
|
|
border
|
|
highlight-current-row
|
|
@row-dblclick="pickRole"
|
|
style="width: 100%">
|
|
<el-table-column prop="username" header-align="center" align="center" label="用户账号"></el-table-column>
|
|
<el-table-column prop="userDisplay" header-align="center" align="center" label="用户名"></el-table-column>
|
|
<el-table-column prop="active" header-align="center" align="center" label="是否在用"></el-table-column>
|
|
</el-table>
|
|
<el-footer style="height: 40px; margin-top: 10px; text-align: center">
|
|
<el-button @click="roleDialogVisible = false">关闭</el-button>
|
|
</el-footer>
|
|
</el-dialog>
|
|
|
|
<el-dialog title="新客户" :visible.sync="newCustomerFlag" width="348px" :close-on-click-modal="false" @close="closeNewCustomer">
|
|
<el-form :inline="true" label-position="top" :model="newCustomerData" style="margin-left: 7px; margin-top: -5px;">
|
|
<el-form-item label="客户名称">
|
|
<el-input v-model="newCustomerData.customerDesc" style="width: 313px"></el-input>
|
|
</el-form-item>
|
|
</el-form>
|
|
<el-footer style="height: 40px; margin-top: 10px; text-align: center">
|
|
<el-button type="primary" @click="saveNewCustomer">保存</el-button>
|
|
<el-button @click="newCustomerFlag = false">关闭</el-button>
|
|
</el-footer>
|
|
</el-dialog>
|
|
|
|
<Chooselist ref="baseList" @getBaseData="getBaseData"></Chooselist>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import {
|
|
batchUpdateProofTrackingPlan,
|
|
createProofTrackingRecord,
|
|
deleteProofTracking,
|
|
finishProofTracking,
|
|
oneKeyCreateProofTracking,
|
|
oneKeyUpdateProofTracking,
|
|
queryProofTrackingBuProcessConfig,
|
|
queryProofTrackingProcessHistory,
|
|
saveProofTrackingBuProcessConfig,
|
|
searchProjectInfoTracking,
|
|
searchProjectPartTracking,
|
|
searchProofTracking,
|
|
syncProofTracking,
|
|
syncProjectPartTracking,
|
|
updateProofTrackingComments,
|
|
updateProofTrackingProcess
|
|
} from '@/api/sampleTracking/sampleTracking'
|
|
import { getCustomerNo, saveNewCustomer } from '@/api/eam/eamProject.js'
|
|
import { getSiteAndBuByUserName } from '@/api/eam/eam.js'
|
|
import {
|
|
searchBusinessInfo,
|
|
searchBusinessInfo1,
|
|
searchBusinessInfo2,
|
|
searchBusinessInfo3,
|
|
searchBusinessInfo4,
|
|
searchBusinessInfo5,
|
|
searchBusinessInfo6,
|
|
searchBusinessInfo7,
|
|
searchBusinessInfo8
|
|
} from '@/api/factory/site.js'
|
|
import { queryCustomerList } from '@/api/customer/customer'
|
|
import Chooselist from '@/views/modules/common/Chooselist_eam'
|
|
|
|
function focusCommentsNativeInput (el, vnode) {
|
|
const doFocus = () => {
|
|
const componentInput = vnode && vnode.componentInstance && vnode.componentInstance.$refs
|
|
? vnode.componentInstance.$refs.input
|
|
: null
|
|
const inputEl = componentInput || (el && el.querySelector ? el.querySelector('input') : null)
|
|
if (!inputEl || typeof inputEl.focus !== 'function') {
|
|
return false
|
|
}
|
|
inputEl.focus()
|
|
const textLength = inputEl.value ? String(inputEl.value).length : 0
|
|
if (typeof inputEl.setSelectionRange === 'function') {
|
|
inputEl.setSelectionRange(textLength, textLength)
|
|
}
|
|
return true
|
|
}
|
|
if (doFocus()) {
|
|
return
|
|
}
|
|
setTimeout(doFocus, 0)
|
|
setTimeout(doFocus, 50)
|
|
setTimeout(doFocus, 100)
|
|
}
|
|
|
|
export default {
|
|
name: 'ProjectProofTracking',
|
|
directives: {
|
|
focusCommentsInput: {
|
|
inserted (el, binding, vnode) {
|
|
if (binding.value) {
|
|
focusCommentsNativeInput(el, vnode)
|
|
}
|
|
},
|
|
componentUpdated (el, binding, vnode) {
|
|
if (binding.value && !binding.oldValue) {
|
|
focusCommentsNativeInput(el, vnode)
|
|
}
|
|
}
|
|
}
|
|
},
|
|
components: {
|
|
Chooselist
|
|
},
|
|
data () {
|
|
return {
|
|
searchData: {
|
|
site: this.$store.state.user.site,
|
|
userName: this.$store.state.user.name,
|
|
projectNo: '',
|
|
projectDesc: '',
|
|
buNo: '',
|
|
testPartNo: '',
|
|
partDesc: '',
|
|
customerNo: '',
|
|
proofingNo: '',
|
|
projectPartSyncFlag: '',
|
|
proofSyncFlag: '',
|
|
proofingStatus: ''
|
|
},
|
|
processColumns: [
|
|
{ label: 'Raw Material', code: 'rawMaterial', planField: 'rawMaterialPlanDate', actualField: 'rawMaterialActualDate', statusField: 'rawMaterialStatus' },
|
|
{ label: 'Cylinder/Cutter', code: 'cylinderCutter', planField: 'cylinderCutterPlanDate', actualField: 'cylinderCutterActualDate', statusField: 'cylinderCutterStatus' },
|
|
{ label: 'Lamination', code: 'lamination', planField: 'laminationPlanDate', actualField: 'laminationActualDate', statusField: 'laminationStatus' },
|
|
{ label: 'Printing', code: 'printing', planField: 'printingPlanDate', actualField: 'printingActualDate', statusField: 'printingStatus' },
|
|
{ label: 'Etching', code: 'etching', planField: 'etchingPlanDate', actualField: 'etchingActualDate', statusField: 'etchingStatus' },
|
|
{ label: 'Slitting&Packing', code: 'slittingPacking', planField: 'slittingPackingPlanDate', actualField: 'slittingPackingActualDate', statusField: 'slittingPackingStatus' },
|
|
{ label: 'Bonding', code: 'bonding', planField: 'bondingPlanDate', actualField: 'bondingActualDate', statusField: 'bondingStatus' },
|
|
{ label: 'CL60/CL822', code: 'cl60Cl822', planField: 'cl60Cl822PlanDate', actualField: 'cl60Cl822ActualDate', statusField: 'cl60Cl822Status' },
|
|
{ label: 'Spotting', code: 'spotting', planField: 'spottingPlanDate', actualField: 'spottingActualDate', statusField: 'spottingStatus' },
|
|
{ label: 'Encoding', code: 'encoding', planField: 'encodingPlanDate', actualField: 'encodingActualDate', statusField: 'encodingStatus' },
|
|
{ label: 'Die cut', code: 'dieCut', planField: 'dieCutPlanDate', actualField: 'dieCutActualDate', statusField: 'dieCutStatus' },
|
|
{ label: 'Inspection', code: 'inspection', planField: 'inspectionPlanDate', actualField: 'inspectionActualDate', statusField: 'inspectionStatus' },
|
|
{ label: 'Delivery&Package', code: 'deliveryPackage', planField: 'deliveryPackagePlanDate', actualField: 'deliveryPackageActualDate', statusField: 'deliveryPackageStatus' }
|
|
],
|
|
buProcessConfigDialogVisible: false,
|
|
buProcessConfigRows: [],
|
|
buProcessConfigMap: {},
|
|
projectCategoryList: ['Low Risk', 'High Risk', 'Sustaining'],
|
|
cProjectRegionList: [
|
|
{ cProjectRegion: 'Global' },
|
|
{ cProjectRegion: 'APAC' },
|
|
{ cProjectRegion: 'CHINA' },
|
|
{ cProjectRegion: 'EU' },
|
|
{ cProjectRegion: 'US' },
|
|
{ cProjectRegion: 'Mexico' },
|
|
{ cProjectRegion: 'Other' }
|
|
],
|
|
priorityList: ['Low', 'Middle', 'High'],
|
|
projectStatusList: ['草稿', '进行中', '已关闭'],
|
|
partTypeList: ['Active', 'On hold', 'Cancel', 'EOL'],
|
|
partStatusList: ['草稿', '进行中', '已量产', '正式量产'],
|
|
cProjectTypeDbList: [
|
|
{ cProjectTypeDb: 'Sustaining' },
|
|
{ cProjectTypeDb: 'Low Risk' },
|
|
{ cProjectTypeDb: 'High Risk' }
|
|
],
|
|
proofProjectPhaseList: [
|
|
{ projectPhase: 'Prototype' },
|
|
{ projectPhase: 'Alpha' },
|
|
{ projectPhase: 'Beta' },
|
|
{ projectPhase: 'Pre-launch' }
|
|
],
|
|
// 一键创建字段白名单(仅 create 模式生效):后续确认要隐藏哪些字段时,只改这里即可。
|
|
oneKeyCreateVisibleFieldKeys: [
|
|
'buNo',
|
|
'projectNo',
|
|
'projectDesc',
|
|
'customerNo',
|
|
'customerDesc',
|
|
'cProjectRegion',
|
|
'projectCreationDate',
|
|
'needDate',
|
|
'projectCategory',
|
|
'priorityLevel',
|
|
'testPartNo',
|
|
'partDesc',
|
|
'partType',
|
|
'projectManager',
|
|
'projectOwner',
|
|
'engineer',
|
|
'cManufactureEngineer',
|
|
'cQualityEngineer6',
|
|
'cQualityEngineer1',
|
|
'cQualityEngineer2',
|
|
'cQualityEngineer4',
|
|
'cQualityEngineer3',
|
|
'cQualityEngineer5',
|
|
'ipqcHardTag',
|
|
'cQualityEngineer7',
|
|
'docEngineer',
|
|
'docEngineer2',
|
|
'projectStatus',
|
|
'projectPhase',
|
|
'proofingNo',
|
|
'proofingStatus',
|
|
'proofingNumber',
|
|
'planStartDate',
|
|
'requiredDeliveryDate',
|
|
'remark'
|
|
],
|
|
userBuList: [],
|
|
tagNo: '',
|
|
newCustomerFlag: false,
|
|
newCustomerData: {
|
|
customerDesc: ''
|
|
},
|
|
roleDialogVisible: false,
|
|
roleDialogTitle: '',
|
|
roleDialogField: '',
|
|
roleDialogApiKey: '0',
|
|
roleDialogList: [],
|
|
roleSearchData: {
|
|
site: this.$store.state.user.site,
|
|
username: '',
|
|
userDisplay: '',
|
|
active: '',
|
|
page: 1,
|
|
limit: 50
|
|
},
|
|
roleConfig: {
|
|
projectManager: { apiKey: '0', title: 'PM/Sales', nameField: 'projectManagerName' },
|
|
projectOwner: { apiKey: '1', title: 'PjM', nameField: 'projectOwnerName' },
|
|
cQualityEngineer1: { apiKey: '2', title: 'IPQC-Lam/Pri/Etch/Slit', nameField: 'cQualityEngineer1Name' },
|
|
cQualityEngineer2: { apiKey: '3', title: 'IPQC-Converting', nameField: 'cQualityEngineer2Name' },
|
|
cQualityEngineer3: { apiKey: '4', title: 'FQC1', nameField: 'cQualityEngineer3Name' },
|
|
cManufactureEngineer: { apiKey: '5', title: 'MFG', nameField: 'cManufactureEngineerName' },
|
|
engineer: { apiKey: '6', title: 'Engineer', nameField: 'engineerName' },
|
|
cQualityEngineer4: { apiKey: '7', title: 'SQE', nameField: 'cQualityEngineer4Name' },
|
|
cQualityEngineer5: { apiKey: '7', title: 'FQC2', nameField: 'cQualityEngineer5Name' },
|
|
cQualityEngineer6: { apiKey: '7', title: 'IQC', nameField: 'cQualityEngineer6Name' },
|
|
docEngineer: { apiKey: '7', title: '文档工程师', nameField: 'docEngineerName' },
|
|
ipqcHardTag: { apiKey: '7', title: 'IPQC-Hardtag', nameField: 'ipqcHardTagName' },
|
|
cQualityEngineer7: { apiKey: '7', title: '前道工程师', nameField: 'cQualityEngineer7Name' },
|
|
docEngineer2: { apiKey: '8', title: '文档工程师2', nameField: 'docEngineer2Name' }
|
|
},
|
|
dataList: [],
|
|
dataListLoading: false,
|
|
syncNpiLoading: false,
|
|
syncProofLoading: false,
|
|
pageIndex: 1,
|
|
pageSize: 20,
|
|
totalPage: 0,
|
|
currentRow: null,
|
|
manualSelectedTrackingId: null,
|
|
selectionRows: [],
|
|
batchEditMode: false,
|
|
processHistoryMap: {},
|
|
processTooltipHoverKey: '',
|
|
processTooltip: {
|
|
visible: false,
|
|
content: '',
|
|
left: 0,
|
|
top: 0
|
|
},
|
|
processHistoryRows: [],
|
|
commentsEditingTrackingId: null,
|
|
commentsDraft: '',
|
|
commentsSaveLoading: false,
|
|
|
|
oneKeyDialogVisible: false,
|
|
oneKeyDialogMode: 'create',
|
|
saveOneKeyLoading: false,
|
|
oneKeyForm: {},
|
|
|
|
proofDialogVisible: false,
|
|
proofSaveLoading: false,
|
|
proofDialogData: this.getDefaultProofDialogData(),
|
|
|
|
processDialogVisible: false,
|
|
saveProcessLoading: false,
|
|
processForm: {},
|
|
|
|
finishDialogVisible: false,
|
|
finishSaveLoading: false,
|
|
finishForm: {
|
|
trackingId: null,
|
|
actualityDeliveryDate: ''
|
|
}
|
|
}
|
|
},
|
|
activated () {
|
|
this.loadUserBuList().then(() => {
|
|
this.queryBuProcessConfig()
|
|
})
|
|
this.getDataList()
|
|
},
|
|
computed: {
|
|
visibleProcessColumns () {
|
|
const searchBuNo = this.getSelectedSearchBuNo()
|
|
// 指定了查询BU时,整表进度列按该BU配置展示。
|
|
if (!searchBuNo) {
|
|
return this.processColumns
|
|
}
|
|
const visibleCodes = this.getProcessVisibleCodesByBuNo(searchBuNo)
|
|
if (!visibleCodes) {
|
|
return this.processColumns
|
|
}
|
|
const visibleColumns = this.processColumns.filter(item => visibleCodes.indexOf(item.code) > -1)
|
|
return visibleColumns.length > 0 ? visibleColumns : this.processColumns
|
|
}
|
|
},
|
|
methods: {
|
|
loadUserBuList () {
|
|
if (this.userBuList.length > 0) {
|
|
this.ensureBuProcessConfigRows()
|
|
return Promise.resolve(this.userBuList)
|
|
}
|
|
const params = { username: this.$store.state.user.name }
|
|
return getSiteAndBuByUserName(params).then(({ data }) => {
|
|
if (data && data.code === 0) {
|
|
const excludedBuNoList = ['3_02-Hardtag', '4_04-MHM', '5_05-Alpha']
|
|
this.userBuList = (data.rows || []).filter(item => {
|
|
const buNo = item && item.buNo ? String(item.buNo).trim() : ''
|
|
return excludedBuNoList.indexOf(buNo) === -1
|
|
})
|
|
this.ensureBuProcessConfigRows()
|
|
}
|
|
return this.userBuList
|
|
}).catch(() => {
|
|
this.userBuList = []
|
|
this.ensureBuProcessConfigRows()
|
|
return []
|
|
})
|
|
},
|
|
getAllProcessCodes () {
|
|
return this.processColumns.map(item => item.code)
|
|
},
|
|
normalizeBuNo (buNo, site) {
|
|
const rawBuNo = buNo == null ? '' : String(buNo).trim()
|
|
if (!rawBuNo) {
|
|
return ''
|
|
}
|
|
const splitIdx = rawBuNo.indexOf('_')
|
|
if (splitIdx < 1 || splitIdx >= rawBuNo.length - 1) {
|
|
return rawBuNo
|
|
}
|
|
// BU统一按“去掉site前缀”展示与保存,例如 2_01-Label -> 01-Label。
|
|
return rawBuNo.substring(splitIdx + 1)
|
|
},
|
|
getValidProcessCodes (codes) {
|
|
if (!Array.isArray(codes) || codes.length === 0) {
|
|
return []
|
|
}
|
|
const allCodes = this.getAllProcessCodes()
|
|
const normalizedCodes = []
|
|
codes.forEach(code => {
|
|
const codeVal = code == null ? '' : String(code).trim()
|
|
if (!codeVal || allCodes.indexOf(codeVal) === -1) {
|
|
return
|
|
}
|
|
if (normalizedCodes.indexOf(codeVal) === -1) {
|
|
normalizedCodes.push(codeVal)
|
|
}
|
|
})
|
|
return normalizedCodes
|
|
},
|
|
getBuProcessConfigEntry (buNo, site) {
|
|
const normalizedBuNo = this.normalizeBuNo(buNo, site)
|
|
if (!normalizedBuNo) {
|
|
return null
|
|
}
|
|
const config = this.buProcessConfigMap[normalizedBuNo]
|
|
if (config) {
|
|
return { key: normalizedBuNo, config: config }
|
|
}
|
|
return null
|
|
},
|
|
getSelectedSearchBuNo () {
|
|
return this.normalizeBuNo(this.searchData.buNo, this.searchData.site)
|
|
},
|
|
handleSearchBuChange () {
|
|
// BU筛选变化(含清空)后立即重新查询,并回到第一页。
|
|
this.getDataList('Y')
|
|
},
|
|
getProcessVisibleCodesByBuNo (buNo, site) {
|
|
const configEntry = this.getBuProcessConfigEntry(buNo, site)
|
|
const config = configEntry ? configEntry.config : null
|
|
// 没有配置或配置为全部显示时,返回 null 表示该 BU 工序列不过滤。
|
|
if (!config || config.showAll !== false) {
|
|
return null
|
|
}
|
|
const validCodes = this.getValidProcessCodes(config.processCodes)
|
|
if (validCodes.length === 0 || validCodes.length >= this.processColumns.length) {
|
|
return null
|
|
}
|
|
return validCodes
|
|
},
|
|
isProcessColumnVisibleForRow (row, processCol) {
|
|
if (!row || !processCol) {
|
|
return true
|
|
}
|
|
// 已指定查询BU时,列集合已经按查询BU过滤,不再按行二次隐藏。
|
|
if (this.getSelectedSearchBuNo()) {
|
|
return true
|
|
}
|
|
const visibleCodes = this.getProcessVisibleCodesByBuNo(row.buNo, row.site)
|
|
if (!visibleCodes) {
|
|
return true
|
|
}
|
|
return visibleCodes.indexOf(processCol.code) > -1
|
|
},
|
|
queryBuProcessConfig () {
|
|
const inData = {
|
|
site: this.$store.state.user.site,
|
|
userName: this.$store.state.user.name
|
|
}
|
|
queryProofTrackingBuProcessConfig(inData).then(({ data }) => {
|
|
if (!(data && data.code === 0)) {
|
|
this.$message.error((data && data.msg) || '加载事业部进度展示配置失败')
|
|
return
|
|
}
|
|
const rows = data.rows || []
|
|
const nextMap = {}
|
|
const allCodeCount = this.processColumns.length
|
|
rows.forEach(item => {
|
|
const buNo = this.normalizeBuNo(item && item.buNo ? item.buNo : '', this.$store.state.user.site)
|
|
if (!buNo) {
|
|
return
|
|
}
|
|
const processCodes = this.getValidProcessCodes(item.processCodes)
|
|
const showAll = item.showAll !== false || processCodes.length === 0 || processCodes.length >= allCodeCount
|
|
if (!showAll) {
|
|
nextMap[buNo] = {
|
|
showAll: false,
|
|
processCodes: processCodes
|
|
}
|
|
}
|
|
})
|
|
this.buProcessConfigMap = nextMap
|
|
this.ensureBuProcessConfigRows()
|
|
this.refreshTrackingTableLayout()
|
|
}).catch(() => {
|
|
this.$message.error('加载事业部进度展示配置异常')
|
|
})
|
|
},
|
|
ensureBuProcessConfigRows () {
|
|
const allCodes = this.getAllProcessCodes()
|
|
const rows = []
|
|
const usedBuMap = {}
|
|
const appendRow = (buNo, buDesc, site) => {
|
|
const key = this.normalizeBuNo(buNo, site || this.$store.state.user.site)
|
|
if (!key || usedBuMap[key]) {
|
|
return
|
|
}
|
|
usedBuMap[key] = true
|
|
const cfg = this.buProcessConfigMap[key]
|
|
const row = {
|
|
buNo: key,
|
|
buDesc: buDesc || key,
|
|
processCodes: allCodes.slice()
|
|
}
|
|
if (cfg && cfg.showAll === false) {
|
|
const validCodes = this.getValidProcessCodes(cfg.processCodes)
|
|
if (validCodes.length > 0 && validCodes.length < allCodes.length) {
|
|
row.processCodes = validCodes
|
|
}
|
|
}
|
|
rows.push(row)
|
|
}
|
|
this.userBuList.forEach(item => {
|
|
if (!item || !item.buNo) {
|
|
return
|
|
}
|
|
appendRow(item.buNo, item.buDesc || this.normalizeBuNo(item.buNo, this.$store.state.user.site), this.$store.state.user.site)
|
|
})
|
|
Object.keys(this.buProcessConfigMap).forEach(buNo => {
|
|
appendRow(buNo, buNo, this.$store.state.user.site)
|
|
})
|
|
this.buProcessConfigRows = rows
|
|
},
|
|
openBuProcessConfigDialog () {
|
|
this.ensureBuProcessConfigRows()
|
|
this.buProcessConfigDialogVisible = true
|
|
},
|
|
refreshTrackingTableLayout () {
|
|
this.$nextTick(() => {
|
|
const tableRef = this.$refs.trackingTable
|
|
if (tableRef && tableRef.doLayout) {
|
|
tableRef.doLayout()
|
|
}
|
|
})
|
|
},
|
|
handleBuProcessCodesChange (row) {
|
|
if (!row) {
|
|
return
|
|
}
|
|
row.processCodes = this.getValidProcessCodes(row.processCodes)
|
|
},
|
|
saveBuProcessConfig () {
|
|
if (!this.buProcessConfigRows || this.buProcessConfigRows.length === 0) {
|
|
this.$message.warning('暂无可配置的事业部')
|
|
return
|
|
}
|
|
const nextMap = {}
|
|
const allCodeCount = this.processColumns.length
|
|
const submitRows = []
|
|
for (let i = 0; i < this.buProcessConfigRows.length; i++) {
|
|
const row = this.buProcessConfigRows[i]
|
|
const buNo = this.normalizeBuNo(row && row.buNo ? row.buNo : '', this.$store.state.user.site)
|
|
if (!buNo) {
|
|
continue
|
|
}
|
|
const validCodes = this.getValidProcessCodes(row.processCodes)
|
|
if (validCodes.length === 0) {
|
|
this.$message.warning(`事业部【${row.buDesc || buNo}】至少需要选择一个可见进度`)
|
|
return
|
|
}
|
|
const showAll = validCodes.length >= allCodeCount
|
|
if (!showAll) {
|
|
nextMap[buNo] = {
|
|
showAll: false,
|
|
processCodes: validCodes
|
|
}
|
|
}
|
|
submitRows.push({
|
|
buNo: buNo,
|
|
showAll: showAll,
|
|
processCodes: validCodes
|
|
})
|
|
}
|
|
const inData = {
|
|
site: this.$store.state.user.site,
|
|
updateBy: this.$store.state.user.name,
|
|
rows: submitRows
|
|
}
|
|
saveProofTrackingBuProcessConfig(inData).then(({ data }) => {
|
|
if (!(data && data.code === 0)) {
|
|
this.$message.error((data && data.msg) || '事业部进度展示设置保存失败')
|
|
return
|
|
}
|
|
this.buProcessConfigMap = nextMap
|
|
this.ensureBuProcessConfigRows()
|
|
this.buProcessConfigDialogVisible = false
|
|
this.$message.success(data.msg || '事业部进度展示设置已保存')
|
|
this.refreshTrackingTableLayout()
|
|
}).catch(() => {
|
|
this.$message.error('事业部进度展示设置保存异常')
|
|
})
|
|
},
|
|
getRoleApi (apiKey) {
|
|
const apiMap = {
|
|
0: searchBusinessInfo,
|
|
1: searchBusinessInfo1,
|
|
2: searchBusinessInfo2,
|
|
3: searchBusinessInfo3,
|
|
4: searchBusinessInfo4,
|
|
5: searchBusinessInfo5,
|
|
6: searchBusinessInfo6,
|
|
7: searchBusinessInfo7,
|
|
8: searchBusinessInfo8
|
|
}
|
|
return apiMap[apiKey]
|
|
},
|
|
fetchRoleListByApiKey (apiKey, queryData) {
|
|
const apiFn = this.getRoleApi(apiKey)
|
|
if (!apiFn) {
|
|
return Promise.resolve([])
|
|
}
|
|
const params = {
|
|
site: this.$store.state.user.site,
|
|
username: queryData && queryData.username ? queryData.username : '',
|
|
userDisplay: queryData && queryData.userDisplay ? queryData.userDisplay : '',
|
|
roleDesc: '',
|
|
active: queryData && queryData.active ? queryData.active : '',
|
|
page: 1,
|
|
limit: 200
|
|
}
|
|
return apiFn(params).then(({ data }) => {
|
|
if (data && data.code === 0) {
|
|
return (data.rows || []).map(item => {
|
|
return {
|
|
username: item.username,
|
|
userDisplay: item.userDisplay || item.user_display || '',
|
|
active: item.active
|
|
}
|
|
})
|
|
}
|
|
return []
|
|
})
|
|
},
|
|
newCustomer () {
|
|
this.newCustomerData.customerDesc = ''
|
|
this.newCustomerFlag = true
|
|
},
|
|
getBaseList (val) {
|
|
this.tagNo = val
|
|
this.$nextTick(() => {
|
|
const strVal = val === 509 ? (this.oneKeyForm.customerNo || '') : ''
|
|
this.$refs.baseList.init(val, strVal, '')
|
|
})
|
|
},
|
|
getBaseData (val) {
|
|
if (this.tagNo === 509) {
|
|
this.oneKeyForm.customerNo = val.customer_no
|
|
this.oneKeyForm.customerDesc = val.customer_desc
|
|
}
|
|
},
|
|
customerNoBlur () {
|
|
if (!this.oneKeyForm.customerNo) {
|
|
this.oneKeyForm.customerDesc = ''
|
|
return
|
|
}
|
|
const params = {
|
|
customerNo: this.oneKeyForm.customerNo,
|
|
createBy: this.$store.state.user.name
|
|
}
|
|
queryCustomerList(params).then(({ data }) => {
|
|
if (data && data.code === 0 && data.rows && data.rows.length === 1) {
|
|
this.oneKeyForm.customerDesc = data.rows[0].customerDesc
|
|
} else {
|
|
this.oneKeyForm.customerDesc = ''
|
|
}
|
|
})
|
|
},
|
|
saveNewCustomer () {
|
|
if (!this.newCustomerData.customerDesc) {
|
|
this.$message.warning('请输入客户名称!')
|
|
return
|
|
}
|
|
this.generateNextCustomerNo().then(customerNo => {
|
|
if (!customerNo) {
|
|
this.$alert('该客户已存在,请重新输入客户名称!', '提示', {
|
|
confirmButtonText: '确定',
|
|
type: 'warning'
|
|
})
|
|
return
|
|
}
|
|
const params = {
|
|
site: this.$store.state.user.site,
|
|
customerNo: customerNo,
|
|
customerDesc: this.newCustomerData.customerDesc,
|
|
createBy: this.$store.state.user.name
|
|
}
|
|
saveNewCustomer(params).then(({ data }) => {
|
|
if (data && data.code === 0) {
|
|
this.oneKeyForm.customerNo = customerNo
|
|
this.oneKeyForm.customerDesc = this.newCustomerData.customerDesc
|
|
this.newCustomerFlag = false
|
|
this.$message.success(data.msg || '新增客户成功')
|
|
} else {
|
|
this.$alert(data && data.msg ? data.msg : '新增客户失败', '提示', {
|
|
confirmButtonText: '确定',
|
|
type: 'warning'
|
|
})
|
|
}
|
|
})
|
|
})
|
|
},
|
|
generateNextCustomerNo () {
|
|
const params = {
|
|
site: this.$store.state.user.site,
|
|
customerDesc: this.newCustomerData.customerDesc,
|
|
createBy: this.$store.state.user.name
|
|
}
|
|
return new Promise(resolve => {
|
|
getCustomerNo(params).then(({ data }) => {
|
|
if (!(data && data.code === 0)) {
|
|
resolve(false)
|
|
return
|
|
}
|
|
if (!data.data || !data.data.customerNo || data.data === '0') {
|
|
resolve('C0001')
|
|
return
|
|
}
|
|
const lastCustomerNo = parseInt(String(data.data.customerNo).substring(1), 10) || 0
|
|
const nextCustomerNo = lastCustomerNo + 1
|
|
if (nextCustomerNo < 10) {
|
|
resolve('C000' + nextCustomerNo)
|
|
} else if (nextCustomerNo < 100) {
|
|
resolve('C00' + nextCustomerNo)
|
|
} else if (nextCustomerNo < 1000) {
|
|
resolve('C0' + nextCustomerNo)
|
|
} else {
|
|
resolve('C' + nextCustomerNo)
|
|
}
|
|
}).catch(() => {
|
|
resolve(false)
|
|
})
|
|
})
|
|
},
|
|
closeNewCustomer () {
|
|
this.newCustomerData.customerDesc = ''
|
|
this.newCustomerFlag = false
|
|
},
|
|
openRoleDialog (field) {
|
|
const roleCfg = this.roleConfig[field]
|
|
if (!roleCfg) {
|
|
return
|
|
}
|
|
this.roleDialogField = field
|
|
this.roleDialogApiKey = roleCfg.apiKey
|
|
this.roleDialogTitle = roleCfg.title
|
|
this.roleSearchData = {
|
|
site: this.$store.state.user.site,
|
|
username: '',
|
|
userDisplay: '',
|
|
active: '',
|
|
page: 1,
|
|
limit: 50
|
|
}
|
|
this.roleDialogVisible = true
|
|
this.queryRoleDialogList()
|
|
},
|
|
queryRoleDialogList () {
|
|
this.fetchRoleListByApiKey(this.roleDialogApiKey, this.roleSearchData).then(rows => {
|
|
this.roleDialogList = rows
|
|
})
|
|
},
|
|
pickRole (row) {
|
|
const roleCfg = this.roleConfig[this.roleDialogField]
|
|
if (!roleCfg) {
|
|
return
|
|
}
|
|
const value = row.username + '-' + row.userDisplay
|
|
this.oneKeyForm[this.roleDialogField] = value
|
|
this.oneKeyForm[roleCfg.nameField] = row.userDisplay
|
|
this.roleDialogVisible = false
|
|
},
|
|
getEmptyOneKeyForm () {
|
|
return {
|
|
site: this.$store.state.user.site,
|
|
buNo: '',
|
|
projectNo: '',
|
|
projectName: '',
|
|
projectDesc: '',
|
|
projectStatus: '草稿',
|
|
projectSource: '',
|
|
testPartNo: '',
|
|
partDesc: '',
|
|
partName: '',
|
|
partSpec: '',
|
|
materialNumber: '',
|
|
finalPartDesc: '',
|
|
finalPartNo: '',
|
|
baseNo: '',
|
|
revNo: '',
|
|
customerNo: '',
|
|
customerDesc: '',
|
|
finalCustomerId: '',
|
|
customerRemark: '',
|
|
parentProjectNo: '',
|
|
oriProjectId: '',
|
|
projectCategory: '',
|
|
cProjectRegion: '',
|
|
projectManager: '',
|
|
projectManagerName: '',
|
|
projectOwner: '',
|
|
projectOwnerName: '',
|
|
cQualityEngineer1: '',
|
|
cQualityEngineer1Name: '',
|
|
cQualityEngineer2: '',
|
|
cQualityEngineer2Name: '',
|
|
cQualityEngineer3: '',
|
|
cQualityEngineer3Name: '',
|
|
cQualityEngineer4: '',
|
|
cQualityEngineer4Name: '',
|
|
cQualityEngineer5: '',
|
|
cQualityEngineer5Name: '',
|
|
cQualityEngineer6: '',
|
|
cQualityEngineer6Name: '',
|
|
cManufactureEngineer: '',
|
|
cManufactureEngineerName: '',
|
|
docEngineer: '',
|
|
docEngineerName: '',
|
|
docEngineer2: '',
|
|
docEngineer2Name: '',
|
|
ipqcHardTag: '',
|
|
ipqcHardTagName: '',
|
|
cQualityEngineer7: '',
|
|
cQualityEngineer7Name: '',
|
|
partType: '',
|
|
partStatus: '草稿',
|
|
projectPhase: '',
|
|
tracker: '',
|
|
engineer: '',
|
|
engineerName: '',
|
|
priorityLevel: '',
|
|
proofingNo: '',
|
|
proofingStatus: '进行中',
|
|
proofingNumber: '',
|
|
projectCreationDate: '',
|
|
projectCloseDate: '',
|
|
buildDate: '',
|
|
closeDate: '',
|
|
comments: '',
|
|
planStartDate: '',
|
|
requiredDeliveryDate: '',
|
|
needDate: '',
|
|
remark: ''
|
|
}
|
|
},
|
|
getDefaultProofDialogData () {
|
|
return {
|
|
trackingId: null,
|
|
site: this.$store.state.user.site,
|
|
projectId: null,
|
|
projectNo: '',
|
|
projectDesc: '',
|
|
buNo: '',
|
|
customerNo: '',
|
|
customerDesc: '',
|
|
projectPartId: null,
|
|
testPartNo: '',
|
|
partDesc: '',
|
|
projectCategory: '',
|
|
cProjectTypeDb: '',
|
|
projectPhase: '',
|
|
projectManager: '',
|
|
projectOwner: '',
|
|
engineer: '',
|
|
priorityLevel: '',
|
|
proofingNo: '',
|
|
proofingNumber: '',
|
|
planStartDate: '',
|
|
requiredDeliveryDate: '',
|
|
actualityDeliveryDate: '',
|
|
proofingStatus: '草稿',
|
|
remark: '',
|
|
createBy: this.$store.state.user.name,
|
|
updateBy: this.$store.state.user.name
|
|
}
|
|
},
|
|
getDataList (flag) {
|
|
if (flag === 'Y') {
|
|
this.pageIndex = 1
|
|
}
|
|
this.searchData.site = this.$store.state.user.site
|
|
this.searchData.userName = this.$store.state.user.name
|
|
const inData = Object.assign({}, this.searchData, {
|
|
page: this.pageIndex,
|
|
limit: this.pageSize
|
|
})
|
|
inData.buNo = this.normalizeBuNo(inData.buNo, inData.site)
|
|
this.dataListLoading = true
|
|
searchProofTracking(inData).then(({ data }) => {
|
|
this.dataListLoading = false
|
|
this.resetProcessTooltip()
|
|
if (data && data.code === 0) {
|
|
this.dataList = (data.page && data.page.list) || []
|
|
this.totalPage = (data.page && data.page.totalCount) || 0
|
|
if (this.commentsEditingTrackingId) {
|
|
const hasEditingRow = this.dataList.some(item => item.trackingId === this.commentsEditingTrackingId)
|
|
if (!hasEditingRow) {
|
|
this.cancelCommentsEdit()
|
|
}
|
|
}
|
|
const manualSelectedId = this.manualSelectedTrackingId
|
|
const previousCurrentId = this.currentRow && this.currentRow.trackingId
|
|
let nextCurrentRow = null
|
|
if (manualSelectedId != null) {
|
|
// 只要用户没有手动点新行,刷新后始终尝试回选上次手动选中的那一行
|
|
nextCurrentRow = this.dataList.find(item => item && item.trackingId === manualSelectedId) || null
|
|
} else if (previousCurrentId != null) {
|
|
nextCurrentRow = this.dataList.find(item => item && item.trackingId === previousCurrentId) || null
|
|
}
|
|
if (!nextCurrentRow && manualSelectedId == null && this.dataList.length > 0) {
|
|
nextCurrentRow = this.dataList[0]
|
|
}
|
|
this.currentRow = nextCurrentRow
|
|
this.$nextTick(() => {
|
|
if (this.$refs.trackingTable && typeof this.$refs.trackingTable.setCurrentRow === 'function') {
|
|
this.$refs.trackingTable.setCurrentRow(this.currentRow || null)
|
|
}
|
|
})
|
|
} else {
|
|
this.dataList = []
|
|
this.totalPage = 0
|
|
this.currentRow = null
|
|
this.$nextTick(() => {
|
|
if (this.$refs.trackingTable && typeof this.$refs.trackingTable.setCurrentRow === 'function') {
|
|
this.$refs.trackingTable.setCurrentRow(null)
|
|
}
|
|
})
|
|
this.$message.error(data.msg || '查询失败')
|
|
}
|
|
}).catch(() => {
|
|
this.dataListLoading = false
|
|
this.resetProcessTooltip()
|
|
this.$message.error('查询异常')
|
|
})
|
|
},
|
|
resetSearch () {
|
|
this.searchData.projectNo = ''
|
|
this.searchData.projectDesc = ''
|
|
this.searchData.buNo = ''
|
|
this.searchData.testPartNo = ''
|
|
this.searchData.partDesc = ''
|
|
this.searchData.customerNo = ''
|
|
this.searchData.proofingNo = ''
|
|
this.searchData.projectPartSyncFlag = ''
|
|
this.searchData.proofSyncFlag = ''
|
|
this.searchData.proofingStatus = ''
|
|
this.getDataList('Y')
|
|
},
|
|
selectionChange (rows) {
|
|
this.selectionRows = rows || []
|
|
},
|
|
isCommentsEditing (row) {
|
|
return !!row && row.trackingId === this.commentsEditingTrackingId
|
|
},
|
|
startCommentsEdit (row) {
|
|
if (this.batchEditMode || !row || !row.trackingId || this.commentsSaveLoading) {
|
|
return
|
|
}
|
|
this.commentsEditingTrackingId = row.trackingId
|
|
this.commentsDraft = row.comments || ''
|
|
},
|
|
cancelCommentsEdit () {
|
|
if (this.commentsSaveLoading) {
|
|
return
|
|
}
|
|
this.commentsEditingTrackingId = null
|
|
this.commentsDraft = ''
|
|
},
|
|
handleCommentsBlur (row) {
|
|
if (this.commentsSaveLoading || !this.isCommentsEditing(row)) {
|
|
return
|
|
}
|
|
const comments = this.commentsDraft == null ? '' : String(this.commentsDraft)
|
|
if (comments.trim()) {
|
|
this.saveCommentsEdit(row, {
|
|
fromBlur: true,
|
|
draftComments: comments
|
|
})
|
|
return
|
|
}
|
|
this.cancelCommentsEdit()
|
|
},
|
|
saveCommentsEdit (row, options) {
|
|
const saveOptions = options || {}
|
|
const fromBlur = !!saveOptions.fromBlur
|
|
if (this.commentsSaveLoading) {
|
|
return
|
|
}
|
|
if (!row || !row.trackingId) {
|
|
this.$message.warning('跟踪记录ID不能为空')
|
|
return
|
|
}
|
|
const comments = Object.prototype.hasOwnProperty.call(saveOptions, 'draftComments')
|
|
? (saveOptions.draftComments == null ? '' : String(saveOptions.draftComments))
|
|
: (this.commentsDraft == null ? '' : String(this.commentsDraft))
|
|
if (comments === (row.comments || '')) {
|
|
this.cancelCommentsEdit()
|
|
return
|
|
}
|
|
if (fromBlur) {
|
|
this.commentsEditingTrackingId = null
|
|
this.commentsDraft = ''
|
|
}
|
|
this.commentsSaveLoading = true
|
|
updateProofTrackingComments({
|
|
trackingId: row.trackingId,
|
|
comments: comments,
|
|
updateBy: this.$store.state.user.name
|
|
}).then(({ data }) => {
|
|
this.commentsSaveLoading = false
|
|
if (data && data.code === 0) {
|
|
row.comments = comments
|
|
this.$message.success('Comments保存成功')
|
|
this.cancelCommentsEdit()
|
|
} else {
|
|
this.$message.error(data.msg || 'Comments保存失败')
|
|
}
|
|
}).catch(() => {
|
|
this.commentsSaveLoading = false
|
|
this.$message.error('Comments保存异常')
|
|
})
|
|
},
|
|
rowClick (row) {
|
|
this.currentRow = row
|
|
this.manualSelectedTrackingId = row && row.trackingId ? row.trackingId : null
|
|
},
|
|
sizeChangeHandle (val) {
|
|
this.pageSize = val
|
|
this.pageIndex = 1
|
|
this.getDataList()
|
|
},
|
|
currentChangeHandle (val) {
|
|
this.pageIndex = val
|
|
this.getDataList()
|
|
},
|
|
getActionRow (row) {
|
|
return row || this.currentRow || (this.selectionRows.length > 0 ? this.selectionRows[0] : null)
|
|
},
|
|
getTrackingProjectPartId (row) {
|
|
if (!row) {
|
|
return null
|
|
}
|
|
return row.projectPartId || row.project_part_id || null
|
|
},
|
|
isSyncedByIdRule (idValue) {
|
|
if (idValue == null || String(idValue).trim() === '') {
|
|
return false
|
|
}
|
|
// 约定:NPI 正式库主键 < 100000,tracking 临时主键 >= 100000。
|
|
const numericId = Number(idValue)
|
|
return Number.isFinite(numericId) && numericId > 0 && numericId < 100000
|
|
},
|
|
isProjectPartSynced (row) {
|
|
if (!row) {
|
|
return false
|
|
}
|
|
const projectId = row.projectId || row.project_id || null
|
|
const projectPartId = this.getTrackingProjectPartId(row)
|
|
return this.isSyncedByIdRule(projectId) && this.isSyncedByIdRule(projectPartId)
|
|
},
|
|
isProofSynced (row) {
|
|
if (!row) {
|
|
return false
|
|
}
|
|
const proofingId = row.proofingId || row.proofing_id || row.trackingId || null
|
|
return this.isSyncedByIdRule(proofingId)
|
|
},
|
|
getProjectPartSyncTextClass (row) {
|
|
return this.isProjectPartSynced(row) ? 'sync-text--ok' : 'sync-text--pending'
|
|
},
|
|
getProofSyncTextClass (row) {
|
|
return this.isProofSynced(row) ? 'sync-text--ok' : 'sync-text--pending'
|
|
},
|
|
getProjectCategoryValue (source) {
|
|
if (!source) {
|
|
return ''
|
|
}
|
|
const category = source.cProjectTypeDb || source.projectCategory || source.project_category || source.c_project_type_db || ''
|
|
return this.isBlankValue(category) ? '' : String(category).trim()
|
|
},
|
|
isOneKeyCreateFieldVisible (fieldKey) {
|
|
if (this.oneKeyDialogMode !== 'create') {
|
|
return true
|
|
}
|
|
return this.oneKeyCreateVisibleFieldKeys.indexOf(fieldKey) > -1
|
|
},
|
|
isBlankValue (value) {
|
|
return value == null || String(value).trim() === ''
|
|
},
|
|
getBuOptionValue (site, buNo) {
|
|
const rawBuNo = buNo == null ? '' : String(buNo).trim()
|
|
if (!rawBuNo) {
|
|
return ''
|
|
}
|
|
if (rawBuNo.indexOf('_') > -1) {
|
|
return rawBuNo
|
|
}
|
|
const targetSuffix = `_${rawBuNo}`
|
|
const matched = this.userBuList.find(item => item && item.buNo && (item.buNo === rawBuNo || item.buNo === `${site}_${rawBuNo}` || String(item.buNo).endsWith(targetSuffix)))
|
|
if (matched && matched.buNo) {
|
|
return matched.buNo
|
|
}
|
|
return site ? `${site}_${rawBuNo}` : rawBuNo
|
|
},
|
|
getRoleDisplayName (value) {
|
|
if (this.isBlankValue(value)) {
|
|
return ''
|
|
}
|
|
const strVal = String(value)
|
|
const splitIdx = strVal.indexOf('-')
|
|
return splitIdx > -1 ? strVal.substring(splitIdx + 1) : strVal
|
|
},
|
|
buildOneKeySubmitPayload () {
|
|
const inData = Object.assign({}, this.oneKeyForm, {
|
|
createBy: this.$store.state.user.name,
|
|
updateBy: this.$store.state.user.name
|
|
})
|
|
if (!inData.projectName && inData.projectDesc) {
|
|
inData.projectName = inData.projectDesc
|
|
}
|
|
if (!inData.projectDesc && inData.projectName) {
|
|
inData.projectDesc = inData.projectName
|
|
}
|
|
if (!inData.tracker) {
|
|
inData.tracker = inData.projectOwner
|
|
}
|
|
if (!inData.priorityLevel) {
|
|
inData.priorityLevel = ''
|
|
}
|
|
// 弹窗仅展示一个立项日期输入,提交时同步到项目与物料两个日期字段,避免物料立项日期被误判为空
|
|
if (!this.isBlankValue(inData.projectCreationDate)) {
|
|
inData.buildDate = inData.projectCreationDate
|
|
} else if (!this.isBlankValue(inData.buildDate)) {
|
|
inData.projectCreationDate = inData.buildDate
|
|
}
|
|
return inData
|
|
},
|
|
validateOneKeySubmitPayload (inData) {
|
|
if (this.isBlankValue(inData.site) || this.isBlankValue(inData.buNo)) {
|
|
this.$message.error('工厂和BU不能为空')
|
|
return false
|
|
}
|
|
if (this.oneKeyDialogMode === 'edit') {
|
|
if (!inData.projectId || !inData.projectPartId || !inData.trackingId) {
|
|
this.$message.error('项目/物料/打样记录ID缺失,无法修改')
|
|
return false
|
|
}
|
|
if (this.isBlankValue(inData.projectNo)) {
|
|
this.$message.error('项目编码不能为空')
|
|
return false
|
|
}
|
|
if (this.isBlankValue(inData.projectName) && this.isBlankValue(inData.projectDesc)) {
|
|
this.$message.error('项目名称不能为空')
|
|
return false
|
|
}
|
|
if (this.isBlankValue(inData.testPartNo)) {
|
|
this.$message.error('项目料号不能为空')
|
|
return false
|
|
}
|
|
if (this.isBlankValue(inData.partDesc)) {
|
|
this.$message.error('料号描述不能为空')
|
|
return false
|
|
}
|
|
if (!this.isBlankValue(inData.proofingNumber) && !/^[1-9]\d*$/.test(String(inData.proofingNumber))) {
|
|
this.$message.error('打样数量必须是正整数')
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
},
|
|
buildOneKeyEditForm (current, projectData, partData) {
|
|
const project = projectData || {}
|
|
const part = partData || {}
|
|
const form = Object.assign(this.getEmptyOneKeyForm(), {
|
|
site: project.site || part.site || current.site || this.$store.state.user.site,
|
|
projectId: project.projectId || current.projectId || null,
|
|
projectPartId: part.projectPartId || this.getTrackingProjectPartId(current),
|
|
trackingId: current.trackingId || null,
|
|
buNo: this.getBuOptionValue(project.site || current.site || this.$store.state.user.site, project.buNo || current.buNo),
|
|
projectNo: project.projectNo || current.projectNo || '',
|
|
projectName: project.projectName || project.projectDesc || current.projectName || current.projectDesc || '',
|
|
projectDesc: project.projectDesc || project.projectName || current.projectDesc || current.projectName || '',
|
|
projectStatus: project.status || project.projectStatus || '草稿',
|
|
projectSource: project.projectSource || '',
|
|
testPartNo: part.testPartNo || current.testPartNo || '',
|
|
partDesc: part.partDesc || current.partDesc || '',
|
|
partName: part.partName || '',
|
|
partSpec: part.partSpec || '',
|
|
materialNumber: part.materialNumber || '',
|
|
finalPartDesc: part.finalPartDesc || '',
|
|
finalPartNo: part.finalPartNo || current.finalPartNo || '',
|
|
baseNo: part.baseNo || '',
|
|
revNo: part.revNo || '',
|
|
customerNo: project.customerNo || part.customerNo || current.customerNo || '',
|
|
customerDesc: project.customerDesc || current.customerDesc || '',
|
|
finalCustomerId: project.finalCustomerId || '',
|
|
customerRemark: project.customerRemark || '',
|
|
parentProjectNo: project.parentProjectNo || '',
|
|
oriProjectId: project.oriProjectId || '',
|
|
projectCategory: project.projectCategory || part.projectCategory || current.projectCategory || '',
|
|
cProjectRegion: project.cProjectRegion || current.cProjectRegion || '',
|
|
projectManager: project.projectManager || part.projectManager || current.projectManager || '',
|
|
projectOwner: project.projectOwner || part.projectOwner || current.projectOwner || '',
|
|
cQualityEngineer1: project.cQualityEngineer1 || part.cQualityEngineer1 || '',
|
|
cQualityEngineer2: project.cQualityEngineer2 || part.cQualityEngineer2 || '',
|
|
cQualityEngineer3: project.cQualityEngineer3 || part.cQualityEngineer3 || '',
|
|
cQualityEngineer4: project.cQualityEngineer4 || part.cQualityEngineer4 || '',
|
|
cQualityEngineer5: project.cQualityEngineer5 || part.cQualityEngineer5 || '',
|
|
cQualityEngineer6: project.cQualityEngineer6 || part.cQualityEngineer6 || '',
|
|
cManufactureEngineer: project.cManufactureEngineer || part.cManufactureEngineer || '',
|
|
docEngineer: project.docEngineer || part.docEngineer || '',
|
|
docEngineer2: project.docEngineer2 || part.docEngineer2 || '',
|
|
ipqcHardTag: project.ipqcHardTag || part.ipqcHardTag || '',
|
|
cQualityEngineer7: project.cQualityEngineer7 || part.cQualityEngineer7 || '',
|
|
partType: part.partType || '',
|
|
partStatus: part.status || part.partStatus || '草稿',
|
|
projectPhase: current.projectPhase || '',
|
|
tracker: current.tracker || project.projectOwner || part.projectOwner || '',
|
|
engineer: current.engineer || project.engineer || part.engineer || '',
|
|
priorityLevel: current.priorityLevel || current.priority || project.priority || part.priority || '',
|
|
proofingNo: current.proofingNo || '',
|
|
proofingStatus: current.proofingStatus || '进行中',
|
|
proofingNumber: current.proofingNumber,
|
|
projectCreationDate: project.projectCreationDate || part.buildDate || '',
|
|
projectCloseDate: project.projectCloseDate || '',
|
|
buildDate: part.buildDate || project.projectCreationDate || '',
|
|
closeDate: part.closeDate || '',
|
|
comments: current.comments || '',
|
|
planStartDate: current.planStartDate || '',
|
|
requiredDeliveryDate: current.requiredDeliveryDate || '',
|
|
needDate: project.needDate || part.needDate || current.needDate || '',
|
|
remark: part.remark || project.remark || current.remark || ''
|
|
})
|
|
form.projectManagerName = this.getRoleDisplayName(form.projectManager)
|
|
form.projectOwnerName = this.getRoleDisplayName(form.projectOwner)
|
|
form.engineerName = this.getRoleDisplayName(form.engineer)
|
|
form.cManufactureEngineerName = this.getRoleDisplayName(form.cManufactureEngineer)
|
|
form.cQualityEngineer1Name = this.getRoleDisplayName(form.cQualityEngineer1)
|
|
form.cQualityEngineer2Name = this.getRoleDisplayName(form.cQualityEngineer2)
|
|
form.cQualityEngineer3Name = this.getRoleDisplayName(form.cQualityEngineer3)
|
|
form.cQualityEngineer4Name = this.getRoleDisplayName(form.cQualityEngineer4)
|
|
form.cQualityEngineer5Name = this.getRoleDisplayName(form.cQualityEngineer5)
|
|
form.cQualityEngineer6Name = this.getRoleDisplayName(form.cQualityEngineer6)
|
|
form.docEngineerName = this.getRoleDisplayName(form.docEngineer)
|
|
form.docEngineer2Name = this.getRoleDisplayName(form.docEngineer2)
|
|
form.ipqcHardTagName = this.getRoleDisplayName(form.ipqcHardTag)
|
|
form.cQualityEngineer7Name = this.getRoleDisplayName(form.cQualityEngineer7)
|
|
return form
|
|
},
|
|
openOneKeyDialog (mode, row) {
|
|
const dialogMode = mode === 'edit' ? 'edit' : 'create'
|
|
this.oneKeyDialogMode = dialogMode
|
|
if (dialogMode !== 'edit') {
|
|
this.oneKeyForm = this.getEmptyOneKeyForm()
|
|
if (this.userBuList.length > 0) {
|
|
this.oneKeyForm.buNo = this.userBuList[0].buNo || ''
|
|
}
|
|
this.oneKeyDialogVisible = true
|
|
return
|
|
}
|
|
const current = this.getActionRow(row)
|
|
if (!current) {
|
|
this.$message.warning('请先选择一条记录后再修改项目/物料/打样')
|
|
this.oneKeyDialogMode = 'create'
|
|
return
|
|
}
|
|
const projectPartId = this.getTrackingProjectPartId(current)
|
|
if (!current.projectId || !projectPartId || !current.trackingId) {
|
|
this.$message.warning('当前记录缺少项目/物料/打样关键信息,无法修改')
|
|
this.oneKeyDialogMode = 'create'
|
|
return
|
|
}
|
|
const queryUser = this.$store.state.user.name
|
|
const querySite = current.site || this.$store.state.user.site
|
|
this.saveOneKeyLoading = true
|
|
Promise.all([
|
|
searchProjectInfoTracking({
|
|
site: querySite,
|
|
userName: queryUser,
|
|
projectId: current.projectId,
|
|
page: 1,
|
|
limit: 1
|
|
}),
|
|
searchProjectPartTracking({
|
|
site: querySite,
|
|
userName: queryUser,
|
|
projectPartId: projectPartId,
|
|
page: 1,
|
|
limit: 1
|
|
})
|
|
]).then(([projectResp, partResp]) => {
|
|
const projectData = projectResp && projectResp.data
|
|
const partData = partResp && partResp.data
|
|
if (!projectData || projectData.code !== 0) {
|
|
throw new Error((projectData && projectData.msg) || '加载项目信息失败')
|
|
}
|
|
if (!partData || partData.code !== 0) {
|
|
throw new Error((partData && partData.msg) || '加载项目物料信息失败')
|
|
}
|
|
const projectRows = (projectData.page && projectData.page.list) || []
|
|
const partRows = (partData.page && partData.page.list) || []
|
|
if (projectRows.length === 0) {
|
|
throw new Error('未找到对应的项目信息,无法修改')
|
|
}
|
|
if (partRows.length === 0) {
|
|
throw new Error('未找到对应的项目物料信息,无法修改')
|
|
}
|
|
this.oneKeyForm = this.buildOneKeyEditForm(current, projectRows[0], partRows[0])
|
|
this.oneKeyDialogVisible = true
|
|
}).catch((e) => {
|
|
this.$message.error((e && e.message) || '加载项目/物料/打样信息异常')
|
|
this.oneKeyDialogMode = 'create'
|
|
}).finally(() => {
|
|
this.saveOneKeyLoading = false
|
|
})
|
|
},
|
|
submitOneKey () {
|
|
const inData = this.buildOneKeySubmitPayload()
|
|
if (!this.validateOneKeySubmitPayload(inData)) {
|
|
return
|
|
}
|
|
this.saveOneKeyLoading = true
|
|
if (this.oneKeyDialogMode === 'edit') {
|
|
oneKeyUpdateProofTracking(inData).then(({ data }) => {
|
|
if (!data || data.code !== 0) {
|
|
throw new Error((data && data.msg) || '修改项目/物料/打样失败')
|
|
}
|
|
this.$message.success('项目/物料/打样修改成功')
|
|
this.oneKeyDialogVisible = false
|
|
this.getDataList()
|
|
}).catch((e) => {
|
|
this.$message.error((e && e.message) || '项目/物料/打样修改异常')
|
|
}).finally(() => {
|
|
this.saveOneKeyLoading = false
|
|
})
|
|
return
|
|
}
|
|
oneKeyCreateProofTracking(inData).then(({ data }) => {
|
|
this.saveOneKeyLoading = false
|
|
if (data && data.code === 0) {
|
|
this.$message.success('一键创建成功')
|
|
this.oneKeyDialogVisible = false
|
|
this.searchData.projectNo = ''
|
|
this.searchData.projectDesc = ''
|
|
this.searchData.testPartNo = ''
|
|
this.searchData.partDesc = ''
|
|
this.searchData.customerNo = ''
|
|
this.searchData.proofingNo = ''
|
|
this.searchData.projectPartSyncFlag = ''
|
|
this.searchData.proofSyncFlag = ''
|
|
this.searchData.proofingStatus = ''
|
|
this.getDataList('Y')
|
|
} else {
|
|
this.$message.error(data.msg || '一键创建失败')
|
|
}
|
|
}).catch(() => {
|
|
this.saveOneKeyLoading = false
|
|
this.$message.error('一键创建异常')
|
|
})
|
|
},
|
|
openCreateProofDialog (row) {
|
|
const current = this.getActionRow(row)
|
|
if (!current) {
|
|
this.$message.warning('请先选择一条记录')
|
|
return
|
|
}
|
|
this.currentRow = current
|
|
const projectPartId = this.getTrackingProjectPartId(current) || current.id
|
|
const projectCategory = this.getProjectCategoryValue(current)
|
|
this.proofDialogData = Object.assign(this.getDefaultProofDialogData(), {
|
|
trackingId: null,
|
|
site: current.site || this.$store.state.user.site,
|
|
projectId: current.projectId,
|
|
projectNo: current.projectNo,
|
|
projectDesc: current.projectDesc,
|
|
buNo: current.buNo,
|
|
customerNo: current.customerNo,
|
|
customerDesc: current.customerDesc,
|
|
projectPartId: projectPartId,
|
|
testPartNo: current.testPartNo,
|
|
partDesc: current.partDesc,
|
|
projectCategory: projectCategory,
|
|
cProjectTypeDb: projectCategory,
|
|
projectManager: current.projectManager,
|
|
projectOwner: current.projectOwner,
|
|
engineer: current.engineer,
|
|
priorityLevel: current.priority,
|
|
proofingNo: '',
|
|
proofingNumber: '',
|
|
planStartDate: '',
|
|
requiredDeliveryDate: '',
|
|
actualityDeliveryDate: '',
|
|
proofingStatus: '草稿',
|
|
remark: '',
|
|
createBy: this.$store.state.user.name,
|
|
updateBy: this.$store.state.user.name
|
|
})
|
|
if (this.isBlankValue(projectCategory)) {
|
|
this.$message.warning('未获取到项目分类,请手动选择')
|
|
}
|
|
this.proofDialogVisible = true
|
|
},
|
|
validateSyncToNpiRow (row) {
|
|
const projectPartId = this.getTrackingProjectPartId(row)
|
|
const missingLabels = []
|
|
if (this.isBlankValue(row && row.site)) {
|
|
missingLabels.push('工厂')
|
|
}
|
|
if (this.isBlankValue(row && row.buNo)) {
|
|
missingLabels.push('BU')
|
|
}
|
|
if (!row || !row.projectId) {
|
|
missingLabels.push('项目ID')
|
|
}
|
|
if (this.isBlankValue(row && row.projectNo)) {
|
|
missingLabels.push('项目编码')
|
|
}
|
|
if (this.isBlankValue(row && row.projectName) && this.isBlankValue(row && row.projectDesc)) {
|
|
missingLabels.push('项目名称')
|
|
}
|
|
if (!projectPartId) {
|
|
missingLabels.push('项目物料ID')
|
|
}
|
|
if (this.isBlankValue(row && row.testPartNo)) {
|
|
missingLabels.push('项目料号')
|
|
}
|
|
if (this.isBlankValue(row && row.partDesc)) {
|
|
missingLabels.push('料号描述')
|
|
}
|
|
if (missingLabels.length > 0) {
|
|
const missingHtml = missingLabels.map(item => `- ${item}`).join('<br/>')
|
|
this.$alert(`同步到NPI前,请先完善以下字段:<br/>${missingHtml}`, '提示', {
|
|
confirmButtonText: '确定',
|
|
dangerouslyUseHTMLString: true
|
|
})
|
|
return {
|
|
passed: false,
|
|
projectPartId: projectPartId
|
|
}
|
|
}
|
|
return {
|
|
passed: true,
|
|
projectPartId: projectPartId
|
|
}
|
|
},
|
|
syncToNpi (row) {
|
|
const current = this.getActionRow(row)
|
|
if (!current) {
|
|
this.$message.warning('请先选择一条记录')
|
|
return
|
|
}
|
|
const syncCheck = this.validateSyncToNpiRow(current)
|
|
if (!syncCheck.passed) {
|
|
return
|
|
}
|
|
const projectPartId = syncCheck.projectPartId
|
|
this.currentRow = current
|
|
const projectNo = current.projectNo || '-'
|
|
const testPartNo = current.testPartNo || '-'
|
|
const confirmMsg = `确认将项目编码[${projectNo}]物料编码[${testPartNo}]同步到NPI吗?`
|
|
this.$confirm(confirmMsg, '提示', {
|
|
confirmButtonText: '确定',
|
|
cancelButtonText: '取消',
|
|
type: 'warning',
|
|
dangerouslyUseHTMLString: true
|
|
}).then(() => {
|
|
const operator = this.$store.state.user.name
|
|
this.syncNpiLoading = true
|
|
syncProjectPartTracking({
|
|
projectPartId: projectPartId,
|
|
updateBy: operator,
|
|
createBy: operator,
|
|
userName: operator
|
|
}).then(({ data }) => {
|
|
if (data && data.code === 0) {
|
|
this.$message.success(`同步成功`)
|
|
this.getDataList()
|
|
} else {
|
|
const failMsg = (data && data.msg) || '同步到NPI失败'
|
|
if (failMsg.indexOf('缺少以下必填项') > -1) {
|
|
this.$alert(failMsg, '同步校验未通过', {
|
|
confirmButtonText: '确定'
|
|
})
|
|
} else {
|
|
this.$message.error(failMsg)
|
|
}
|
|
}
|
|
}).catch(() => {
|
|
this.$message.error('同步到NPI异常')
|
|
}).finally(() => {
|
|
this.syncNpiLoading = false
|
|
})
|
|
})
|
|
.catch(() => {})
|
|
},
|
|
syncProofToNpi (row) {
|
|
const current = this.getActionRow(row)
|
|
if (!current || !current.trackingId) {
|
|
this.$message.warning('请先选择一条打样记录')
|
|
return
|
|
}
|
|
this.currentRow = current
|
|
const projectNo = current.projectNo || '-'
|
|
const testPartNo = current.testPartNo || '-'
|
|
const proofingNo = current.proofingNo || '-'
|
|
const confirmMsg = `确认将当前打样记录同步到NPI吗?<br/>项目编码:${projectNo}<br/>物料编码:${testPartNo}<br/>打样单号:${proofingNo}`
|
|
this.$confirm(confirmMsg, '提示', {
|
|
confirmButtonText: '确定',
|
|
cancelButtonText: '取消',
|
|
type: 'warning',
|
|
dangerouslyUseHTMLString: true
|
|
}).then(() => {
|
|
const operator = this.$store.state.user.name
|
|
this.syncProofLoading = true
|
|
syncProofTracking({
|
|
trackingId: current.trackingId,
|
|
updateBy: operator,
|
|
createBy: operator,
|
|
userName: operator
|
|
}).then(({ data }) => {
|
|
if (data && data.code === 0) {
|
|
this.$message.success('打样同步成功')
|
|
this.getDataList()
|
|
} else {
|
|
const failMsg = (data && data.msg) || '同步打样到NPI失败'
|
|
if (failMsg.indexOf('缺少以下必填项') > -1 || failMsg.indexOf('请先同步项目') > -1 || failMsg.indexOf('请先同步项目物料') > -1) {
|
|
this.$alert(failMsg, '同步校验未通过', {
|
|
confirmButtonText: '确定'
|
|
})
|
|
} else {
|
|
this.$message.error(failMsg)
|
|
}
|
|
}
|
|
}).catch(() => {
|
|
this.$message.error('同步打样到NPI异常')
|
|
}).finally(() => {
|
|
this.syncProofLoading = false
|
|
})
|
|
}).catch(() => {})
|
|
},
|
|
validateProofDialogData () {
|
|
if (!this.proofDialogData.projectId || !this.proofDialogData.projectPartId) {
|
|
this.$message.warning('项目或项目料号信息不完整')
|
|
return false
|
|
}
|
|
if (!this.proofDialogData.cProjectTypeDb) {
|
|
this.$message.warning('项目分类不能为空')
|
|
return false
|
|
}
|
|
if (!this.proofDialogData.projectPhase) {
|
|
this.$message.warning('项目阶段不能为空')
|
|
return false
|
|
}
|
|
if (!this.proofDialogData.proofingNo) {
|
|
this.$message.warning('打样单号不能为空')
|
|
return false
|
|
}
|
|
if (!this.proofDialogData.proofingNumber) {
|
|
this.$message.warning('数量不能为空')
|
|
return false
|
|
}
|
|
if (!/^[1-9]\d*$/.test(String(this.proofDialogData.proofingNumber))) {
|
|
this.$alert('数量必需是大于等于0的正整数', '提示', {
|
|
confirmButtonText: '确定'
|
|
})
|
|
return false
|
|
}
|
|
if (!this.proofDialogData.planStartDate) {
|
|
this.$message.warning('打样开始日期不能为空')
|
|
return false
|
|
}
|
|
if (!this.proofDialogData.requiredDeliveryDate) {
|
|
this.$message.warning('预计完成日期不能为空')
|
|
return false
|
|
}
|
|
return true
|
|
},
|
|
buildProofPayload () {
|
|
return {
|
|
site: this.proofDialogData.site,
|
|
projectId: this.proofDialogData.projectId,
|
|
projectPartId: this.proofDialogData.projectPartId,
|
|
projectNo: this.proofDialogData.projectNo,
|
|
testPartNo: this.proofDialogData.testPartNo,
|
|
customerNo: this.proofDialogData.customerNo,
|
|
buNo: this.proofDialogData.buNo,
|
|
projectCategory: this.proofDialogData.cProjectTypeDb,
|
|
projectPhase: this.proofDialogData.projectPhase,
|
|
proofingNo: this.proofDialogData.proofingNo,
|
|
proofingNumber: Number(this.proofDialogData.proofingNumber),
|
|
planStartDate: this.proofDialogData.planStartDate,
|
|
requiredDeliveryDate: this.proofDialogData.requiredDeliveryDate,
|
|
actualityDeliveryDate: this.proofDialogData.actualityDeliveryDate,
|
|
proofingStatus: this.proofDialogData.proofingStatus || '草稿',
|
|
remark: this.proofDialogData.remark,
|
|
tracker: this.proofDialogData.projectOwner,
|
|
engineer: this.proofDialogData.engineer,
|
|
priorityLevel: this.proofDialogData.priorityLevel,
|
|
createBy: this.$store.state.user.name,
|
|
updateBy: this.$store.state.user.name
|
|
}
|
|
},
|
|
saveProofRecord () {
|
|
if (!this.validateProofDialogData()) {
|
|
return
|
|
}
|
|
const payload = this.buildProofPayload()
|
|
this.proofSaveLoading = true
|
|
createProofTrackingRecord(payload).then(({ data }) => {
|
|
this.proofSaveLoading = false
|
|
if (data && data.code === 0) {
|
|
this.$message.success(data.msg || '新增打样成功')
|
|
this.proofDialogVisible = false
|
|
this.getDataList()
|
|
} else {
|
|
this.$alert(data && data.msg ? data.msg : '新增打样失败', '错误', { confirmButtonText: '确定' })
|
|
}
|
|
}).catch(() => {
|
|
this.proofSaveLoading = false
|
|
this.$message.error('新增打样异常')
|
|
})
|
|
},
|
|
toggleBatchEdit () {
|
|
this.batchEditMode = !this.batchEditMode
|
|
if (this.batchEditMode) {
|
|
this.cancelCommentsEdit()
|
|
}
|
|
this.$nextTick(() => {
|
|
const tableRef = this.$refs.trackingTable
|
|
if (tableRef && tableRef.doLayout) {
|
|
tableRef.doLayout()
|
|
}
|
|
if (this.batchEditMode) {
|
|
setTimeout(() => {
|
|
this.scrollToRawMaterialColumn()
|
|
}, 0)
|
|
}
|
|
})
|
|
},
|
|
scrollToRawMaterialColumn () {
|
|
const tableRef = this.$refs.trackingTable
|
|
if (!tableRef || !tableRef.$el) {
|
|
return
|
|
}
|
|
const headerWrapper = tableRef.headerWrapper || tableRef.$el.querySelector('.el-table__header-wrapper')
|
|
const bodyWrapper = tableRef.bodyWrapper || tableRef.$el.querySelector('.el-table__body-wrapper')
|
|
if (!headerWrapper || !bodyWrapper) {
|
|
return
|
|
}
|
|
const headerCells = headerWrapper.querySelectorAll('th')
|
|
let targetCell = null
|
|
for (let i = 0; i < headerCells.length; i++) {
|
|
const text = (headerCells[i].innerText || '').replace(/\s+/g, ' ').trim()
|
|
if (text === 'Raw Material') {
|
|
targetCell = headerCells[i]
|
|
break
|
|
}
|
|
}
|
|
if (!targetCell) {
|
|
return
|
|
}
|
|
const fixedLeftWrapper = tableRef.$el.querySelector('.el-table__fixed')
|
|
const fixedLeftWidth = fixedLeftWrapper ? fixedLeftWrapper.offsetWidth : 0
|
|
const nextScrollLeft = Math.max(targetCell.offsetLeft - fixedLeftWidth - 8, 0)
|
|
bodyWrapper.scrollLeft = nextScrollLeft
|
|
headerWrapper.scrollLeft = nextScrollLeft
|
|
},
|
|
saveBatchPlan () {
|
|
const rows = this.selectionRows && this.selectionRows.length > 0 ? this.selectionRows : this.dataList
|
|
if (!rows || rows.length === 0) {
|
|
this.$message.warning('没有可保存的数据')
|
|
return
|
|
}
|
|
const payloadRows = rows.map(row => ({
|
|
trackingId: row.trackingId,
|
|
rawMaterialActualDate: row.rawMaterialActualDate,
|
|
cylinderCutterActualDate: row.cylinderCutterActualDate,
|
|
laminationActualDate: row.laminationActualDate,
|
|
printingActualDate: row.printingActualDate,
|
|
etchingActualDate: row.etchingActualDate,
|
|
slittingPackingActualDate: row.slittingPackingActualDate,
|
|
bondingActualDate: row.bondingActualDate,
|
|
cl60Cl822ActualDate: row.cl60Cl822ActualDate,
|
|
spottingActualDate: row.spottingActualDate,
|
|
encodingActualDate: row.encodingActualDate,
|
|
dieCutActualDate: row.dieCutActualDate,
|
|
inspectionActualDate: row.inspectionActualDate,
|
|
deliveryPackageActualDate: row.deliveryPackageActualDate,
|
|
comments: row.comments == null ? '' : String(row.comments),
|
|
updateBy: this.$store.state.user.name
|
|
}))
|
|
batchUpdateProofTrackingPlan({
|
|
updateBy: this.$store.state.user.name,
|
|
rows: payloadRows
|
|
}).then(({ data }) => {
|
|
if (data && data.code === 0) {
|
|
this.$message.success('批量修改成功')
|
|
this.batchEditMode = false
|
|
this.getDataList()
|
|
} else {
|
|
this.$message.error(data.msg || '批量修改失败')
|
|
}
|
|
}).catch(() => {
|
|
this.$message.error('批量修改异常')
|
|
})
|
|
},
|
|
handleProcessDateChange (row, processCol, dateVal) {
|
|
if (!row || !processCol) {
|
|
return
|
|
}
|
|
const actualDate = this.formatDate(dateVal)
|
|
this.updateProcessFromTable(row, processCol, {
|
|
status: '已完成',
|
|
actualDate: actualDate,
|
|
remark: '表格直接选择日期'
|
|
}, true)
|
|
},
|
|
markProcessComplete (row, processCol) {
|
|
if (!row || !processCol || this.isProcessComplete(row, processCol)) {
|
|
return
|
|
}
|
|
const today = this.formatDate(new Date())
|
|
this.updateProcessFromTable(row, processCol, {
|
|
status: '已完成',
|
|
actualDate: today,
|
|
remark: '表格一键完成'
|
|
}, false, '工序已标记为完成')
|
|
},
|
|
updateProcessFromTable (row, processCol, processData, silentSuccess, successMsg) {
|
|
if (!row || !processCol || !row.trackingId) {
|
|
this.$message.error('工序参数缺失')
|
|
return
|
|
}
|
|
const status = processData && processData.status ? String(processData.status).trim() : ''
|
|
if (!status) {
|
|
this.$message.error('工序状态不能为空')
|
|
return
|
|
}
|
|
const actualDate = processData && processData.actualDate ? this.formatDate(processData.actualDate) : ''
|
|
const inData = {
|
|
trackingId: row.trackingId,
|
|
processCode: processCol.code,
|
|
processName: processCol.label,
|
|
status: status,
|
|
actualDate: actualDate || null,
|
|
remark: processData && processData.remark ? processData.remark : '',
|
|
updateBy: this.$store.state.user.name
|
|
}
|
|
updateProofTrackingProcess(inData).then(({ data }) => {
|
|
if (data && data.code === 0) {
|
|
row[processCol.statusField] = status
|
|
row[processCol.actualField] = actualDate
|
|
const cacheKey = `${row.trackingId}_${processCol.code}`
|
|
if (this.processHistoryMap[cacheKey]) {
|
|
this.$delete(this.processHistoryMap, cacheKey)
|
|
}
|
|
if (!silentSuccess) {
|
|
this.$message.success(successMsg || '工序更新成功')
|
|
}
|
|
} else {
|
|
this.$message.error(data.msg || '工序更新失败')
|
|
this.getDataList()
|
|
}
|
|
}).catch(() => {
|
|
this.$message.error('工序更新异常')
|
|
this.getDataList()
|
|
})
|
|
},
|
|
openProcessDialog (row, processCol) {
|
|
if (!row || !processCol) {
|
|
return
|
|
}
|
|
this.currentRow = row
|
|
this.processForm = {
|
|
trackingId: row.trackingId,
|
|
processCode: processCol.code,
|
|
processName: processCol.label,
|
|
status: row[processCol.statusField] || '未完成',
|
|
actualDate: row[processCol.actualField] || '',
|
|
remark: ''
|
|
}
|
|
this.processHistoryRows = []
|
|
this.processDialogVisible = true
|
|
this.loadProcessHistory(row, processCol, true)
|
|
},
|
|
submitProcessUpdate () {
|
|
if (!this.processForm.trackingId || !this.processForm.processCode) {
|
|
this.$message.error('参数缺失')
|
|
return
|
|
}
|
|
if (!this.processForm.status) {
|
|
this.$message.error('请选择状态')
|
|
return
|
|
}
|
|
const inData = Object.assign({}, this.processForm, {
|
|
updateBy: this.$store.state.user.name
|
|
})
|
|
this.saveProcessLoading = true
|
|
updateProofTrackingProcess(inData).then(({ data }) => {
|
|
this.saveProcessLoading = false
|
|
if (data && data.code === 0) {
|
|
this.$message.success('工序更新成功')
|
|
this.processDialogVisible = false
|
|
this.processHistoryMap = {}
|
|
this.getDataList()
|
|
} else {
|
|
this.$message.error(data.msg || '工序更新失败')
|
|
}
|
|
}).catch(() => {
|
|
this.saveProcessLoading = false
|
|
this.$message.error('工序更新异常')
|
|
})
|
|
},
|
|
finishProof (row) {
|
|
const current = row || this.currentRow
|
|
if (!current || !current.trackingId) {
|
|
this.$message.warning('请先选择记录')
|
|
return
|
|
}
|
|
this.finishForm = {
|
|
trackingId: current.trackingId,
|
|
actualityDeliveryDate: current.actualityDeliveryDate || this.formatDate(new Date())
|
|
}
|
|
this.finishDialogVisible = true
|
|
},
|
|
deleteProof (row) {
|
|
const current = row || this.currentRow
|
|
if (!current || !current.trackingId) {
|
|
this.$message.warning('请先选择记录')
|
|
return
|
|
}
|
|
this.$confirm('确定删除该打样记录吗?该操作仅删除打样记录,不会删除项目和项目物料。', '提示', {
|
|
confirmButtonText: '确定',
|
|
cancelButtonText: '取消',
|
|
type: 'warning'
|
|
}).then(() => {
|
|
deleteProofTracking({
|
|
trackingId: current.trackingId,
|
|
updateBy: this.$store.state.user.name
|
|
}).then(({ data }) => {
|
|
if (data && data.code === 0) {
|
|
this.$message.success('打样记录删除成功')
|
|
this.processHistoryMap = {}
|
|
this.resetProcessTooltip()
|
|
this.getDataList()
|
|
} else {
|
|
this.$message.error((data && data.msg) || '删除打样记录失败')
|
|
}
|
|
}).catch(() => {
|
|
this.$message.error('删除打样记录异常')
|
|
})
|
|
}).catch(() => {})
|
|
},
|
|
submitFinishProof () {
|
|
if (!this.finishForm.trackingId) {
|
|
this.$message.warning('跟踪记录ID不能为空')
|
|
return
|
|
}
|
|
if (!this.finishForm.actualityDeliveryDate) {
|
|
this.$message.warning('请选择实际完成日期')
|
|
return
|
|
}
|
|
this.finishSaveLoading = true
|
|
finishProofTracking({
|
|
trackingId: this.finishForm.trackingId,
|
|
actualityDeliveryDate: this.finishForm.actualityDeliveryDate,
|
|
updateBy: this.$store.state.user.name
|
|
}).then(({ data }) => {
|
|
this.finishSaveLoading = false
|
|
if (data && data.code === 0) {
|
|
this.$message.success('打样完成成功')
|
|
this.finishDialogVisible = false
|
|
this.getDataList()
|
|
} else {
|
|
this.$message.error(data.msg || '打样完成失败')
|
|
}
|
|
}).catch(() => {
|
|
this.finishSaveLoading = false
|
|
this.$message.error('打样完成异常')
|
|
})
|
|
},
|
|
getProcessCacheKey (row, processCol) {
|
|
if (!row || !processCol || !row.trackingId) {
|
|
return ''
|
|
}
|
|
return `${row.trackingId}_${processCol.code}`
|
|
},
|
|
resetProcessTooltip () {
|
|
this.processTooltipHoverKey = ''
|
|
this.processTooltip.visible = false
|
|
this.processTooltip.content = ''
|
|
},
|
|
hideProcessTooltip () {
|
|
this.processTooltip.visible = false
|
|
this.processTooltip.content = ''
|
|
},
|
|
updateProcessTooltipPosition (event) {
|
|
if (!event) {
|
|
return
|
|
}
|
|
const offsetX = 12
|
|
const offsetY = 16
|
|
let left = event.clientX + offsetX
|
|
let top = event.clientY + offsetY
|
|
const maxWidth = 220
|
|
const maxHeight = 120
|
|
if (left + maxWidth > window.innerWidth - 8) {
|
|
left = window.innerWidth - maxWidth - 8
|
|
}
|
|
if (top + maxHeight > window.innerHeight - 8) {
|
|
top = event.clientY - maxHeight - 8
|
|
}
|
|
this.processTooltip.left = Math.max(8, left)
|
|
this.processTooltip.top = Math.max(8, top)
|
|
},
|
|
handleProcessTooltipMouseMove (event) {
|
|
if (!this.processTooltip.visible) {
|
|
return
|
|
}
|
|
this.updateProcessTooltipPosition(event)
|
|
},
|
|
handleProcessTooltipMouseLeave () {
|
|
this.processTooltipHoverKey = ''
|
|
this.hideProcessTooltip()
|
|
},
|
|
handleProcessTooltipMouseEnter (row, processCol, event) {
|
|
const cacheKey = this.getProcessCacheKey(row, processCol)
|
|
if (!cacheKey) {
|
|
return
|
|
}
|
|
this.processTooltipHoverKey = cacheKey
|
|
this.updateProcessTooltipPosition(event)
|
|
const showTooltip = () => {
|
|
if (this.processTooltipHoverKey !== cacheKey) {
|
|
return
|
|
}
|
|
if (!this.hasProcessHistory(row, processCol)) {
|
|
this.hideProcessTooltip()
|
|
return
|
|
}
|
|
const content = this.getProcessTooltip(row, processCol)
|
|
if (!content) {
|
|
this.hideProcessTooltip()
|
|
return
|
|
}
|
|
this.processTooltip.content = content
|
|
this.processTooltip.visible = true
|
|
}
|
|
if (Object.prototype.hasOwnProperty.call(this.processHistoryMap, cacheKey)) {
|
|
showTooltip()
|
|
return
|
|
}
|
|
this.loadProcessHistory(row, processCol, false).then(() => {
|
|
showTooltip()
|
|
})
|
|
},
|
|
loadProcessHistory (row, processCol, refreshDialog) {
|
|
if (!row || !row.trackingId) {
|
|
return Promise.resolve([])
|
|
}
|
|
const cacheKey = this.getProcessCacheKey(row, processCol)
|
|
if (Object.prototype.hasOwnProperty.call(this.processHistoryMap, cacheKey)) {
|
|
const cachedRows = this.processHistoryMap[cacheKey] || []
|
|
if (refreshDialog) {
|
|
this.processHistoryRows = cachedRows
|
|
}
|
|
return Promise.resolve(cachedRows)
|
|
}
|
|
return queryProofTrackingProcessHistory({
|
|
trackingId: row.trackingId,
|
|
processCode: processCol.code
|
|
}).then(({ data }) => {
|
|
let rows = []
|
|
if (data && data.code === 0) {
|
|
rows = data.rows || []
|
|
// Vue2 对对象新增 key 需要使用 $set 才能触发视图更新(tooltip 才会刷新历史列表)
|
|
this.$set(this.processHistoryMap, cacheKey, rows)
|
|
if (refreshDialog) {
|
|
this.processHistoryRows = rows
|
|
}
|
|
}
|
|
return rows
|
|
}).catch(() => {
|
|
if (refreshDialog) {
|
|
this.processHistoryRows = []
|
|
}
|
|
this.$set(this.processHistoryMap, cacheKey, [])
|
|
return []
|
|
})
|
|
},
|
|
hasProcessHistory (row, processCol) {
|
|
if (!row || !processCol || !row.trackingId) {
|
|
return false
|
|
}
|
|
const cacheKey = `${row.trackingId}_${processCol.code}`
|
|
const rows = this.processHistoryMap[cacheKey] || []
|
|
return rows.length > 0
|
|
},
|
|
getProcessTooltip (row, processCol) {
|
|
if (!row || !processCol) {
|
|
return ''
|
|
}
|
|
const cacheKey = row.trackingId ? `${row.trackingId}_${processCol.code}` : ''
|
|
const rows = this.processHistoryMap[cacheKey] || []
|
|
|
|
const dateList = []
|
|
const pushDate = (dateVal) => {
|
|
const formatted = this.formatDate(dateVal)
|
|
if (!formatted) {
|
|
return
|
|
}
|
|
if (dateList.indexOf(formatted) === -1) {
|
|
dateList.push(formatted)
|
|
}
|
|
}
|
|
|
|
// 先放当前实际完成日期,再放历史变更日期(实际)
|
|
pushDate(row[processCol.actualField])
|
|
rows.forEach(item => {
|
|
pushDate(item.newActualDate)
|
|
pushDate(item.oldActualDate)
|
|
})
|
|
|
|
if (dateList.length === 0) {
|
|
return ''
|
|
}
|
|
return dateList.join('\n')
|
|
},
|
|
isProcessComplete (row, processCol) {
|
|
if (!row || !processCol) {
|
|
return false
|
|
}
|
|
const statusVal = row[processCol.statusField]
|
|
const status = statusVal ? String(statusVal).trim() : ''
|
|
|
|
if (!status) {
|
|
// 兼容历史数据:若没有状态但有实际完成日期,也按完成处理
|
|
return !!this.formatDate(row[processCol.actualField])
|
|
}
|
|
if (status === '未完成' || status === '进行中') {
|
|
return false
|
|
}
|
|
if (status === '已完成' || status === '打样完成') {
|
|
return true
|
|
}
|
|
return status.indexOf('完成') > -1 && status.indexOf('未') === -1
|
|
},
|
|
formatDate (val) {
|
|
if (!val) {
|
|
return ''
|
|
}
|
|
if (typeof val === 'string') {
|
|
return val.length > 10 ? val.substring(0, 10) : val
|
|
}
|
|
const date = new Date(val)
|
|
if (isNaN(date.getTime())) {
|
|
return ''
|
|
}
|
|
const y = date.getFullYear()
|
|
const m = `${date.getMonth() + 1}`.padStart(2, '0')
|
|
const d = `${date.getDate()}`.padStart(2, '0')
|
|
return `${y}-${m}-${d}`
|
|
},
|
|
formatDateTime (val) {
|
|
if (!val) {
|
|
return ''
|
|
}
|
|
if (typeof val === 'string') {
|
|
return val.length > 19 ? val.substring(0, 19) : val
|
|
}
|
|
const date = new Date(val)
|
|
if (isNaN(date.getTime())) {
|
|
return ''
|
|
}
|
|
const y = date.getFullYear()
|
|
const m = `${date.getMonth() + 1}`.padStart(2, '0')
|
|
const d = `${date.getDate()}`.padStart(2, '0')
|
|
const hh = `${date.getHours()}`.padStart(2, '0')
|
|
const mm = `${date.getMinutes()}`.padStart(2, '0')
|
|
const ss = `${date.getSeconds()}`.padStart(2, '0')
|
|
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style >
|
|
.data-table .cell {
|
|
line-height: 26px;
|
|
font-size: 12px;
|
|
height: 26px;
|
|
}
|
|
|
|
.search-form {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.button-group-col {
|
|
width: 100%;
|
|
margin-top: 16px;
|
|
}
|
|
|
|
.button-row {
|
|
width: 100%;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.bu-process-config-dialog .el-checkbox-group {
|
|
display: grid;
|
|
grid-template-columns: repeat(5, minmax(110px, 1fr));
|
|
column-gap: 12px;
|
|
row-gap: 8px;
|
|
align-items: center;
|
|
}
|
|
|
|
.bu-process-config-dialog .bu-process-list-column .cell {
|
|
white-space: normal !important;
|
|
height: auto !important;
|
|
line-height: 20px;
|
|
padding-top: 6px;
|
|
padding-bottom: 6px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.bu-process-config-dialog .bu-process-list-column {
|
|
vertical-align: top;
|
|
}
|
|
|
|
.bu-process-config-dialog .bu-process-list-column .el-checkbox,
|
|
.bu-process-config-dialog .bu-process-list-column .el-checkbox + .el-checkbox {
|
|
width: 100%;
|
|
margin: 0 !important;
|
|
}
|
|
|
|
.bu-process-config-dialog .bu-process-list-column .el-checkbox__label {
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.button-col {
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.button-col .el-button {
|
|
width: 100%;
|
|
}
|
|
|
|
.one-key-grid-form {
|
|
padding: 0 8px;
|
|
}
|
|
|
|
.one-key-grid-form .el-form-item {
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.proof-grid-form {
|
|
padding: 0 8px;
|
|
}
|
|
|
|
.proof-grid-form .el-form-item {
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.big-label a {
|
|
color: #35b4b4;
|
|
}
|
|
|
|
.sync-text--ok {
|
|
color: #67c23a;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.sync-text--pending {
|
|
color: #e6a23c;
|
|
}
|
|
|
|
.process-cell {
|
|
background: #fff;
|
|
min-height: 44px;
|
|
padding: 4px 2px;
|
|
}
|
|
|
|
.process-cell.is-complete {
|
|
background: #ececec;
|
|
}
|
|
|
|
.process-cell.is-complete .link-date {
|
|
color: #8c8c8c;
|
|
}
|
|
|
|
.process-cell.is-complete .link-date:hover,
|
|
.process-cell.is-complete .link-date:focus {
|
|
color: #8c8c8c;
|
|
}
|
|
|
|
.process-cell--masked {
|
|
background: transparent !important;
|
|
}
|
|
|
|
.process-content {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 4px;
|
|
text-align: center;
|
|
line-height: 18px;
|
|
}
|
|
|
|
.process-complete-btn {
|
|
padding: 4px 8px;
|
|
min-width: 12px;
|
|
}
|
|
|
|
.comments-cell {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
min-height: 26px;
|
|
}
|
|
|
|
.comments-edit-input {
|
|
flex: 1;
|
|
}
|
|
|
|
.comments-save-btn {
|
|
padding: 4px 7px;
|
|
min-width: 28px;
|
|
}
|
|
|
|
.comments-text {
|
|
width: 100%;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.process-date-tooltip {
|
|
white-space: pre-line;
|
|
}
|
|
|
|
.process-history-tooltip {
|
|
position: fixed;
|
|
z-index: 3000;
|
|
max-width: 220px;
|
|
padding: 10px 12px;
|
|
border-radius: 4px;
|
|
background: rgba(48, 49, 51, 0.95);
|
|
color: #fff;
|
|
font-size: 12px;
|
|
line-height: 1.5;
|
|
white-space: pre-line;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.link-date {
|
|
color: #0c4dbb;
|
|
text-decoration: none;
|
|
}
|
|
|
|
.link-date:hover,
|
|
.link-date:focus {
|
|
text-decoration: none;
|
|
}
|
|
|
|
.actual-date {
|
|
margin-top: 2px;
|
|
color: #666;
|
|
}
|
|
|
|
.finish-dialog-tip {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
margin-bottom: 10px;
|
|
padding: 8px 10px;
|
|
border-radius: 4px;
|
|
background: #f4f8ff;
|
|
color: #3a4b5f;
|
|
font-size: 12px;
|
|
}
|
|
|
|
.finish-dialog-tip i {
|
|
color: #409eff;
|
|
}
|
|
|
|
.finish-tip-highlight {
|
|
font-size: 13px;
|
|
font-weight: 700;
|
|
color: #1f2d3d;
|
|
}
|
|
|
|
.finish-proof-dialog .el-dialog__body {
|
|
padding-bottom: 8px;
|
|
}
|
|
|
|
.finish-form .el-form-item {
|
|
margin-bottom: 14px;
|
|
}
|
|
|
|
.action-link {
|
|
color: #0c4dbb;
|
|
margin: 0 4px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.edit-link {
|
|
color: #e6a23c;
|
|
}
|
|
|
|
.delete-link {
|
|
color: #f56c6c;
|
|
}
|
|
|
|
.end-link {
|
|
color: #a303ff;
|
|
}
|
|
</style>
|
|
|