|
|
@ -58,6 +58,7 @@ |
|
|
>事业部进度设置</el-button> |
|
|
>事业部进度设置</el-button> |
|
|
<el-button type="info" v-if="isAuth('833001005:set2')" plain @click="openDefaultProcessConfigDialog">默认进度设置</el-button> |
|
|
<el-button type="info" v-if="isAuth('833001005:set2')" plain @click="openDefaultProcessConfigDialog">默认进度设置</el-button> |
|
|
<el-button type="danger" plain :loading="deleteProofLoading" @click="deleteSelectedProofs">删除</el-button> |
|
|
<el-button type="danger" plain :loading="deleteProofLoading" @click="deleteSelectedProofs">删除</el-button> |
|
|
|
|
|
<el-button type="warning" plain :loading="costRateRecalcLoading" @click="recalculateCostByRate">按汇率重算</el-button> |
|
|
<el-tooltip |
|
|
<el-tooltip |
|
|
style="margin-top: 3px; margin-left: 10px" |
|
|
style="margin-top: 3px; margin-left: 10px" |
|
|
placement="top"> |
|
|
placement="top"> |
|
|
@ -67,6 +68,19 @@ |
|
|
</template> |
|
|
</template> |
|
|
<i class="el-icon-question default-process-tip-icon"></i> |
|
|
<i class="el-icon-question default-process-tip-icon"></i> |
|
|
</el-tooltip> |
|
|
</el-tooltip> |
|
|
|
|
|
<span class="cost-rate-tip"> |
|
|
|
|
|
汇率 |
|
|
|
|
|
<el-input |
|
|
|
|
|
v-model="usdCnyExchangeRateDraft" |
|
|
|
|
|
class="cost-rate-input" |
|
|
|
|
|
size="mini" |
|
|
|
|
|
clearable |
|
|
|
|
|
placeholder="未设置" |
|
|
|
|
|
:disabled="costRateSaving" |
|
|
|
|
|
@blur="saveExchangeRate" |
|
|
|
|
|
@keyup.enter.native="$event.target.blur()" |
|
|
|
|
|
/> |
|
|
|
|
|
</span> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
<el-form v-show="searchExpanded" :inline="true" :model="searchData" label-position="top" class="search-form"> |
|
|
<el-form v-show="searchExpanded" :inline="true" :model="searchData" label-position="top" class="search-form"> |
|
|
@ -298,6 +312,49 @@ |
|
|
v-else-if="item.columnProp === 'deliveryVariance'" |
|
|
v-else-if="item.columnProp === 'deliveryVariance'" |
|
|
:class="{ 'delivery-variance-alert': isDeliveryVarianceAlert(scope.row) }" |
|
|
:class="{ 'delivery-variance-alert': isDeliveryVarianceAlert(scope.row) }" |
|
|
>{{ getTrackingColumnDisplayValue(scope.row, item.columnProp) }}</span> |
|
|
>{{ getTrackingColumnDisplayValue(scope.row, item.columnProp) }}</span> |
|
|
|
|
|
<div |
|
|
|
|
|
v-else-if="isCostManualColumn(item.columnProp)" |
|
|
|
|
|
class="cost-cell" |
|
|
|
|
|
@click.stop="startCostEdit(scope.row, item.columnProp)" |
|
|
|
|
|
> |
|
|
|
|
|
<el-select |
|
|
|
|
|
v-if="isCostEditing(scope.row, item.columnProp) && item.columnProp === 'customizedForMasAls'" |
|
|
|
|
|
ref="costEditor" |
|
|
|
|
|
v-model="costEditDraft" |
|
|
|
|
|
class="cost-editor" |
|
|
|
|
|
size="mini" |
|
|
|
|
|
filterable |
|
|
|
|
|
allow-create |
|
|
|
|
|
default-first-option |
|
|
|
|
|
clearable |
|
|
|
|
|
placeholder="请选择或输入" |
|
|
|
|
|
@visible-change="handleCostSelectVisible($event, scope.row, item.columnProp)" |
|
|
|
|
|
@keyup.esc.native="cancelCostEdit(scope.row)" |
|
|
|
|
|
> |
|
|
|
|
|
<el-option |
|
|
|
|
|
v-for="option in customizedForMasAlsOptions" |
|
|
|
|
|
:key="option" |
|
|
|
|
|
:label="option" |
|
|
|
|
|
:value="option" |
|
|
|
|
|
/> |
|
|
|
|
|
</el-select> |
|
|
|
|
|
<el-input |
|
|
|
|
|
v-else-if="isCostEditing(scope.row, item.columnProp)" |
|
|
|
|
|
ref="costEditor" |
|
|
|
|
|
v-model="costEditDraft" |
|
|
|
|
|
class="cost-editor" |
|
|
|
|
|
size="mini" |
|
|
|
|
|
@keydown.enter.native.prevent="saveCostEdit(scope.row, item.columnProp)" |
|
|
|
|
|
@keyup.esc.native="cancelCostEdit(scope.row)" |
|
|
|
|
|
@blur="saveCostEdit(scope.row, item.columnProp)" |
|
|
|
|
|
/> |
|
|
|
|
|
<span v-else class="cost-display cost-display--editable">{{ getCostManualDisplay(scope.row, item.columnProp) }}</span> |
|
|
|
|
|
</div> |
|
|
|
|
|
<span |
|
|
|
|
|
v-else-if="isCostCalculatedColumn(item.columnProp)" |
|
|
|
|
|
class="cost-calculated-text" |
|
|
|
|
|
:title="getCostCalculatedTitle(scope.row, item.columnProp)" |
|
|
|
|
|
>{{ formatCostAmount(getCostCalculatedValue(scope.row, item.columnProp)) }}</span> |
|
|
<span v-else>{{ getTrackingColumnDisplayValue(scope.row, item.columnProp) }}</span> |
|
|
<span v-else>{{ getTrackingColumnDisplayValue(scope.row, item.columnProp) }}</span> |
|
|
</template> |
|
|
</template> |
|
|
</el-table-column> |
|
|
</el-table-column> |
|
|
@ -917,7 +974,7 @@ |
|
|
</el-col> |
|
|
</el-col> |
|
|
<el-col :span="6" v-show="isOneKeyCreateFieldVisible('proofingStatus')"> |
|
|
<el-col :span="6" v-show="isOneKeyCreateFieldVisible('proofingStatus')"> |
|
|
<el-form-item label="打样状态"> |
|
|
<el-form-item label="打样状态"> |
|
|
<!-- 新建固定草稿;修改只允许改成终止/取消/报废,选项按打开弹窗时的原状态生成,避免选中后丢掉“保持原状态”。 --> |
|
|
|
|
|
|
|
|
<!-- 新建固定草稿。修改默认可改成终止/取消/报废;只有打开时原状态已是这三种,才额外给出“进行中”。选项锚定原状态,避免选中后无法改回。 --> |
|
|
<el-select |
|
|
<el-select |
|
|
v-model="oneKeyForm.proofingStatus" |
|
|
v-model="oneKeyForm.proofingStatus" |
|
|
:disabled="oneKeyDialogMode === 'create'" |
|
|
:disabled="oneKeyDialogMode === 'create'" |
|
|
@ -1295,6 +1352,9 @@ import { |
|
|
batchSyncProofTracking, |
|
|
batchSyncProofTracking, |
|
|
batchSyncProjectPartTracking, |
|
|
batchSyncProjectPartTracking, |
|
|
updateProofTrackingComments, |
|
|
updateProofTrackingComments, |
|
|
|
|
|
updateProofTrackingCost, |
|
|
|
|
|
saveProofTrackingExchangeRate, |
|
|
|
|
|
refreshProofTrackingCostByRate, |
|
|
updateProofTrackingProcess |
|
|
updateProofTrackingProcess |
|
|
} from '@/api/sampleTracking/sampleTracking' |
|
|
} from '@/api/sampleTracking/sampleTracking' |
|
|
import { searchExpApplyList } from '@/api/erf/erf' |
|
|
import { searchExpApplyList } from '@/api/erf/erf' |
|
|
@ -1398,6 +1458,15 @@ const ONE_KEY_ROLE_FIELDS = [ |
|
|
'docEngineer2' |
|
|
'docEngineer2' |
|
|
] |
|
|
] |
|
|
|
|
|
|
|
|
|
|
|
const COST_MANUAL_COLUMNS = ['customizedForMasAls', 'tpKctUsd', 'toolingCostCn', 'sampleCostFromFnCn'] |
|
|
|
|
|
const COST_CALCULATED_COLUMNS = ['sampleCostUsd', 'toolingCostUsd', 'sampleAndToolingCostUsd', 'sampleCostFromFnUsd'] |
|
|
|
|
|
const CUSTOMIZED_FOR_MAS_ALS_OPTIONS = [ |
|
|
|
|
|
'PM-standard', |
|
|
|
|
|
'PM-Customized for ALS', |
|
|
|
|
|
'PM-Customized for MAS', |
|
|
|
|
|
'PO' |
|
|
|
|
|
] |
|
|
|
|
|
|
|
|
const DEFAULT_TRACKING_COLUMNS = [ |
|
|
const DEFAULT_TRACKING_COLUMNS = [ |
|
|
{ |
|
|
{ |
|
|
serialNumber: 'proofTrackingTable1ProjectNo', |
|
|
serialNumber: 'proofTrackingTable1ProjectNo', |
|
|
@ -1525,6 +1594,21 @@ const DEFAULT_TRACKING_COLUMNS = [ |
|
|
columnWidth: 120, |
|
|
columnWidth: 120, |
|
|
showOverflowTooltip: true |
|
|
showOverflowTooltip: true |
|
|
}, |
|
|
}, |
|
|
|
|
|
// 紧跟 PM/Sales:下拉可选,也允许手工录入文本。 |
|
|
|
|
|
{ |
|
|
|
|
|
serialNumber: 'proofTrackingTable1CustomizedForMasAls', |
|
|
|
|
|
columnProp: 'customizedForMasAls', |
|
|
|
|
|
headerAlign: 'center', |
|
|
|
|
|
align: 'left', |
|
|
|
|
|
columnLabel: 'Customized for MAS/ALS', |
|
|
|
|
|
columnHidden: false, |
|
|
|
|
|
columnImage: false, |
|
|
|
|
|
columnSortable: false, |
|
|
|
|
|
status: true, |
|
|
|
|
|
fixed: '', |
|
|
|
|
|
columnWidth: 180, |
|
|
|
|
|
showOverflowTooltip: true |
|
|
|
|
|
}, |
|
|
{ |
|
|
{ |
|
|
serialNumber: 'proofTrackingTable1ProofingNo', |
|
|
serialNumber: 'proofTrackingTable1ProofingNo', |
|
|
columnProp: 'proofingNo', |
|
|
columnProp: 'proofingNo', |
|
|
@ -1568,6 +1652,105 @@ const DEFAULT_TRACKING_COLUMNS = [ |
|
|
columnWidth: 90, |
|
|
columnWidth: 90, |
|
|
showOverflowTooltip: false |
|
|
showOverflowTooltip: false |
|
|
}, |
|
|
}, |
|
|
|
|
|
// 成本列紧跟 Sample Qty:单价、模具费、样品费都按数量折算,和数量放在一起看。 |
|
|
|
|
|
{ |
|
|
|
|
|
serialNumber: 'proofTrackingTable1TpKctUsd', |
|
|
|
|
|
columnProp: 'tpKctUsd', |
|
|
|
|
|
headerAlign: 'center', |
|
|
|
|
|
align: 'center', |
|
|
|
|
|
columnLabel: 'TP(KCT/USD)', |
|
|
|
|
|
columnHidden: false, |
|
|
|
|
|
columnImage: false, |
|
|
|
|
|
columnSortable: false, |
|
|
|
|
|
status: true, |
|
|
|
|
|
fixed: '', |
|
|
|
|
|
columnWidth: 120, |
|
|
|
|
|
showOverflowTooltip: false |
|
|
|
|
|
}, |
|
|
|
|
|
{ |
|
|
|
|
|
serialNumber: 'proofTrackingTable1SampleCostUsd', |
|
|
|
|
|
columnProp: 'sampleCostUsd', |
|
|
|
|
|
headerAlign: 'center', |
|
|
|
|
|
align: 'center', |
|
|
|
|
|
columnLabel: 'Sample Cost/USD', |
|
|
|
|
|
columnHidden: false, |
|
|
|
|
|
columnImage: false, |
|
|
|
|
|
columnSortable: false, |
|
|
|
|
|
status: true, |
|
|
|
|
|
fixed: '', |
|
|
|
|
|
columnWidth: 140, |
|
|
|
|
|
showOverflowTooltip: false |
|
|
|
|
|
}, |
|
|
|
|
|
{ |
|
|
|
|
|
serialNumber: 'proofTrackingTable1ToolingCostCn', |
|
|
|
|
|
columnProp: 'toolingCostCn', |
|
|
|
|
|
headerAlign: 'center', |
|
|
|
|
|
align: 'center', |
|
|
|
|
|
columnLabel: 'Tooling cost/CN', |
|
|
|
|
|
columnHidden: false, |
|
|
|
|
|
columnImage: false, |
|
|
|
|
|
columnSortable: false, |
|
|
|
|
|
status: true, |
|
|
|
|
|
fixed: '', |
|
|
|
|
|
columnWidth: 140, |
|
|
|
|
|
showOverflowTooltip: false |
|
|
|
|
|
}, |
|
|
|
|
|
{ |
|
|
|
|
|
serialNumber: 'proofTrackingTable1ToolingCostUsd', |
|
|
|
|
|
columnProp: 'toolingCostUsd', |
|
|
|
|
|
headerAlign: 'center', |
|
|
|
|
|
align: 'center', |
|
|
|
|
|
columnLabel: 'Tooling Cost/USD', |
|
|
|
|
|
columnHidden: false, |
|
|
|
|
|
columnImage: false, |
|
|
|
|
|
columnSortable: false, |
|
|
|
|
|
status: true, |
|
|
|
|
|
fixed: '', |
|
|
|
|
|
columnWidth: 150, |
|
|
|
|
|
showOverflowTooltip: false |
|
|
|
|
|
}, |
|
|
|
|
|
{ |
|
|
|
|
|
serialNumber: 'proofTrackingTable1SampleAndToolingCostUsd', |
|
|
|
|
|
columnProp: 'sampleAndToolingCostUsd', |
|
|
|
|
|
headerAlign: 'center', |
|
|
|
|
|
align: 'center', |
|
|
|
|
|
columnLabel: 'Sample and Tooling Cost/USD', |
|
|
|
|
|
columnHidden: false, |
|
|
|
|
|
columnImage: false, |
|
|
|
|
|
columnSortable: false, |
|
|
|
|
|
status: true, |
|
|
|
|
|
fixed: '', |
|
|
|
|
|
columnWidth: 210, |
|
|
|
|
|
showOverflowTooltip: false |
|
|
|
|
|
}, |
|
|
|
|
|
{ |
|
|
|
|
|
serialNumber: 'proofTrackingTable1SampleCostFromFnCn', |
|
|
|
|
|
columnProp: 'sampleCostFromFnCn', |
|
|
|
|
|
headerAlign: 'center', |
|
|
|
|
|
align: 'center', |
|
|
|
|
|
columnLabel: 'Sample Cost from FN/CN', |
|
|
|
|
|
columnHidden: false, |
|
|
|
|
|
columnImage: false, |
|
|
|
|
|
columnSortable: false, |
|
|
|
|
|
status: true, |
|
|
|
|
|
fixed: '', |
|
|
|
|
|
columnWidth: 180, |
|
|
|
|
|
showOverflowTooltip: false |
|
|
|
|
|
}, |
|
|
|
|
|
{ |
|
|
|
|
|
serialNumber: 'proofTrackingTable1SampleCostFromFnUsd', |
|
|
|
|
|
columnProp: 'sampleCostFromFnUsd', |
|
|
|
|
|
headerAlign: 'center', |
|
|
|
|
|
align: 'center', |
|
|
|
|
|
columnLabel: 'Sample Cost from FN/USD', |
|
|
|
|
|
columnHidden: false, |
|
|
|
|
|
columnImage: false, |
|
|
|
|
|
columnSortable: false, |
|
|
|
|
|
status: true, |
|
|
|
|
|
fixed: '', |
|
|
|
|
|
columnWidth: 190, |
|
|
|
|
|
showOverflowTooltip: false |
|
|
|
|
|
}, |
|
|
{ |
|
|
{ |
|
|
serialNumber: 'proofTrackingTable1PmInqueryTime', |
|
|
serialNumber: 'proofTrackingTable1PmInqueryTime', |
|
|
columnProp: 'pmInqueryTime', |
|
|
columnProp: 'pmInqueryTime', |
|
|
@ -1907,6 +2090,15 @@ export default { |
|
|
commentsEditingTrackingId: null, |
|
|
commentsEditingTrackingId: null, |
|
|
commentsDraft: '', |
|
|
commentsDraft: '', |
|
|
commentsSaveLoading: false, |
|
|
commentsSaveLoading: false, |
|
|
|
|
|
costEditingKey: '', |
|
|
|
|
|
costEditDraft: '', |
|
|
|
|
|
costEditOriginal: '', |
|
|
|
|
|
costSelectReady: false, |
|
|
|
|
|
usdCnyExchangeRate: null, |
|
|
|
|
|
usdCnyExchangeRateDraft: '', |
|
|
|
|
|
costRateSaving: false, |
|
|
|
|
|
costRateRecalcLoading: false, |
|
|
|
|
|
customizedForMasAlsOptions: CUSTOMIZED_FOR_MAS_ALS_OPTIONS, |
|
|
// 工序日期按需编辑:空字符串表示未打开日期组件。 |
|
|
// 工序日期按需编辑:空字符串表示未打开日期组件。 |
|
|
processDateEditingKey: '', |
|
|
processDateEditingKey: '', |
|
|
|
|
|
|
|
|
@ -1971,6 +2163,7 @@ export default { |
|
|
this.destroyDefaultProcessConfigSortable() |
|
|
this.destroyDefaultProcessConfigSortable() |
|
|
this.clearProcessDateEditClickTimer() |
|
|
this.clearProcessDateEditClickTimer() |
|
|
this.exitProcessDateEdit() |
|
|
this.exitProcessDateEdit() |
|
|
|
|
|
this.exitCostEdit() |
|
|
}, |
|
|
}, |
|
|
beforeDestroy () { |
|
|
beforeDestroy () { |
|
|
if (this.$store.state.common.contentIsNeedRefresh) { |
|
|
if (this.$store.state.common.contentIsNeedRefresh) { |
|
|
@ -1982,6 +2175,7 @@ export default { |
|
|
} |
|
|
} |
|
|
this.clearProcessDateEditClickTimer() |
|
|
this.clearProcessDateEditClickTimer() |
|
|
this.exitProcessDateEdit() |
|
|
this.exitProcessDateEdit() |
|
|
|
|
|
this.exitCostEdit() |
|
|
this.unbindTrackingTableResize() |
|
|
this.unbindTrackingTableResize() |
|
|
}, |
|
|
}, |
|
|
watch: { |
|
|
watch: { |
|
|
@ -2056,12 +2250,16 @@ export default { |
|
|
if (this.oneKeyDialogMode === 'create') { |
|
|
if (this.oneKeyDialogMode === 'create') { |
|
|
return ['草稿', '进行中', '打样完成'] |
|
|
return ['草稿', '进行中', '打样完成'] |
|
|
} |
|
|
} |
|
|
// 选项锚定打开弹窗时的原状态,避免选中终止后“进行中”从下拉里消失,用户无法在保存前改回。 |
|
|
|
|
|
|
|
|
// 选项锚定打开弹窗时的原状态,避免选中后丢掉当前值、保存前无法改回。 |
|
|
|
|
|
// “进行中”只在原状态为终止/取消/报废时作为可改目标加入;草稿等状态不能改成进行中。 |
|
|
|
|
|
// 原状态本身已是进行中时仍保留该值,否则下拉无法显示当前状态。 |
|
|
const currentStatus = this.oneKeyOriginalProofingStatus |
|
|
const currentStatus = this.oneKeyOriginalProofingStatus |
|
|
? String(this.oneKeyOriginalProofingStatus).trim() |
|
|
? String(this.oneKeyOriginalProofingStatus).trim() |
|
|
: '' |
|
|
: '' |
|
|
const options = [] |
|
|
const options = [] |
|
|
if (currentStatus && this.proofingStatusChangeOptions.indexOf(currentStatus) === -1) { |
|
|
|
|
|
|
|
|
if (this.isClosedProofingStatusValue(currentStatus)) { |
|
|
|
|
|
options.push('进行中') |
|
|
|
|
|
} else if (currentStatus) { |
|
|
options.push(currentStatus) |
|
|
options.push(currentStatus) |
|
|
} |
|
|
} |
|
|
this.proofingStatusChangeOptions.forEach(item => { |
|
|
this.proofingStatusChangeOptions.forEach(item => { |
|
|
@ -4387,10 +4585,13 @@ export default { |
|
|
// 列表会整表换行数据,未提交的工序日期编辑态不能带到新行上。 |
|
|
// 列表会整表换行数据,未提交的工序日期编辑态不能带到新行上。 |
|
|
this.clearProcessDateEditClickTimer() |
|
|
this.clearProcessDateEditClickTimer() |
|
|
this.exitProcessDateEdit() |
|
|
this.exitProcessDateEdit() |
|
|
|
|
|
this.exitCostEdit() |
|
|
searchProofTracking(inData).then(({ data }) => { |
|
|
searchProofTracking(inData).then(({ data }) => { |
|
|
this.dataListLoading = false |
|
|
this.dataListLoading = false |
|
|
this.resetProcessTooltip() |
|
|
this.resetProcessTooltip() |
|
|
if (data && data.code === 0) { |
|
|
if (data && data.code === 0) { |
|
|
|
|
|
this.usdCnyExchangeRate = data.usdCnyExchangeRate == null ? null : data.usdCnyExchangeRate |
|
|
|
|
|
this.usdCnyExchangeRateDraft = this.usdCnyExchangeRate == null ? '' : this.formatCostDisplay(this.usdCnyExchangeRate) |
|
|
this.dataList = (data.page && data.page.list) || [] |
|
|
this.dataList = (data.page && data.page.list) || [] |
|
|
this.syncDataListProcessValues() |
|
|
this.syncDataListProcessValues() |
|
|
this.resetDataListPageOrderIndexes() |
|
|
this.resetDataListPageOrderIndexes() |
|
|
@ -4766,6 +4967,438 @@ export default { |
|
|
this.$message.error('Comments保存异常') |
|
|
this.$message.error('Comments保存异常') |
|
|
}) |
|
|
}) |
|
|
}, |
|
|
}, |
|
|
|
|
|
isCostManualColumn (columnProp) { |
|
|
|
|
|
return COST_MANUAL_COLUMNS.indexOf(columnProp) > -1 |
|
|
|
|
|
}, |
|
|
|
|
|
isCostCalculatedColumn (columnProp) { |
|
|
|
|
|
return COST_CALCULATED_COLUMNS.indexOf(columnProp) > -1 |
|
|
|
|
|
}, |
|
|
|
|
|
isCostEditing (row, columnProp) { |
|
|
|
|
|
return !!row && this.costEditingKey === `${row.trackingId}:${columnProp}` |
|
|
|
|
|
}, |
|
|
|
|
|
isCostEditingRow (row) { |
|
|
|
|
|
if (!row || !this.costEditingKey) { |
|
|
|
|
|
return false |
|
|
|
|
|
} |
|
|
|
|
|
return this.costEditingKey.indexOf(`${row.trackingId}:`) === 0 |
|
|
|
|
|
}, |
|
|
|
|
|
formatCostDisplay (value) { |
|
|
|
|
|
if (value == null || String(value).trim() === '') { |
|
|
|
|
|
return '' |
|
|
|
|
|
} |
|
|
|
|
|
const number = Number(value) |
|
|
|
|
|
if (!Number.isFinite(number)) { |
|
|
|
|
|
return String(value) |
|
|
|
|
|
} |
|
|
|
|
|
return number.toFixed(6).replace(/\.?0+$/, '') |
|
|
|
|
|
}, |
|
|
|
|
|
// 费用金额固定两位。汇率仍走 formatCostDisplay,避免把 6.685421 收成 6.69。 |
|
|
|
|
|
formatCostAmount (value) { |
|
|
|
|
|
if (value == null || String(value).trim() === '') { |
|
|
|
|
|
return '' |
|
|
|
|
|
} |
|
|
|
|
|
const number = Number(value) |
|
|
|
|
|
if (!Number.isFinite(number)) { |
|
|
|
|
|
return String(value) |
|
|
|
|
|
} |
|
|
|
|
|
return this.roundCost(number).toFixed(2) |
|
|
|
|
|
}, |
|
|
|
|
|
roundCost (value) { |
|
|
|
|
|
const number = Number(value) |
|
|
|
|
|
if (!Number.isFinite(number)) { |
|
|
|
|
|
return null |
|
|
|
|
|
} |
|
|
|
|
|
return Math.round((number + Number.EPSILON) * 100) / 100 |
|
|
|
|
|
}, |
|
|
|
|
|
toCostNumber (value) { |
|
|
|
|
|
if (value == null || String(value).trim() === '') { |
|
|
|
|
|
return null |
|
|
|
|
|
} |
|
|
|
|
|
const number = Number(value) |
|
|
|
|
|
return Number.isFinite(number) ? number : null |
|
|
|
|
|
}, |
|
|
|
|
|
getRowSampleQty (row) { |
|
|
|
|
|
if (!row) { |
|
|
|
|
|
return null |
|
|
|
|
|
} |
|
|
|
|
|
const qty = row.sampleQty != null && row.sampleQty !== '' ? row.sampleQty : row.proofingNumber |
|
|
|
|
|
return this.toCostNumber(qty) |
|
|
|
|
|
}, |
|
|
|
|
|
getCostRateNumber () { |
|
|
|
|
|
const rate = this.toCostNumber(this.usdCnyExchangeRate) |
|
|
|
|
|
return rate != null && rate > 0 ? rate : null |
|
|
|
|
|
}, |
|
|
|
|
|
getCostManualDisplay (row, columnProp) { |
|
|
|
|
|
if (!row) { |
|
|
|
|
|
return '' |
|
|
|
|
|
} |
|
|
|
|
|
if (columnProp === 'customizedForMasAls') { |
|
|
|
|
|
return this.isBlankValue(row.customizedForMasAls) ? '' : String(row.customizedForMasAls) |
|
|
|
|
|
} |
|
|
|
|
|
return this.formatCostAmount(row[columnProp]) |
|
|
|
|
|
}, |
|
|
|
|
|
normalizeCostDraft (columnProp, rawValue) { |
|
|
|
|
|
if (columnProp === 'customizedForMasAls') { |
|
|
|
|
|
const text = rawValue == null ? '' : String(rawValue).trim() |
|
|
|
|
|
if (!text) { |
|
|
|
|
|
return { value: null, error: '' } |
|
|
|
|
|
} |
|
|
|
|
|
if (text.length > 100) { |
|
|
|
|
|
return { value: null, error: 'Customized for MAS/ALS不能超过100个字符' } |
|
|
|
|
|
} |
|
|
|
|
|
return { value: text, error: '' } |
|
|
|
|
|
} |
|
|
|
|
|
const text = rawValue == null ? '' : String(rawValue).trim() |
|
|
|
|
|
if (!text) { |
|
|
|
|
|
return { value: null, error: '' } |
|
|
|
|
|
} |
|
|
|
|
|
if (!/^\d+(\.\d+)?$/.test(text)) { |
|
|
|
|
|
return { value: null, error: '请输入不小于0的数字' } |
|
|
|
|
|
} |
|
|
|
|
|
const number = Number(text) |
|
|
|
|
|
if (!Number.isFinite(number) || number >= 1000000000000) { |
|
|
|
|
|
return { value: null, error: '数值超出可保存范围' } |
|
|
|
|
|
} |
|
|
|
|
|
return { value: this.roundCost(number), error: '' } |
|
|
|
|
|
}, |
|
|
|
|
|
isSameCostDraft (columnProp, normalizedValue, originalDisplay) { |
|
|
|
|
|
if (columnProp === 'customizedForMasAls') { |
|
|
|
|
|
const left = normalizedValue == null ? '' : String(normalizedValue).trim() |
|
|
|
|
|
const right = originalDisplay == null ? '' : String(originalDisplay).trim() |
|
|
|
|
|
return left === right |
|
|
|
|
|
} |
|
|
|
|
|
return this.formatCostAmount(normalizedValue) === this.formatCostAmount(originalDisplay) |
|
|
|
|
|
}, |
|
|
|
|
|
sumPreviewCost (left, right) { |
|
|
|
|
|
if (left == null && right == null) { |
|
|
|
|
|
return null |
|
|
|
|
|
} |
|
|
|
|
|
return this.roundCost((left || 0) + (right || 0)) |
|
|
|
|
|
}, |
|
|
|
|
|
// 列表默认显示已保存结果。只有正在改的那个数字,才按当天汇率预览受影响的计算列。 |
|
|
|
|
|
getCostCalculatedValue (row, columnProp) { |
|
|
|
|
|
if (!row) { |
|
|
|
|
|
return null |
|
|
|
|
|
} |
|
|
|
|
|
if (!this.isCostEditingRow(row)) { |
|
|
|
|
|
return row[columnProp] |
|
|
|
|
|
} |
|
|
|
|
|
const editingProp = this.costEditingKey.slice(this.costEditingKey.indexOf(':') + 1) |
|
|
|
|
|
const preview = this.previewEditedCost(row, editingProp) |
|
|
|
|
|
if (preview && Object.prototype.hasOwnProperty.call(preview, columnProp)) { |
|
|
|
|
|
return preview[columnProp] |
|
|
|
|
|
} |
|
|
|
|
|
return row[columnProp] |
|
|
|
|
|
}, |
|
|
|
|
|
previewEditedCost (row, editingProp) { |
|
|
|
|
|
const normalized = this.normalizeCostDraft(editingProp, this.costEditDraft) |
|
|
|
|
|
if (normalized.error) { |
|
|
|
|
|
return null |
|
|
|
|
|
} |
|
|
|
|
|
const rate = this.getCostRateNumber() |
|
|
|
|
|
if (editingProp === 'tpKctUsd') { |
|
|
|
|
|
const qty = this.getRowSampleQty(row) |
|
|
|
|
|
const sampleCostUsd = normalized.value == null || qty == null |
|
|
|
|
|
? null |
|
|
|
|
|
: this.roundCost(normalized.value * qty / 1000) |
|
|
|
|
|
return { |
|
|
|
|
|
sampleCostUsd: sampleCostUsd, |
|
|
|
|
|
sampleAndToolingCostUsd: this.sumPreviewCost(sampleCostUsd, this.toCostNumber(row.toolingCostUsd)) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
if (editingProp === 'toolingCostCn') { |
|
|
|
|
|
const toolingCostUsd = normalized.value == null || rate == null |
|
|
|
|
|
? null |
|
|
|
|
|
: this.roundCost(normalized.value / rate) |
|
|
|
|
|
return { |
|
|
|
|
|
toolingCostUsd: toolingCostUsd, |
|
|
|
|
|
sampleAndToolingCostUsd: this.sumPreviewCost(this.toCostNumber(row.sampleCostUsd), toolingCostUsd) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
if (editingProp === 'sampleCostFromFnCn') { |
|
|
|
|
|
return { |
|
|
|
|
|
sampleCostFromFnUsd: normalized.value == null || rate == null |
|
|
|
|
|
? null |
|
|
|
|
|
: this.roundCost(normalized.value / rate) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
return null |
|
|
|
|
|
}, |
|
|
|
|
|
getCostCalculatedTitle (row, columnProp) { |
|
|
|
|
|
const rate = this.formatCostDisplay(this.usdCnyExchangeRate) |
|
|
|
|
|
const rateText = rate ? `汇率 ${rate}` : '未设置汇率,不能折算' |
|
|
|
|
|
if (columnProp === 'sampleCostUsd') { |
|
|
|
|
|
return '修改 TP 时按 TP(KCT/USD) × Sample Qty / 1000 计算' |
|
|
|
|
|
} |
|
|
|
|
|
if (columnProp === 'toolingCostUsd') { |
|
|
|
|
|
return `修改 Tooling cost/CN 时按人民币 / ${rateText}` |
|
|
|
|
|
} |
|
|
|
|
|
if (columnProp === 'sampleAndToolingCostUsd') { |
|
|
|
|
|
return 'Sample Cost/USD + Tooling Cost/USD。点“按汇率重算”会用当前汇率重算全部自动计算列' |
|
|
|
|
|
} |
|
|
|
|
|
if (columnProp === 'sampleCostFromFnUsd') { |
|
|
|
|
|
return `修改 Sample Cost from FN/CN 时按人民币 / ${rateText}` |
|
|
|
|
|
} |
|
|
|
|
|
return '' |
|
|
|
|
|
}, |
|
|
|
|
|
normalizeExchangeRateDraft (rawValue) { |
|
|
|
|
|
const text = rawValue == null ? '' : String(rawValue).trim() |
|
|
|
|
|
if (!text) { |
|
|
|
|
|
return { value: null, error: '' } |
|
|
|
|
|
} |
|
|
|
|
|
if (!/^\d+(\.\d{1,6})?$/.test(text)) { |
|
|
|
|
|
return { value: null, error: '汇率请输入大于0的数字,最多6位小数' } |
|
|
|
|
|
} |
|
|
|
|
|
const number = Number(text) |
|
|
|
|
|
if (!Number.isFinite(number) || number <= 0 || number >= 1000) { |
|
|
|
|
|
return { value: null, error: '汇率必须大于0且小于1000' } |
|
|
|
|
|
} |
|
|
|
|
|
return { value: Math.round((number + Number.EPSILON) * 1000000) / 1000000, error: '' } |
|
|
|
|
|
}, |
|
|
|
|
|
isSameExchangeRate (left, right) { |
|
|
|
|
|
if (left == null || right == null) { |
|
|
|
|
|
return left == null && right == null |
|
|
|
|
|
} |
|
|
|
|
|
return Math.abs(Number(left) - Number(right)) < 0.0000005 |
|
|
|
|
|
}, |
|
|
|
|
|
// 汇率写在 siteid=2。空值允许保存,但之后不能把人民币折成美元。 |
|
|
|
|
|
saveExchangeRate () { |
|
|
|
|
|
const normalized = this.normalizeExchangeRateDraft(this.usdCnyExchangeRateDraft) |
|
|
|
|
|
if (normalized.error) { |
|
|
|
|
|
this.$message.warning(normalized.error) |
|
|
|
|
|
return Promise.resolve(false) |
|
|
|
|
|
} |
|
|
|
|
|
if (this.isSameExchangeRate(normalized.value, this.toCostNumber(this.usdCnyExchangeRate))) { |
|
|
|
|
|
return Promise.resolve(true) |
|
|
|
|
|
} |
|
|
|
|
|
if (this._exchangeRateSavePromise) { |
|
|
|
|
|
return this._exchangeRateSavePromise |
|
|
|
|
|
} |
|
|
|
|
|
this.costRateSaving = true |
|
|
|
|
|
this._exchangeRateSavePromise = saveProofTrackingExchangeRate({ |
|
|
|
|
|
usdCnyRate: normalized.value, |
|
|
|
|
|
updateBy: this.$store.state.user.name |
|
|
|
|
|
}).then(({ data }) => { |
|
|
|
|
|
if (!data || data.code !== 0) { |
|
|
|
|
|
this.$message.error((data && data.msg) || '汇率保存失败') |
|
|
|
|
|
return false |
|
|
|
|
|
} |
|
|
|
|
|
this.usdCnyExchangeRate = data.usdCnyExchangeRate == null ? null : data.usdCnyExchangeRate |
|
|
|
|
|
this.usdCnyExchangeRateDraft = this.usdCnyExchangeRate == null ? '' : this.formatCostDisplay(this.usdCnyExchangeRate) |
|
|
|
|
|
return true |
|
|
|
|
|
}).catch(() => { |
|
|
|
|
|
this.$message.error('汇率保存失败') |
|
|
|
|
|
return false |
|
|
|
|
|
}).finally(() => { |
|
|
|
|
|
this.costRateSaving = false |
|
|
|
|
|
this._exchangeRateSavePromise = null |
|
|
|
|
|
}) |
|
|
|
|
|
return this._exchangeRateSavePromise |
|
|
|
|
|
}, |
|
|
|
|
|
recalculateCostByRate () { |
|
|
|
|
|
const normalized = this.normalizeExchangeRateDraft(this.usdCnyExchangeRateDraft) |
|
|
|
|
|
if (normalized.error) { |
|
|
|
|
|
this.$message.warning(normalized.error) |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
if (normalized.value == null) { |
|
|
|
|
|
this.$message.warning('未设置汇率,无法计算') |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
this.$confirm('将按当前汇率重算全部自动计算的费用列并保存,是否继续?', '提示', { |
|
|
|
|
|
confirmButtonText: '确定', |
|
|
|
|
|
cancelButtonText: '取消', |
|
|
|
|
|
type: 'warning' |
|
|
|
|
|
}).then(() => { |
|
|
|
|
|
this.costRateRecalcLoading = true |
|
|
|
|
|
return this.saveExchangeRate() |
|
|
|
|
|
}).then(saved => { |
|
|
|
|
|
if (saved !== true) { |
|
|
|
|
|
return null |
|
|
|
|
|
} |
|
|
|
|
|
return refreshProofTrackingCostByRate({ updateBy: this.$store.state.user.name }) |
|
|
|
|
|
}).then(response => { |
|
|
|
|
|
if (!response) { |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
const data = response.data |
|
|
|
|
|
if (data && data.code === 0) { |
|
|
|
|
|
this.$message.success(data.msg || '费用已按汇率重算') |
|
|
|
|
|
this.getDataList() |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
this.$message.error((data && data.msg) || '按汇率重算失败') |
|
|
|
|
|
}).catch(error => { |
|
|
|
|
|
if (error === 'cancel' || error === 'close') { |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
this.$message.error('按汇率重算失败') |
|
|
|
|
|
}).finally(() => { |
|
|
|
|
|
this.costRateRecalcLoading = false |
|
|
|
|
|
}) |
|
|
|
|
|
}, |
|
|
|
|
|
resolveCostEditor () { |
|
|
|
|
|
let editor = this.$refs.costEditor |
|
|
|
|
|
if (Array.isArray(editor)) { |
|
|
|
|
|
editor = editor.filter(item => item)[0] |
|
|
|
|
|
} |
|
|
|
|
|
return editor || null |
|
|
|
|
|
}, |
|
|
|
|
|
focusCostEditor (retried) { |
|
|
|
|
|
const editor = this.resolveCostEditor() |
|
|
|
|
|
if (!editor) { |
|
|
|
|
|
if (!retried) { |
|
|
|
|
|
this.$nextTick(() => { |
|
|
|
|
|
this.focusCostEditor(true) |
|
|
|
|
|
}) |
|
|
|
|
|
} |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
if (typeof editor.focus === 'function') { |
|
|
|
|
|
editor.focus() |
|
|
|
|
|
} |
|
|
|
|
|
if (typeof editor.toggleMenu === 'function' && !editor.visible) { |
|
|
|
|
|
editor.toggleMenu() |
|
|
|
|
|
} |
|
|
|
|
|
const input = editor.$refs && editor.$refs.input |
|
|
|
|
|
if (input && typeof input.select === 'function' && typeof editor.toggleMenu !== 'function') { |
|
|
|
|
|
input.select() |
|
|
|
|
|
} |
|
|
|
|
|
}, |
|
|
|
|
|
findCostEditingTarget () { |
|
|
|
|
|
if (!this.costEditingKey) { |
|
|
|
|
|
return null |
|
|
|
|
|
} |
|
|
|
|
|
const splitIndex = this.costEditingKey.indexOf(':') |
|
|
|
|
|
if (splitIndex < 0) { |
|
|
|
|
|
return null |
|
|
|
|
|
} |
|
|
|
|
|
const trackingId = this.costEditingKey.slice(0, splitIndex) |
|
|
|
|
|
const columnProp = this.costEditingKey.slice(splitIndex + 1) |
|
|
|
|
|
const row = (this.dataList || []).find(item => item && String(item.trackingId) === String(trackingId)) |
|
|
|
|
|
if (!row) { |
|
|
|
|
|
return null |
|
|
|
|
|
} |
|
|
|
|
|
return { row: row, columnProp: columnProp } |
|
|
|
|
|
}, |
|
|
|
|
|
exitCostEdit () { |
|
|
|
|
|
this.costEditingKey = '' |
|
|
|
|
|
this.costEditDraft = '' |
|
|
|
|
|
this.costEditOriginal = '' |
|
|
|
|
|
this.costSelectReady = false |
|
|
|
|
|
}, |
|
|
|
|
|
cancelCostEdit (row) { |
|
|
|
|
|
if (row && !this.isCostEditingRow(row)) { |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
this.exitCostEdit() |
|
|
|
|
|
}, |
|
|
|
|
|
startCostEdit (row, columnProp) { |
|
|
|
|
|
if (!row || !row.trackingId || !this.isCostManualColumn(columnProp)) { |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
const nextKey = `${row.trackingId}:${columnProp}` |
|
|
|
|
|
if (this.costEditingKey === nextKey) { |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
if (this.costEditingKey) { |
|
|
|
|
|
const editing = this.findCostEditingTarget() |
|
|
|
|
|
if (editing) { |
|
|
|
|
|
this.saveCostEdit(editing.row, editing.columnProp) |
|
|
|
|
|
} else { |
|
|
|
|
|
this.exitCostEdit() |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
this.costEditingKey = nextKey |
|
|
|
|
|
this.costEditOriginal = this.getCostManualDisplay(row, columnProp) |
|
|
|
|
|
this.costEditDraft = this.costEditOriginal |
|
|
|
|
|
this.costSelectReady = false |
|
|
|
|
|
this.$nextTick(() => { |
|
|
|
|
|
this.focusCostEditor() |
|
|
|
|
|
// 下拉刚挂上时会先关一次面板,这段时间不把关闭当成保存。 |
|
|
|
|
|
setTimeout(() => { |
|
|
|
|
|
if (this.costEditingKey === nextKey) { |
|
|
|
|
|
this.costSelectReady = true |
|
|
|
|
|
} |
|
|
|
|
|
}, 200) |
|
|
|
|
|
}) |
|
|
|
|
|
}, |
|
|
|
|
|
handleCostSelectVisible (visible, row, columnProp) { |
|
|
|
|
|
if (visible || !this.isCostEditing(row, columnProp) || !this.costSelectReady) { |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
const editor = this.resolveCostEditor() |
|
|
|
|
|
const typed = editor && editor.query != null ? String(editor.query).trim() : '' |
|
|
|
|
|
if (typed && typed !== String(this.costEditDraft || '').trim()) { |
|
|
|
|
|
this.costEditDraft = typed |
|
|
|
|
|
} |
|
|
|
|
|
this.saveCostEdit(row, columnProp) |
|
|
|
|
|
}, |
|
|
|
|
|
saveCostEdit (row, columnProp) { |
|
|
|
|
|
if (!this.isCostEditing(row, columnProp)) { |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
const normalized = this.normalizeCostDraft(columnProp, this.costEditDraft) |
|
|
|
|
|
if (normalized.error) { |
|
|
|
|
|
this.$message.warning(normalized.error) |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
if (this.isSameCostDraft(columnProp, normalized.value, this.costEditOriginal)) { |
|
|
|
|
|
this.exitCostEdit() |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
const version = (row._costSaveVersion || 0) + 1 |
|
|
|
|
|
this.$set(row, '_costSaveVersion', version) |
|
|
|
|
|
this.$set(row, columnProp, normalized.value) |
|
|
|
|
|
const payload = { |
|
|
|
|
|
trackingId: row.trackingId, |
|
|
|
|
|
customizedForMasAls: this.isBlankValue(row.customizedForMasAls) ? null : String(row.customizedForMasAls).trim(), |
|
|
|
|
|
tpKctUsd: this.toCostNumber(row.tpKctUsd), |
|
|
|
|
|
toolingCostCn: this.toCostNumber(row.toolingCostCn), |
|
|
|
|
|
sampleCostFromFnCn: this.toCostNumber(row.sampleCostFromFnCn), |
|
|
|
|
|
updateBy: this.$store.state.user.name |
|
|
|
|
|
} |
|
|
|
|
|
this.exitCostEdit() |
|
|
|
|
|
updateProofTrackingCost(payload).then(({ data }) => { |
|
|
|
|
|
const current = (this.dataList || []).find(item => item && item.trackingId === row.trackingId) |
|
|
|
|
|
if (!current || (current._costSaveVersion != null && current._costSaveVersion !== version)) { |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
if (data && data.code === 0) { |
|
|
|
|
|
this.applySavedCost(current, data.row || {}) |
|
|
|
|
|
if (data.msg && String(data.msg).indexOf('未设置汇率') > -1) { |
|
|
|
|
|
this.$message.warning(data.msg) |
|
|
|
|
|
} |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
this.$message.error((data && data.msg) || '费用保存失败') |
|
|
|
|
|
this.getDataList() |
|
|
|
|
|
}).catch(() => { |
|
|
|
|
|
const current = (this.dataList || []).find(item => item && item.trackingId === row.trackingId) |
|
|
|
|
|
if (!current || (current._costSaveVersion != null && current._costSaveVersion !== version)) { |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
this.$message.error('费用保存异常') |
|
|
|
|
|
this.getDataList() |
|
|
|
|
|
}) |
|
|
|
|
|
}, |
|
|
|
|
|
applySavedCost (row, saved) { |
|
|
|
|
|
const fields = [ |
|
|
|
|
|
'customizedForMasAls', |
|
|
|
|
|
'tpKctUsd', |
|
|
|
|
|
'toolingCostCn', |
|
|
|
|
|
'sampleCostFromFnCn', |
|
|
|
|
|
'sampleCostUsd', |
|
|
|
|
|
'toolingCostUsd', |
|
|
|
|
|
'sampleAndToolingCostUsd', |
|
|
|
|
|
'sampleCostFromFnUsd' |
|
|
|
|
|
] |
|
|
|
|
|
fields.forEach(field => { |
|
|
|
|
|
if (saved && Object.prototype.hasOwnProperty.call(saved, field)) { |
|
|
|
|
|
this.$set(row, field, saved[field]) |
|
|
|
|
|
} |
|
|
|
|
|
}) |
|
|
|
|
|
}, |
|
|
handleTrackingTableSortChange (sortData) { |
|
|
handleTrackingTableSortChange (sortData) { |
|
|
this.trackingTableSortProp = sortData && sortData.prop ? String(sortData.prop) : '' |
|
|
this.trackingTableSortProp = sortData && sortData.prop ? String(sortData.prop) : '' |
|
|
this.trackingTableSortOrder = sortData && sortData.order ? String(sortData.order) : '' |
|
|
this.trackingTableSortOrder = sortData && sortData.order ? String(sortData.order) : '' |
|
|
@ -5727,8 +6360,7 @@ export default { |
|
|
baseline: current.baseline || '', |
|
|
baseline: current.baseline || '', |
|
|
pmInqueryTime: this.formatDate(current.pmInqueryTime), |
|
|
pmInqueryTime: this.formatDate(current.pmInqueryTime), |
|
|
importance: this.normalizeImportanceValue(current.importance), |
|
|
importance: this.normalizeImportanceValue(current.importance), |
|
|
needDate: project.needDate || part.needDate || current.needDate || '', |
|
|
|
|
|
remark: part.remark || project.remark || current.remark || '' |
|
|
|
|
|
|
|
|
needDate: project.needDate || part.needDate || current.needDate || '' |
|
|
}) |
|
|
}) |
|
|
form.projectManagerName = this.getRoleDisplayName(form.projectManager) |
|
|
form.projectManagerName = this.getRoleDisplayName(form.projectManager) |
|
|
form.projectOwnerName = this.getRoleDisplayName(form.projectOwner) |
|
|
form.projectOwnerName = this.getRoleDisplayName(form.projectOwner) |
|
|
@ -5855,9 +6487,9 @@ export default { |
|
|
: '' |
|
|
: '' |
|
|
const nextStatus = inData.proofingStatus ? String(inData.proofingStatus).trim() : '' |
|
|
const nextStatus = inData.proofingStatus ? String(inData.proofingStatus).trim() : '' |
|
|
const proofingStatusChanged = this.oneKeyDialogMode !== 'create' && nextStatus !== previousStatus |
|
|
const proofingStatusChanged = this.oneKeyDialogMode !== 'create' && nextStatus !== previousStatus |
|
|
if (proofingStatusChanged && this.proofingStatusChangeOptions.indexOf(nextStatus) === -1) { |
|
|
|
|
|
|
|
|
if (proofingStatusChanged && !this.isAllowedOneKeyProofingStatusChange(previousStatus, nextStatus)) { |
|
|
this.saveOneKeyLoading = false |
|
|
this.saveOneKeyLoading = false |
|
|
this.$message.warning('打样状态只能更改为终止、取消、报废') |
|
|
|
|
|
|
|
|
this.$message.warning('打样状态只能更改为终止、取消、报废;当前为终止、取消、报废时可以改回进行中') |
|
|
return |
|
|
return |
|
|
} |
|
|
} |
|
|
if (proofingStatusChanged) { |
|
|
if (proofingStatusChanged) { |
|
|
@ -6483,7 +7115,23 @@ export default { |
|
|
return '#046e97' |
|
|
return '#046e97' |
|
|
}, |
|
|
}, |
|
|
isProofingClosedStatus (row) { |
|
|
isProofingClosedStatus (row) { |
|
|
return this.proofingStatusChangeOptions.indexOf(this.getNormalizedProofingStatus(row)) > -1 |
|
|
|
|
|
|
|
|
return this.isClosedProofingStatusValue(this.getNormalizedProofingStatus(row)) |
|
|
|
|
|
}, |
|
|
|
|
|
isClosedProofingStatusValue (status) { |
|
|
|
|
|
const normalizedStatus = status ? String(status).trim() : '' |
|
|
|
|
|
return this.proofingStatusChangeOptions.indexOf(normalizedStatus) > -1 |
|
|
|
|
|
}, |
|
|
|
|
|
isAllowedOneKeyProofingStatusChange (previousStatus, nextStatus) { |
|
|
|
|
|
const previous = previousStatus ? String(previousStatus).trim() : '' |
|
|
|
|
|
const next = nextStatus ? String(nextStatus).trim() : '' |
|
|
|
|
|
if (!next || next === previous) { |
|
|
|
|
|
return true |
|
|
|
|
|
} |
|
|
|
|
|
if (this.proofingStatusChangeOptions.indexOf(next) > -1) { |
|
|
|
|
|
return true |
|
|
|
|
|
} |
|
|
|
|
|
// 重新打开只允许从终止/取消/报废回到进行中,避免草稿等状态被改成进行中。 |
|
|
|
|
|
return next === '进行中' && this.isClosedProofingStatusValue(previous) |
|
|
}, |
|
|
}, |
|
|
canDeleteProofStatus (row) { |
|
|
canDeleteProofStatus (row) { |
|
|
return this.deletableProofingStatuses.indexOf(this.getNormalizedProofingStatus(row)) > -1 |
|
|
return this.deletableProofingStatuses.indexOf(this.getNormalizedProofingStatus(row)) > -1 |
|
|
@ -7630,6 +8278,50 @@ export default { |
|
|
min-width: 28px; |
|
|
min-width: 28px; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.cost-rate-tip { |
|
|
|
|
|
display: inline-flex; |
|
|
|
|
|
align-items: center; |
|
|
|
|
|
margin-left: 10px; |
|
|
|
|
|
color: #606266; |
|
|
|
|
|
font-size: 12px; |
|
|
|
|
|
line-height: 18px; |
|
|
|
|
|
white-space: nowrap; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.cost-rate-input { |
|
|
|
|
|
width: 120px; |
|
|
|
|
|
margin-left: 6px; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.cost-cell { |
|
|
|
|
|
min-height: 24px; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.cost-display--editable { |
|
|
|
|
|
display: inline-block; |
|
|
|
|
|
width: 100%; |
|
|
|
|
|
min-height: 24px; |
|
|
|
|
|
line-height: 24px; |
|
|
|
|
|
padding: 0 4px; |
|
|
|
|
|
border: 1px solid transparent; |
|
|
|
|
|
border-radius: 4px; |
|
|
|
|
|
cursor: pointer; |
|
|
|
|
|
box-sizing: border-box; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.cost-display--editable:hover { |
|
|
|
|
|
border-color: #dcdfe6; |
|
|
|
|
|
background: #fff; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.el-table.proof-tracking-table .cost-editor { |
|
|
|
|
|
width: 100%; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.cost-calculated-text { |
|
|
|
|
|
color: #606266; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/* Comments 两行共 28px,与原单元格内容高度一致,不撑高整行 */ |
|
|
/* Comments 两行共 28px,与原单元格内容高度一致,不撑高整行 */ |
|
|
.el-table.proof-tracking-table .comments-text { |
|
|
.el-table.proof-tracking-table .comments-text { |
|
|
display: -webkit-box; |
|
|
display: -webkit-box; |
|
|
|