|
|
<template> <div class="mod-config"> <el-form :inline="true" label-position="top" :model="searchData"> <el-form-item label="序列号"> <el-input v-model="searchData.referenceNo" clearable style="width: 140px"></el-input> </el-form-item> <el-form-item label="单据状态"> <el-select v-model="searchData.status" clearable style="width: 120px"> <el-option label="草稿" value="草稿"></el-option> <el-option label="审批中" value="审批中"></el-option> <el-option label="已完成" value="已完成"></el-option> </el-select> </el-form-item> <el-form-item label="节点审批人"> <el-input v-model="searchData.currentApprover" clearable style="width: 120px"></el-input> </el-form-item> <el-form-item label="当前节点"> <el-select v-model="searchData.nodeId" placeholder="请选择节点" clearable style="width: 140px"> <el-option v-for="option in nodeOptions" :key="option.id" :label="option.name" :value="option.id"> </el-option> </el-select> </el-form-item> <el-form-item :label="' '"> <el-button v-if="authSearch" @click="getDataList">查询</el-button> <el-button v-if="authUpdate" @click="addOrUpdateHandle()">新增</el-button> <el-button v-if="authDelete" type="danger" @click="deleteHandle()">删除</el-button> <download-excel v-if="authSearch" :fields="exportFieldMap" :data="exportData" type="xls" :name="exportName" :header="exportHeader" :footer="exportFooter" :fetch="createExportData" :before-generate="startDownload" :before-finish="finishDownload" worksheet="导出信息" :class="['el-button', 'el-button--primary', 'el-button--medium', {'is-loading': exportLoading}]"> <i v-if="exportLoading" class="el-icon-loading"></i> <span>导出</span> </download-excel> <el-button v-if="authSearch" @click="searchHandle()">搜索</el-button> </el-form-item> </el-form>
<el-table ref="labTable" :height="height" :data="dataList" border :row-style="rowStyle" @row-click="changeClickRow" @current-change="currentChange" @selection-change="dataListSelectionChange" v-loading="dataListLoading" style="width: 100%;"> <el-table-column type="selection" header-align="center" align="center" width="50"></el-table-column> <el-table-column prop="referenceNo" header-align="center" align="center" label="序列号" width="180"></el-table-column> <el-table-column prop="status" header-align="center" align="center" label="单据状态" width="110"></el-table-column> <el-table-column prop="nodeName" header-align="center" align="center" label="当前节点" width="140"></el-table-column> <el-table-column prop="currentApprover" header-align="center" align="center" label="当前审批人" width="150"></el-table-column> <el-table-column prop="applicant" header-align="center" align="center" label="申请人编码" width="120"></el-table-column> <el-table-column prop="applicantName" header-align="center" align="center" label="申请人名称" width="140"></el-table-column> <el-table-column prop="applicationDate" header-align="center" align="center" label="申请日期" width="120"> <template slot-scope="scope"> <span>{{ normalizeDateOnly(scope.row.applicationDate) }}</span> </template> </el-table-column> <el-table-column prop="applyDepartment" header-align="center" align="center" label="申请部门" width="150"></el-table-column> <el-table-column prop="requestedDate" header-align="center" align="center" label="需求日期" width="120"> <template slot-scope="scope"> <span>{{ normalizeDateOnly(scope.row.requestedDate) }}</span> </template> </el-table-column> <el-table-column prop="customerId" header-align="center" align="center" label="客户编码" width="120"></el-table-column> <el-table-column prop="customerName" header-align="center" align="center" label="客户名称" width="160"></el-table-column> <el-table-column prop="projectId" header-align="center" align="center" label="项目编码" width="130"></el-table-column> <el-table-column prop="projectName" header-align="center" align="center" label="项目名称" width="170"></el-table-column> <el-table-column prop="sampleName" header-align="center" align="center" label="样品名称" width="150"></el-table-column> <el-table-column prop="sampleModel" header-align="center" align="center" label="样品型号" width="150"></el-table-column> <el-table-column prop="sampleQty" header-align="center" align="center" label="样品数量" width="100"></el-table-column> <el-table-column prop="productStage" header-align="center" align="center" label="产品阶段" width="120"></el-table-column> <el-table-column prop="testType" header-align="center" align="center" label="测试类型" width="120"></el-table-column> <el-table-column prop="reportDocument" header-align="center" align="center" label="报告出具" width="120"></el-table-column> <el-table-column prop="returnSample" header-align="center" align="center" label="样品退回" width="100"> <template slot-scope="scope"> <span>{{ displayYesNo(scope.row.returnSample) }}</span> </template> </el-table-column> <el-table-column prop="testLab" header-align="center" align="center" label="测试实验室" width="140"></el-table-column> <el-table-column prop="testStartDate" header-align="center" align="center" label="测试开始时间" width="120"> <template slot-scope="scope"> <span>{{ normalizeDateOnly(scope.row.testStartDate) }}</span> </template> </el-table-column> <el-table-column prop="completedDate" header-align="center" align="center" label="测试完成日期" width="120"> <template slot-scope="scope"> <span>{{ normalizeDateOnly(scope.row.completedDate) }}</span> </template> </el-table-column> <el-table-column prop="testNumber" header-align="center" align="center" label="测试编码" width="140"></el-table-column> <el-table-column prop="testerName" header-align="center" align="center" label="测试人" width="180" :show-overflow-tooltip="true"> <template slot-scope="scope"> <span>{{ scope.row.testerName || scope.row.tester || '' }}</span> </template> </el-table-column> <el-table-column fixed="right" header-align="center" align="center" width="130" label="操作"> <template slot-scope="scope"> <el-link v-if="authUpdate && scope.row.status !== '已完成'" style="cursor: pointer" @click="addOrUpdateHandle(scope.row)">编辑</el-link> <el-link v-if="authUpdate && scope.row.status === '已完成'" style="cursor: pointer" @click="addOrUpdateHandle(scope.row)">详情</el-link> <el-link v-if="authIssue && scope.row.status === '草稿'" style="cursor: pointer; margin-left: 10px;" @click="issueModal(scope.row)">下达</el-link> </template> </el-table-column> </el-table>
<el-pagination style="margin-top: 0px" @size-change="sizeChangeHandle" @current-change="currentChangeHandle" :current-page="pageIndex" :page-sizes="[20, 50, 100, 200, 500]" :page-size="pageSize" :total="totalPage" layout="total, sizes, prev, pager, next, jumper"> </el-pagination>
<el-dialog :title="modalTitle" :visible.sync="modalFlag" width="965px" top="5vh" v-drag :close-on-click-modal="false" :showClose="false">
<el-tabs tab-position="left" type="border-card" v-model="activeName" style="width: 100%;height: 730px;"> <el-tab-pane label="基本信息" name="basicInfo"> <div style="height: 715px; overflow-y: auto;"> <el-form :inline="true" label-position="top" :model="modalData" style="margin-top: -5px;"> <el-form-item> <span style="cursor: pointer" v-if="!isLabFieldDisabled('applicant')" slot="label" @click="getBaseList(103, 1)"><a herf="#">申请人/Application</a></span> <span v-else slot="label">申请人/Application</span> <el-input v-model="modalData.applicant" @blur="applicantBlur(103)" :disabled="isLabFieldDisabled('applicant')" style="width: 100px"></el-input> <el-input v-model="modalData.applicantName" disabled style="width: 155px"></el-input> </el-form-item> <el-form-item label="申请日期/Apply Date"> <el-date-picker v-model="modalData.applicationDate" type="date" value-format="yyyy-MM-dd" :disabled="isLabFieldDisabled('applicationDate')" style="width: 110px" :editable="false"></el-date-picker> </el-form-item> <el-form-item label="申请工厂/Apply Site"> <el-select v-model="modalData.site" :disabled="isEditMode || showModalFlag" style="width: 135px" @change="handleModalSiteChange"> <el-option v-for="item in siteOptions" :key="item.siteID" :label="item.siteID + '-' + item.siteName" :value="item.siteID"> </el-option> </el-select> </el-form-item> <el-form-item label="申请部门/Apply Department"> <el-input v-model="modalData.applyDepartment" :disabled="isLabFieldDisabled('applyDepartment')" style="width: 225px"></el-input> </el-form-item> </el-form>
<el-form :inline="true" label-position="top" :model="modalData"> <el-form-item> <span slot="label" v-if="!modalData.customerIdFlag && !isLabFieldDisabled('customerId')" @click="getBaseList(102, 1)"><a herf="#">客户/Customer</a></span> <span slot="label" v-else>客户/Customer</span> <el-input :disabled="modalData.customerIdFlag || isLabFieldDisabled('customerId')" readonly v-model="modalData.customerId" @blur="handleQueryCustomer" style="width: 100px"></el-input> <el-input disabled v-model="modalData.customerName" style="width: 155px"></el-input> </el-form-item> <el-form-item> <span slot="label" v-if="!modalData.projectIdFlag && !isLabFieldDisabled('projectId')" @click="chooseProjectListFlag = true"><a herf="#">项目/Project</a></span> <span slot="label" v-else>项目/Project</span> <el-input :disabled="modalData.projectIdFlag || isLabFieldDisabled('projectId')" readonly v-model="modalData.projectId" @blur="handleQueryProjectByCustomer" style="width: 100px"></el-input> <el-input disabled v-model="modalData.projectName" style="width: 155px"></el-input> </el-form-item> <el-form-item label="需求日期/Requested Date"> <el-date-picker v-model="modalData.requestedDate" type="date" value-format="yyyy-MM-dd" :disabled="isLabFieldDisabled('requestedDate')" style="width: 225px" :editable="false"></el-date-picker> </el-form-item> </el-form>
<el-form :inline="true" label-position="top" :model="modalData"> <el-form-item label="样品名称/Sample Name"> <el-input v-model="modalData.sampleName" :disabled="isLabFieldDisabled('sampleName')" style="width: 260px"></el-input> </el-form-item> <el-form-item label="样品型号/Sample Model"> <el-input v-model="modalData.sampleModel" :disabled="isLabFieldDisabled('sampleModel')" style="width: 259px"></el-input> </el-form-item> <el-form-item label="样品数量/Sample QTY"> <el-input v-model="modalData.sampleQty" :disabled="isLabFieldDisabled('sampleQty')" style="width: 225px"></el-input> </el-form-item> </el-form>
<el-form :inline="true" label-position="top" :model="modalData"> <el-form-item label="测试目的/Test Purpose"> <el-input v-model="modalData.testPurpose" :disabled="isLabFieldDisabled('testPurpose')" style="width: 260px"></el-input> </el-form-item> <el-form-item label="产品阶段/Product Stage"> <dict-data-select v-model="modalData.productStage" clearable :disabled="isLabFieldDisabled('productStage')" style="width: 259px" dict-type="lab_product_stage"></dict-data-select> </el-form-item> <el-form-item label="测试类型/Test Type"> <el-radio-group v-model="modalData.testType" :disabled="isLabFieldDisabled('testType')" style="width: 225px"> <el-radio label="内部验证" @click.native.prevent="radioClick('testType', '内部验证')">内部验证</el-radio> <el-radio label="客户要求" @click.native.prevent="radioClick('testType', '客户要求')">客户要求</el-radio> </el-radio-group> </el-form-item> </el-form>
<el-form :inline="true" label-position="top" :model="modalData" style="margin-left: 2px"> <el-form-item label="报告出具/Report Document"> <el-radio-group v-model="modalData.reportDocument" :disabled="isLabFieldDisabled('reportDocument')" style="width: 260px"> <el-radio label="内部报告" @click.native.prevent="radioClick('reportDocument', '内部报告')">内部报告</el-radio> <el-radio label="客户报告" @click.native.prevent="radioClick('reportDocument', '客户报告')">客户报告</el-radio> </el-radio-group> </el-form-item> <el-form-item label="样品退回/Return Sample"> <el-radio-group v-model="modalData.returnSample" :disabled="isLabFieldDisabled('returnSample')" style="width: 259px"> <el-radio label="Y" @click.native.prevent="radioClick('returnSample', 'Y')">是</el-radio> <el-radio label="N" @click.native.prevent="radioClick('returnSample', 'N')">否</el-radio> </el-radio-group> </el-form-item> </el-form>
<el-form :inline="true" label-position="top" :model="modalData"> <el-form-item label="Application Surface"> <el-input v-model="modalData.applicationSurface" :disabled="isLabFieldDisabled('applicationSurface')" style="width: 533px"></el-input> </el-form-item> <el-form-item label="Test Lab"> <dict-data-select v-model="modalData.testLab" clearable :disabled="isLabFieldDisabled('testLab')" style="width: 225px" dict-type="lab_test_lab" @change="handleTestLabChange"></dict-data-select> </el-form-item> </el-form>
<el-form :inline="true" label-position="top" :model="modalData"> <el-form-item> <span style="cursor: pointer" v-if="!isLabFieldDisabled('labApprover')" slot="label" @click="openLabApproverChooseModal"><a herf="#">实验室审批人</a></span> <span v-else slot="label">实验室审批人</span> <el-input v-model="modalData.labApproverName" readonly clearable :disabled="isLabFieldDisabled('labApprover')" style="width: 772px" @focus="openLabApproverChooseModal"> <span slot="suffix" v-show="modalData.labApproverName && !isLabFieldDisabled('labApprover')" @click.stop="clearLabApproverSelection"> <i class="el-icon-circle-close"></i> </span> </el-input> </el-form-item> </el-form>
<el-form :inline="true" label-position="top" style="margin-top: -15px"> <el-form-item label=" "> <el-button type="primary" :disabled="showModalFlag" @click="openPropertyChooseModal">测试项目及条件/Test Items & Conditions</el-button> </el-form-item> </el-form>
<div class="rq" style="width: 772px;"> <el-table :data="modalData.propertyItemList" border :height="260" style="width: 100%;"> <el-table-column prop="itemNo" header-align="center" align="center" label="属性编码" width="100"></el-table-column> <el-table-column prop="itemDesc" header-align="center" align="left" label="属性名称" min-width="150"></el-table-column> <el-table-column header-align="center" align="center" label="属性值" min-width="250"> <template slot-scope="scope"> <el-select v-if="scope.row.valueChooseFlag === 'Y'" v-model="scope.row.itemValue" :disabled="showModalFlag" clearable filterable style="width: 100%;"> <el-option v-for="(option, index) in (scope.row.availableValueList || [])" :key="scope.row.itemNo + '-' + index + '-' + option.availableValue" :label="option.availableValue" :value="option.availableValue"> </el-option> </el-select> <el-input v-else v-model="scope.row.itemValue" :disabled="showModalFlag" clearable></el-input> </template> </el-table-column> </el-table> </div>
<el-form :inline="true" label-position="top" :model="modalData" style="margin-top: 0px"> <el-form-item style="display: block;"> <template slot="label"> <span class="judge-criteria-label" @click="openTestSpecDialog">测试规范/Test spec</span> </template> <div class="judge-criteria-box"> <template v-if="testSpecFileList.length > 0"> <el-link v-for="item in testSpecFileList" :key="item.id" type="primary" style="margin-right: 10px" @click.stop="previewJudgeCriteriaFile(item)"> {{ item.fileName }} </el-link> </template> <span v-else class="judge-criteria-placeholder">点击“测试规范”上传附件</span> </div> </el-form-item> </el-form>
<el-form :inline="true" label-position="top" :model="modalData" style="margin-top: 15px"> <el-form-item style="display: block;"> <template slot="label"> <span class="judge-criteria-label" @click="openJudgeCriteriaDialog">判断标准/Judge Criteria</span> </template> <div class="judge-criteria-box"> <template v-if="judgeCriteriaFileList.length > 0"> <el-link v-for="item in judgeCriteriaFileList" :key="item.id" type="primary" style="margin-right: 10px" @click.stop="previewJudgeCriteriaFile(item)"> {{ item.fileName }} </el-link> </template> <span v-else class="judge-criteria-placeholder">点击“判断标准”上传附件</span> </div> </el-form-item> </el-form> <el-form :inline="true" label-position="top" :model="modalData" style="margin-top: 15px"> <el-form-item label="注意事项/Attention" style="display: block;"> <el-input type="textarea" :rows="3" v-model="modalData.attention" :disabled="isLabFieldDisabled('attention')" resize="none" style="width: 772px"></el-input> </el-form-item> </el-form> </div> </el-tab-pane>
<el-tab-pane label="审批信息" name="approvalInfo"> <div style="height: 715px; overflow-y: auto;"> <el-form :inline="true" label-position="top" :model="modalData" style="margin-top: -5px;"> <el-form-item label="备注(部门经理)/ Comments(Department Manager)" style="display: block;"> <el-input type="textarea" :rows="3" v-model="modalData.departmentManagerComments" :disabled="isLabFieldDisabled('departmentManagerComments')" resize="none" style="width: 772px"></el-input> </el-form-item> </el-form> <el-form :inline="true" label-position="top" :model="modalData" style="margin-top: 45px;"> <el-form-item label="备注(实验室)/ Comments(Lab)" style="display: block;"> <el-input type="textarea" :rows="3" v-model="modalData.labComments" :disabled="isLabFieldDisabled('labComments')" resize="none" style="width: 772px"></el-input> </el-form-item> </el-form> <el-form :inline="true" label-position="top" :model="modalData" style="margin-top: 45px"> <el-form-item> <span style="cursor: pointer" v-if="!isLabFieldDisabled('tester')" slot="label" @click="openTesterChooseModal"><a herf="#">测试人/Tester</a></span> <span v-else slot="label">测试人/Tester</span> <el-input v-model="modalData.testerName" readonly :disabled="isLabFieldDisabled('tester')" style="width: 772px" placeholder="请选择测试人" @focus="openTesterChooseModal"> <span slot="suffix" v-show="modalData.testerName && !isLabFieldDisabled('tester')" @click.stop="clearTesterSelection"> <i class="el-icon-circle-close" style="margin-left: 5px;cursor: pointer;"></i> </span> </el-input> </el-form-item> </el-form> </div> </el-tab-pane>
<el-tab-pane label="测试结果" name="resultInfo"> <div style="height: 715px; overflow-y: auto;"> <el-form :inline="true" label-position="top" :model="modalData" style="margin-top: -5px;"> <el-form-item label="测试开始时间/Test Start Date"> <el-date-picker v-model="modalData.testStartDate" type="date" value-format="yyyy-MM-dd" :disabled="isLabFieldDisabled('testStartDate')" style="width: 170px" :editable="false"></el-date-picker> </el-form-item> <el-form-item label="测试完成日期/Completed Date"> <el-date-picker v-model="modalData.completedDate" type="date" value-format="yyyy-MM-dd" :disabled="isLabFieldDisabled('completedDate')" style="width: 170px" :editable="false"></el-date-picker> </el-form-item> <el-form-item label="测试编码/Test Number"> <el-input v-model="modalData.testNumber" :disabled="isLabFieldDisabled('testNumber')" style="width: 250px"></el-input> </el-form-item> </el-form> <el-form :inline="true" label-position="top" :model="modalData"> <el-form-item label="异常情况及说明/Unnormal symptom and description" style="display: block;"> <el-input type="textarea" :rows="3" v-model="modalData.unnormalSymptomAndDescription" :disabled="isLabFieldDisabled('unnormalSymptomAndDescription')" resize="none" style="width: 772px"></el-input> </el-form-item> </el-form> <el-form :inline="true" label-position="top" :model="modalData" style="margin-top: 45px"> <el-form-item style="display: block;"> <template slot="label"> <span class="judge-criteria-label" @click="openTestReportDialog">测试报告/Test Report</span> </template> <div class="judge-criteria-box"> <template v-if="testReportFileList.length > 0"> <el-link v-for="item in testReportFileList" :key="item.id" type="primary" style="margin-right: 10px" @click.stop="previewTestReportFile(item)"> {{ item.fileName }} </el-link> </template> <span v-else class="judge-criteria-placeholder">点击“测试报告”上传附件</span> </div> </el-form-item> </el-form> <el-form :inline="true" label-position="top" :model="modalData" style="margin-top: 20px"> <el-form-item label="备注/Comments" style="display: block;"> <el-input type="textarea" :rows="3" v-model="modalData.testerComments" :disabled="isLabFieldDisabled('testerComments')" resize="none" style="width: 772px"></el-input> </el-form-item> </el-form> </div> </el-tab-pane> </el-tabs>
<el-footer style="height:35px;margin-top: 15px;text-align:center"> <el-button type="primary" v-if="canSaveAction()" @click="dataFormSubmit()">保存</el-button> <el-button type="primary" @click="handleModalClose">关闭</el-button> <el-button type="primary" v-if="canAgreeAction()" :loading="submitLoading" @click="agreeSubmit">同意</el-button> <el-button type="primary" v-if="canRejectAction()" :loading="submitLoading" @click="openRejectModal">驳回</el-button> </el-footer> </el-dialog>
<el-dialog width="420px" title="驳回意见" :close-on-click-modal="false" :visible.sync="submitModalFlag" v-drag> <el-form :inline="true" label-position="top" style="margin-top: -15px;"> <el-form-item label="意见"> <el-input type="textarea" :rows="4" v-model="rejectOpinion" style="width: 380px"></el-input> </el-form-item> </el-form> <div slot="footer" class="dialog-footer"> <el-button @click="submitModalFlag = false">取消</el-button> <el-button type="primary" :loading="submitLoading" @click="rejectSubmit">确定</el-button> </div> </el-dialog>
<el-dialog title="属性清单" :close-on-click-modal="false" v-drag :visible.sync="propertyChooseModalFlag" width="820px"> <div class="rq"> <el-form :inline="true" label-position="top" :model="propertyChooseData"> <el-form-item label="模板"> <el-select v-model="propertyChooseData.codeNo" placeholder="请选择模板" style="width: 180px"> <el-option v-for="item in propertyModelList" :key="item.codeNo" :label="item.codeDesc" :value="item.codeNo"> </el-option> </el-select> </el-form-item> <el-form-item label="属性编码"> <el-input v-model="propertyChooseData.itemNo" clearable style="width: 140px"></el-input> </el-form-item> <el-form-item label="属性名称"> <el-input v-model="propertyChooseData.itemDesc" clearable style="width: 140px"></el-input> </el-form-item> <el-form-item :label="' '"> <el-button type="primary" @click="searchPropertyItemList()">查询</el-button> </el-form-item> </el-form> <el-table :height="320" :data="propertyItemList" ref="propertyItemTable" @row-click="propertyItemClickRow" @selection-change="selectionPropertyItem" border style="width: 100%;"> <el-table-column type="selection" header-align="center" align="center" width="50"> </el-table-column> <el-table-column prop="itemNo" header-align="center" align="center" label="属性编码" width="180"></el-table-column> <el-table-column prop="itemDesc" header-align="center" align="left" label="属性名称" min-width="300"></el-table-column> <el-table-column prop="defaultValue" header-align="center" align="left" label="参照值" min-width="180"></el-table-column> </el-table> </div> <el-footer style="height:40px;margin-top: 20px;text-align:center"> <el-button type="primary" @click="confirmPropertyItem">确认</el-button> <el-button type="primary" @click="propertyChooseModalFlag = false">关闭</el-button> </el-footer> </el-dialog>
<el-dialog title="判断标准附件" :close-on-click-modal="false" :visible.sync="judgeCriteriaDialogVisible" width="900px" v-drag @close="handleJudgeCriteriaDialogClose"> <oss-components ref="judgeCriteriaOss" :save-visible="authFileSave" :download-visible="authFileDownLoad" :remove-visible="authFileRemove" :preview-visible="authFilePreview" :disabled="showModalFlag || modalData.status === '已完成'" :row-click-select="true" label="序列号" :height="460" style="margin-top: 2px" :columns="judgeCriteriaFileColumnList" :order-ref1="modalData.site || ''" :order-ref2="modalData.referenceNo || ''" order-ref3="judgeCriteria"> </oss-components> </el-dialog>
<el-dialog title="测试规范附件" :close-on-click-modal="false" :visible.sync="testSpecDialogVisible" width="900px" v-drag @close="handleTestSpecDialogClose"> <oss-components ref="testSpecOss" :save-visible="authFileSave" :download-visible="authFileDownLoad" :remove-visible="authFileRemove" :preview-visible="authFilePreview" :disabled="showModalFlag || modalData.status === '已完成'" :row-click-select="true" label="序列号" :height="460" style="margin-top: 2px" :columns="judgeCriteriaFileColumnList" :order-ref1="modalData.site || ''" :order-ref2="modalData.referenceNo || ''" order-ref3="testSpec"> </oss-components> </el-dialog>
<el-dialog title="测试报告附件" :close-on-click-modal="false" :visible.sync="testReportDialogVisible" width="900px" v-drag @close="handleTestReportDialogClose"> <oss-components ref="testReportOss" :save-visible="authFileSave" :download-visible="authFileDownLoad" :remove-visible="authFileRemove" :preview-visible="authFilePreview" :disabled="showModalFlag || modalData.status === '已完成'" :row-click-select="true" label="序列号" :height="460" style="margin-top: 2px" :columns="judgeCriteriaFileColumnList" :order-ref1="modalData.site || ''" :order-ref2="modalData.referenceNo || ''" order-ref3="testReport"> </oss-components> </el-dialog>
<el-dialog title="人员选择" @open="openTesterDialog" @close="closeTesterDialog" v-drag :visible.sync="testerFlag" width="40vw" :close-on-click-modal="false"> <el-form :inline="true" label-position="top" :model="testerSearchData"> <el-form-item label="编码"> <el-input v-model="testerSearchData.operatorId" clearable style="width: 120px"></el-input> </el-form-item> <el-form-item label="名称"> <el-input v-model="testerSearchData.operatorName" clearable style="width: 120px"></el-input> </el-form-item> <el-form-item label=" "> <el-button type="primary" @click="filterTesterOptions">查询</el-button> </el-form-item> </el-form> <el-table v-if="testerFlag" :height="300" :data="testerDisplayList" @selection-change="handleTesterSelectionChange" @row-click="(row,column,event) => handleTesterTableClick(row,column,event,'testerTable')" ref="testerTable" border row-key="operatorId" style="width: 100%;"> <el-table-column type="selection" header-align="center" align="center" :reserve-selection="true" width="50"> </el-table-column> <el-table-column label="编码" property="operatorId" align="left" header-align="center"/> <el-table-column label="名称" property="operatorName" align="left" header-align="center"/> </el-table> <el-footer style="height:40px;margin-top: 20px;text-align:center"> <el-button type="primary" @click="saveTesterChooseModal">确定</el-button> <el-button type="primary" @click="testerFlag = false">关闭</el-button> </el-footer> </el-dialog>
<el-dialog title="实验室审批人选择" @open="openLabApproverDialog" @close="closeLabApproverDialog" v-drag :visible.sync="labApproverFlag" width="40vw" :close-on-click-modal="false"> <el-form :inline="true" label-position="top" :model="labApproverSearchData"> <el-form-item label="编码"> <el-input v-model="labApproverSearchData.operatorId" clearable style="width: 120px"></el-input> </el-form-item> <el-form-item label="名称"> <el-input v-model="labApproverSearchData.operatorName" clearable style="width: 120px"></el-input> </el-form-item> <el-form-item label=" "> <el-button type="primary" @click="filterLabApproverOptions">查询</el-button> </el-form-item> </el-form> <el-table v-if="labApproverFlag" :height="300" :data="labApproverDisplayList" @selection-change="handleLabApproverSelectionChange" @row-click="(row,column,event) => handleTesterTableClick(row,column,event,'labApproverTable')" ref="labApproverTable" border row-key="operatorId" style="width: 100%;"> <el-table-column type="selection" header-align="center" align="center" :reserve-selection="true" width="50"> </el-table-column> <el-table-column label="编码" property="operatorId" align="left" header-align="center"/> <el-table-column label="名称" property="operatorName" align="left" header-align="center"/> </el-table> <el-footer style="height:40px;margin-top: 20px;text-align:center"> <el-button type="primary" @click="saveLabApproverChooseModal">确定</el-button> <el-button type="primary" @click="labApproverFlag = false">关闭</el-button> </el-footer> </el-dialog>
<el-dialog title="选择-项目" :close-on-click-modal="false" @close="closeProjectInfoDialog" @open="searchProjectInfoList" :visible.sync="chooseProjectListFlag" width="35%"> <el-form label-position="top" :model="searchProjectData" ref="closeProjectInfoForm"> <el-row :gutter="10"> <el-col :span="6"> <el-form-item label="项目号"> <el-input v-model="searchProjectData.projectId"></el-input> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="项目名称"> <el-input v-model="searchProjectData.projectName"></el-input> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label=" "> <el-button type="primary" @click="searchProjectInfoList">查询</el-button> </el-form-item> </el-col> </el-row> <el-table :height="223" :data="projectList" border @row-click="projectClickRow"> <el-table-column label="项目号" prop="projectId"/> <el-table-column label="项目名称" prop="projectName"/> </el-table> </el-form> </el-dialog>
<el-tabs v-model="activeTable" type="border-card" style="width: 100%; height: 100%;" @tab-click="tabClick" v-loading="currentDetailLoading" class="customer-tab"> <el-tab-pane label="基本信息" name="basicInfo"> <div :style="{height: secondHeight + 'px'}" style="margin-left: 5px;margin-top: 5px; overflow-y: auto;"> <el-form :inline="true" label-position="top" :model="currentDetail"> <el-form-item label="申请人/Application"> <el-input :value="currentDetail.applicant || ''" disabled style="width: 100px"></el-input> <el-input :value="currentDetail.applicantName || ''" disabled style="width: 155px"></el-input> </el-form-item> <el-form-item label="申请日期/Apply Date"> <el-input :value="normalizeDateOnly(currentDetail.applicationDate)" disabled style="width: 110px"></el-input> </el-form-item> <el-form-item label="申请工厂/Apply Site"> <el-input :value="currentDetail.site || ''" disabled style="width: 135px"></el-input> </el-form-item> <el-form-item label="申请部门/Apply Department"> <el-input :value="currentDetail.applyDepartment || ''" disabled style="width: 225px"></el-input> </el-form-item> </el-form>
<el-form :inline="true" label-position="top" :model="currentDetail"> <el-form-item label="客户/Customer"> <el-input :value="currentDetail.customerId || ''" disabled style="width: 100px"></el-input> <el-input :value="currentDetail.customerName || ''" disabled style="width: 155px"></el-input> </el-form-item> <el-form-item label="项目/Project"> <el-input :value="currentDetail.projectId || ''" disabled style="width: 100px"></el-input> <el-input :value="currentDetail.projectName || ''" disabled style="width: 155px"></el-input> </el-form-item> <el-form-item label="需求日期/Requested Date"> <el-input :value="normalizeDateOnly(currentDetail.requestedDate)" disabled style="width: 225px"></el-input> </el-form-item> </el-form>
<el-form :inline="true" label-position="top" :model="currentDetail"> <el-form-item label="样品名称/Sample Name"> <el-input :value="currentDetail.sampleName || ''" disabled style="width: 260px"></el-input> </el-form-item> <el-form-item label="样品型号/Sample Model"> <el-input :value="currentDetail.sampleModel || ''" disabled style="width: 259px"></el-input> </el-form-item> <el-form-item label="样品数量/Sample QTY"> <el-input :value="currentDetail.sampleQty || ''" disabled style="width: 225px"></el-input> </el-form-item> </el-form>
<el-form :inline="true" label-position="top" :model="currentDetail"> <el-form-item label="测试目的/Test Purpose"> <el-input :value="currentDetail.testPurpose || ''" disabled style="width: 260px"></el-input> </el-form-item> <el-form-item label="产品阶段/Product Stage"> <el-input :value="currentDetail.productStage || ''" disabled style="width: 259px"></el-input> </el-form-item> <el-form-item label="测试类型/Test Type"> <el-input :value="currentDetail.testType || ''" disabled style="width: 225px"></el-input> </el-form-item> </el-form>
<el-form :inline="true" label-position="top" :model="currentDetail"> <el-form-item label="报告出具/Report Document"> <el-input :value="currentDetail.reportDocument || ''" disabled style="width: 260px"></el-input> </el-form-item> <el-form-item label="样品退回/Return Sample"> <el-input :value="displayYesNo(currentDetail.returnSample)" disabled style="width: 259px"></el-input> </el-form-item> </el-form>
<el-form :inline="true" label-position="top" :model="currentDetail"> <el-form-item label="Application Surface"> <el-input :value="currentDetail.applicationSurface || ''" disabled style="width: 533px"></el-input> </el-form-item> <el-form-item label="Test Lab"> <el-input :value="currentDetail.testLab || ''" disabled style="width: 225px"></el-input> </el-form-item> </el-form>
<el-form :inline="true" label-position="top" :model="currentDetail" style="margin-top: 0px"> <el-form-item label="实验室审批人" style="display: block;"> <el-input :value="currentDetail.labApproverName || currentDetail.labApprover || ''" disabled style="width: 772px"></el-input> </el-form-item> </el-form>
<div class="rq" style="width: 772px;margin-top: 0px"> <el-table :data="currentDetail.propertyItemList || []" border :height="260" style="width: 100%;"> <el-table-column prop="itemNo" header-align="center" align="center" label="属性编码" width="100"></el-table-column> <el-table-column prop="itemDesc" header-align="center" align="left" label="属性名称" min-width="150"></el-table-column> <el-table-column prop="itemValue" header-align="center" align="left" label="属性值" min-width="250" show-overflow-tooltip></el-table-column> </el-table> </div>
<el-form :inline="true" label-position="top" :model="currentDetail" style="margin-top: 5px"> <el-form-item label="测试规范/Test spec" style="display: block;"> <div class="judge-criteria-box" style="cursor: default;"> <template v-if="currentTestSpecFileList.length > 0"> <el-link v-for="item in currentTestSpecFileList" :key="item.id" type="primary" style="margin-right: 10px" @click.stop="previewJudgeCriteriaFile(item)"> {{ item.fileName }} </el-link> </template> <span v-else class="judge-criteria-placeholder">暂无测试规范附件</span> </div> </el-form-item> </el-form>
<el-form :inline="true" label-position="top" :model="currentDetail" style="margin-top: 18px"> <el-form-item label="判断标准/Judge Criteria" style="display: block;"> <div class="judge-criteria-box" style="cursor: default;"> <template v-if="currentJudgeCriteriaFileList.length > 0"> <el-link v-for="item in currentJudgeCriteriaFileList" :key="item.id" type="primary" style="margin-right: 10px" @click.stop="previewJudgeCriteriaFile(item)"> {{ item.fileName }} </el-link> </template> <span v-else class="judge-criteria-placeholder">暂无判断标准附件</span> </div> </el-form-item> </el-form>
<el-form :inline="true" label-position="top" :model="currentDetail" style="margin-top: 20px"> <el-form-item label="注意事项/Attention" style="display: block;"> <el-input type="textarea" :rows="3" :value="currentDetail.attention || ''" disabled resize="none" style="width: 772px"></el-input> </el-form-item> </el-form> </div> </el-tab-pane> <el-tab-pane label="审批信息" name="approvalInfoDetail"> <div :style="{height: secondHeight + 'px'}" style="margin-left: 5px;margin-top: 5px; overflow-y: auto;"> <el-form :inline="true" label-position="top" :model="currentDetail"> <el-form-item label="备注(部门经理)/ Comments(Department Manager)" style="display: block;"> <el-input type="textarea" :rows="3" :value="currentDetail.departmentManagerComments || ''" disabled resize="none" style="width: 772px"></el-input> </el-form-item> </el-form> <el-form :inline="true" label-position="top" :model="currentDetail" style="margin-top: 45px"> <el-form-item label="备注(实验室)/ Comments(Lab)" style="display: block;"> <el-input type="textarea" :rows="3" :value="currentDetail.labComments || ''" disabled resize="none" style="width: 772px"></el-input> </el-form-item> </el-form> <el-form :inline="true" label-position="top" :model="currentDetail" style="margin-top: 45px"> <el-form-item label="测试人/Tester"> <el-input :value="currentDetail.testerName || currentDetail.tester || ''" disabled style="width: 772px"></el-input> </el-form-item> </el-form> </div> </el-tab-pane>
<el-tab-pane label="测试结果" name="resultInfo"> <div :style="{height: secondHeight + 'px'}" style="margin-left: 5px;margin-top: 5px; overflow-y: auto;"> <el-form :inline="true" label-position="top" :model="currentDetail"> <el-form-item label="测试开始时间/Test Start Date"> <el-input :value="normalizeDateOnly(currentDetail.testStartDate)" disabled style="width: 170px"></el-input> </el-form-item> <el-form-item label="测试完成日期/Completed Date"> <el-input :value="normalizeDateOnly(currentDetail.completedDate)" disabled style="width: 170px"></el-input> </el-form-item> <el-form-item label="测试编码/Test Number"> <el-input :value="currentDetail.testNumber || ''" disabled style="width: 250px"></el-input> </el-form-item> </el-form> <el-form :inline="true" label-position="top" :model="currentDetail"> <el-form-item label="异常情况及说明/Unnormal symptom and description" style="display: block;"> <el-input type="textarea" :rows="3" :value="currentDetail.unnormalSymptomAndDescription || ''" disabled resize="none" style="width: 772px"></el-input> </el-form-item> </el-form> <el-form :inline="true" label-position="top" :model="currentDetail" style="margin-top: 45px"> <el-form-item label="测试报告/Test Report" style="display: block;"> <div class="judge-criteria-box" style="cursor: default;"> <template v-if="currentTestReportFileList.length > 0"> <el-link v-for="item in currentTestReportFileList" :key="item.id" type="primary" style="margin-right: 10px" @click.stop="previewTestReportFile(item)"> {{ item.fileName }} </el-link> </template> <span v-else class="judge-criteria-placeholder">暂无测试报告附件</span> </div> </el-form-item> </el-form> <el-form :inline="true" label-position="top" :model="currentDetail" style="margin-top: 20px"> <el-form-item label="备注/Comments" style="display: block;"> <el-input type="textarea" :rows="3" :value="currentDetail.testerComments || ''" disabled resize="none" style="width: 772px"></el-input> </el-form-item> </el-form> </div> </el-tab-pane>
<el-tab-pane label="审批记录" name="approvalInformation"> <approval-information v-model:data-list="approvalList" :height="secondHeight"></approval-information> </el-tab-pane>
</el-tabs>
<ChooseList ref="baseList" @getBaseData="getBaseData"></ChooseList> </div></template>
<script>import * as api from '@/api/lab/lab'import { getSiteList, searchUserListForRole } from '@/api/base/site'import { queryOss, previewOssFileById } from '@/api/oss/oss'import { checkSuperAdmin } from '@/api/changeManagement/changeManagement'import { verifyData } from '@/api/chooselist/chooselist.js'import { searchProjectInfoList } from '@/api/quotation/quotationInformation.js'import { queryCustomer } from '@/api/customer/customerInformation'import { queryProjectByCustomer } from '@/api/project/project'import ChooseList from '@/views/modules/common/Chooselist'import DictDataSelect from '../sys/dict-data-select.vue'import ApprovalInformation from '../changeManagement/approvalInformation.vue'import ossComponents from '../oss/ossComponents.vue'
export default { components: { ChooseList, DictDataSelect, ApprovalInformation, ossComponents }, data () { return { searchData: { site: '', referenceNo: '', status: '', currentApprover: '', nodeId: '' }, exportLoading: false, exportData: [], exportFieldMap: {}, exportName: '', exportHeader: ['Lab记录'], exportFooter: [], resultList: [], dataListSelections: [], dataList: [], pageIndex: 1, pageSize: 20, totalPage: 0, dataListLoading: false,
activeTable: 'basicInfo', menuId: '', authSearch: false, authUpdate: false, authIssue: false, authSubmit: false, authReject: false, authDelete: false, authFileSave: false, authFileDownLoad: false, authFileRemove: false, authFilePreview: false, authDataEntry: false, superAdmin: false, createBy2: this.$store.state.user.name, height: 400, secondHeight: 200, currentRow: {}, currentDetail: this.buildEmptyDetailData(), currentDetailLoading: false, currentDetailRequestId: 0, nodeOptions: [], approvalList: [], plmLabAuthorityArr: [], nodeAuthorityLoaded: false, isEditMode: false, modalTitle: 'Lab 新增', activeName: 'basicInfo', showModalFlag: false, submitModalFlag: false, rejectOpinion: '', submitLoading: false,
tagNo: null, tagNo1: null, modalFlag: false, judgeCriteriaDialogVisible: false, testSpecDialogVisible: false, testReportDialogVisible: false, judgeCriteriaFileList: [], testSpecFileList: [], currentJudgeCriteriaFileList: [], currentTestSpecFileList: [], currentTestReportFileList: [], testReportFileList: [], judgeCriteriaFileColumnList: [ { columnProp: 'fileName', headerAlign: 'center', align: 'center', columnLabel: '文件名称', columnHidden: false, columnImage: false, columnSortable: false, status: true, fixed: '', columnWidth: 180 }, { columnProp: 'fileRemark', headerAlign: 'center', align: 'center', columnLabel: '备注', columnHidden: false, columnImage: false, columnSortable: false, status: true, fixed: '', columnWidth: 220 }, { columnProp: 'createDate', headerAlign: 'center', align: 'center', columnLabel: '上传时间', columnHidden: false, columnImage: false, columnSortable: false, status: true, fixed: '', columnWidth: 170 }, { columnProp: 'createBy', headerAlign: 'center', align: 'center', columnLabel: '上传人', columnHidden: false, columnImage: false, columnSortable: false, status: true, fixed: '', columnWidth: 140 } ], siteOptions: [], chooseProjectListFlag: false, searchProjectData: { site: '', projectId: undefined, projectName: undefined, customerId: undefined }, projectList: [], modalData: this.buildDefaultModalData(), propertyChooseModalFlag: false, propertyModelList: [], propertyItemList: [], propertyItemSelections: [], propertyChooseData: this.buildDefaultPropertyChooseData(), testerOptionList: [], testerDisplayList: [], testerSelectionCache: [], testerFlag: false, testerSearchData: { operatorId: '', operatorName: '' }, labApproverOptionList: [], labApproverDisplayList: [], labApproverSelectionCache: [], labApproverFlag: false, labApproverSearchData: { operatorId: '', operatorName: '' } } }, created () { this.menuId = this.$route.meta.menuId this.getButtonAuthData() this.checkSuperAdmin() this.loadSiteOptions() }, mounted () { this.fetchNodeOptions() if (this.authSearch) { this.getDataList() } this.$nextTick(() => { this.height = window.innerHeight / 2 - 30 this.secondHeight = window.innerHeight / 2 - 186 }) }, methods: { buildDefaultPropertyChooseData () { const currentSite = this.modalData && this.modalData.site ? this.modalData.site : this.$store.state.user.site return { site: currentSite, functionType: 'LAB', codeNo: '', itemNo: '', itemDesc: '' } }, getDefaultSiteValue () { const loginSite = this.$store.state.user.site || '' if (this.siteOptions.some(item => item.siteID === loginSite)) { return loginSite } if (this.siteOptions.length > 0) { return this.siteOptions[0].siteID || loginSite } return loginSite }, loadSiteOptions () { getSiteList().then(({data}) => { if (data && data.code === 0 && Array.isArray(data.rows)) { this.siteOptions = data.rows } else { this.siteOptions = [] } }).catch(() => { this.siteOptions = [] }).finally(() => { if (this.siteOptions.length === 0 && this.$store.state.user.site) { this.siteOptions = [{ siteID: this.$store.state.user.site, siteName: this.$store.state.user.site }] } }) }, buildDefaultModalData (useLoginSite = true) { return { site: useLoginSite ? this.$store.state.user.site : '', referenceNo: '', applicant: '', applicantName: '', applicationDate: '', applyDepartment: '', requestedDate: '', customerId: '', customerName: '', customerIdFlag: false, projectId: '', projectName: '', projectIdFlag: true, sampleName: '', sampleModel: '', sampleQty: '', testPurpose: '', productStage: '', testType: '', reportDocument: '', returnSample: '', applicationSurface: '', testLab: '', labApprover: '', labApproverName: '', labApproverCodeList: [], labApproverList: [], attention: '', testStartDate: '', completedDate: '', unnormalSymptomAndDescription: '', testNumber: '', testerComments: '', departmentManagerComments: '', labComments: '', tester: '', testerName: '', testerCodeList: [], testerList: [], status: '草稿', stepId: 10, rejectFlag: 'N', rejectStepId: null, createBy2: '', isReject: 'Y', tpProcessControl: 'N', csProcessControl: 'N', propertyItemList: [] } }, buildEmptyDetailData () { return this.buildDefaultModalData(false) }, fetchNodeOptions () { if (!this.menuId) { this.nodeOptions = [] return } const siteForNode = this.searchData.site || this.$store.state.user.site const params = { site: siteForNode, menuId: this.menuId } api.getNodeList(params).then(({data}) => { if (data && data.code === 0 && Array.isArray(data.rows)) { this.nodeOptions = data.rows .filter(item => item && item.nodeId) .map(item => ({ id: item.nodeId, name: item.nodeName })) } else { this.nodeOptions = [] } }).catch(() => { this.nodeOptions = [] }) }, handleModalSiteChange (site) { if (!site || this.isEditMode) { return } this.testSpecDialogVisible = false this.testReportDialogVisible = false this.testerFlag = false this.testerOptionList = [] this.testerDisplayList = [] this.testerSelectionCache = [] this.testerSearchData = { operatorId: '', operatorName: '' } this.resetLabApproverOptionState() this.modalData.customerId = '' this.modalData.customerName = '' this.modalData.projectId = '' this.modalData.projectName = '' this.modalData.projectIdFlag = true this.$set(this.modalData, 'testerCodeList', []) this.$set(this.modalData, 'testerList', []) this.$set(this.modalData, 'tester', '') this.$set(this.modalData, 'testerName', '') this.clearLabApproverFieldData() this.$set(this.modalData, 'propertyItemList', []) this.judgeCriteriaFileList = [] this.testSpecFileList = [] this.testReportFileList = [] this.searchProjectData.site = site }, resetLabApproverOptionState () { this.labApproverFlag = false this.labApproverOptionList = [] this.labApproverDisplayList = [] this.labApproverSelectionCache = [] this.labApproverSearchData = { operatorId: '', operatorName: '' } }, clearLabApproverFieldData () { this.$set(this.modalData, 'labApproverCodeList', []) this.$set(this.modalData, 'labApproverList', []) this.$set(this.modalData, 'labApprover', '') this.$set(this.modalData, 'labApproverName', '') }, handleTestLabChange (value) { if (!this.modalData || this.showModalFlag || this.isLabFieldDisabled('testLab')) { return } this.$set(this.modalData, 'testLab', value || '') this.resetLabApproverOptionState() this.clearLabApproverFieldData() }, loadNodeAuthority (site, stepId) { if (!site || stepId === null || stepId === undefined || !this.menuId) { this.plmLabAuthorityArr = [] this.nodeAuthorityLoaded = true return Promise.resolve() } this.nodeAuthorityLoaded = false const params = { site: site, stepId: stepId, menuId: this.menuId } return api.getLabNodeAuthority(params).then(({data}) => { if (data && data.code === 0 && data.rows) { this.plmLabAuthorityArr = data.rows.plm_lab || [] } else { this.plmLabAuthorityArr = [] } this.nodeAuthorityLoaded = true }).catch(() => { this.plmLabAuthorityArr = [] this.nodeAuthorityLoaded = true }) }, labFieldFlag (fieldId) { if (!this.plmLabAuthorityArr || this.plmLabAuthorityArr.length === 0) { return 'N' } const target = this.plmLabAuthorityArr.find(item => item.fieldId === fieldId) return target ? target.updateFlag : 'N' }, isLabFieldDisabled (fieldId) { if (this.showModalFlag) { return true } if (!this.isEditMode) { return false } return this.labFieldFlag(fieldId) === 'N' }, normalizeDateOnly (value) { if (value === null || value === undefined || value === '') { return '' } if (value instanceof Date && !Number.isNaN(value.getTime())) { const year = value.getFullYear() const month = String(value.getMonth() + 1).padStart(2, '0') const day = String(value.getDate()).padStart(2, '0') return year + '-' + month + '-' + day } const text = String(value).trim() if (!text) { return '' } if (text.includes('T')) { return text.split('T')[0] } return text.length >= 10 ? text.substring(0, 10) : text }, getCurrentDateString () { return this.normalizeDateOnly(new Date()) }, displayYesNo (value) { if (value === 'Y') { return '是' } if (value === 'N') { return '否' } return value || '' }, resolvePreviewContentType (fileType) { const lower = String(fileType || '').toLowerCase() if (!lower) { return '' } if (['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'].includes(lower)) { return 'image/' + lower } if (['mp4', 'avi', 'mov', 'wmv', 'flv'].includes(lower)) { return 'video/' + lower } if (lower === 'txt') { return 'text/plain;charset=utf-8' } if (lower === 'pdf') { return 'application/pdf;charset=UTF-8' } if (['xls', 'xlsx', 'docx'].includes(lower)) { return lower } return '' }, refreshJudgeCriteriaOssTable () { const ref = this.$refs.judgeCriteriaOss if (ref && typeof ref.handleQuery === 'function') { ref.handleQuery() } }, refreshTestSpecOssTable () { const ref = this.$refs.testSpecOss if (ref && typeof ref.handleQuery === 'function') { ref.handleQuery() } }, refreshTestReportOssTable () { const ref = this.$refs.testReportOss if (ref && typeof ref.handleQuery === 'function') { ref.handleQuery() } }, queryAttachmentFileList (site, referenceNo, orderRef3) { if (!site || !referenceNo || !orderRef3) { return Promise.resolve([]) } const params = { orderRef1: site, orderRef2: referenceNo, orderRef3: orderRef3 } return queryOss(params).then(({data}) => { if (data && data.code === 0 && Array.isArray(data.rows)) { return data.rows } return [] }).catch(() => { return [] }) }, refreshJudgeCriteriaFileList () { return this.queryAttachmentFileList(this.modalData.site, this.modalData.referenceNo, 'judgeCriteria').then(rows => { this.judgeCriteriaFileList = rows }) }, refreshTestSpecFileList () { return this.queryAttachmentFileList(this.modalData.site, this.modalData.referenceNo, 'testSpec').then(rows => { this.testSpecFileList = rows }) }, refreshTestReportFileList () { return this.queryAttachmentFileList(this.modalData.site, this.modalData.referenceNo, 'testReport').then(rows => { this.testReportFileList = rows }) }, loadCurrentAttachmentFileLists (site, referenceNo, requestId) { if (!site || !referenceNo) { if (requestId === this.currentDetailRequestId) { this.currentJudgeCriteriaFileList = [] this.currentTestSpecFileList = [] this.currentTestReportFileList = [] } return Promise.resolve() } return Promise.all([ this.queryAttachmentFileList(site, referenceNo, 'judgeCriteria'), this.queryAttachmentFileList(site, referenceNo, 'testSpec'), this.queryAttachmentFileList(site, referenceNo, 'testReport') ]).then(([judgeFiles, testSpecFiles, testReportFiles]) => { if (requestId !== this.currentDetailRequestId) { return } this.currentJudgeCriteriaFileList = judgeFiles this.currentTestSpecFileList = testSpecFiles this.currentTestReportFileList = testReportFiles }) }, openJudgeCriteriaDialog () { if (!this.modalData.site) { this.$message.warning('请先选择申请工厂') return } if (!this.modalData.referenceNo) { this.$message.warning('单据编号为空,无法上传附件') return } this.judgeCriteriaDialogVisible = true this.refreshJudgeCriteriaFileList() this.$nextTick(() => { this.refreshJudgeCriteriaOssTable() }) }, openTestSpecDialog () { if (!this.modalData.site) { this.$message.warning('请先选择申请工厂') return } if (!this.modalData.referenceNo) { this.$message.warning('单据编号为空,无法上传附件') return } this.testSpecDialogVisible = true this.refreshTestSpecFileList() this.$nextTick(() => { this.refreshTestSpecOssTable() }) }, openTestReportDialog () { if (!this.modalData.site) { this.$message.warning('请先选择申请工厂') return } if (!this.modalData.referenceNo) { this.$message.warning('单据编号为空,无法上传附件') return } this.testReportDialogVisible = true this.refreshTestReportFileList() this.$nextTick(() => { this.refreshTestReportOssTable() }) }, handleJudgeCriteriaDialogClose () { this.refreshJudgeCriteriaFileList() }, handleTestSpecDialogClose () { this.refreshTestSpecFileList() }, handleTestReportDialogClose () { this.refreshTestReportFileList() }, previewJudgeCriteriaFile (row) { if (!this.authFilePreview) { this.$message.warning('没有附件预览权限') return } if (!row || !row.id) { this.$message.warning('附件不存在,无法预览') return } const type = this.resolvePreviewContentType(row.fileType) if (!type) { this.$message.warning('该文件格式暂不支持预览') return } previewOssFileById({ id: row.id }).then(({data}) => { const blob = new Blob([data], { type: type }) const fileURL = URL.createObjectURL(blob) if (type === 'xls' || type === 'xlsx' || type === 'docx') { const { href } = this.$router.resolve({ name: 'pre', query: { src: fileURL, type: type } }) window.open(href, '_blank') } else { window.open(fileURL, '_blank') } }).catch(() => { this.$message.error('文件预览失败') }) }, previewTestReportFile (row) { this.previewJudgeCriteriaFile(row) }, resolvePropertyDefaultValue (item) { if (item && item.defaultValue !== null && item.defaultValue !== undefined && String(item.defaultValue).trim() !== '') { return String(item.defaultValue).trim() } if (item && item.valueChooseFlag === 'Y' && Array.isArray(item.availableValueList) && item.availableValueList.length > 0) { const firstValue = item.availableValueList[0].availableValue return firstValue === null || firstValue === undefined ? '' : String(firstValue) } return '' }, normalizePropertyItem (item) { const raw = item || {} const availableValueList = Array.isArray(raw.availableValueList) ? raw.availableValueList.map(option => ({ itemNo: raw.itemNo || '', availableValue: option && option.availableValue !== undefined && option.availableValue !== null ? String(option.availableValue) : '' })).filter(option => option.availableValue !== '') : [] const defaultValue = raw.defaultValue === null || raw.defaultValue === undefined ? '' : String(raw.defaultValue) if (defaultValue && !availableValueList.some(option => option.availableValue === defaultValue)) { availableValueList.unshift({ itemNo: raw.itemNo || '', availableValue: defaultValue }) } const itemValueSource = raw.itemValue !== undefined && raw.itemValue !== null ? raw.itemValue : raw.chooseValue const itemValue = itemValueSource === undefined || itemValueSource === null || String(itemValueSource).trim() === '' ? this.resolvePropertyDefaultValue({ ...raw, defaultValue, availableValueList }) : String(itemValueSource) return { site: raw.site || this.modalData.site || this.$store.state.user.site, referenceNo: raw.referenceNo || this.modalData.referenceNo || '', seqNo: raw.seqNo || 0, itemNo: raw.itemNo || '', itemDesc: raw.itemDesc || '', itemValue: itemValue, valueChooseFlag: raw.valueChooseFlag || 'N', defaultValue: defaultValue, availableValueList: availableValueList } }, loadPropertyModelList () { const params = { site: this.modalData.site, functionType: 'LAB', codeNo: '', codeDesc: '' } return api.getLabPropertyModelList(params).then(({data}) => { if (data && data.code === 0) { this.propertyModelList = data.data || [] } else { this.propertyModelList = [] this.$message.warning((data && data.msg) || '查询Lab属性模板失败') } }).catch(() => { this.propertyModelList = [] this.$message.error('查询Lab属性模板失败') }) }, restorePropertySelection () { if (!this.$refs.propertyItemTable) { return } this.$refs.propertyItemTable.clearSelection() const selectedNos = new Set((this.modalData.propertyItemList || []).map(item => item.itemNo)) this.propertyItemList.forEach(item => { if (selectedNos.has(item.itemNo)) { this.$refs.propertyItemTable.toggleRowSelection(item, true) } }) }, openPropertyChooseModal () { if (!this.modalData.site) { this.$message.warning('请先选择申请工厂') return } this.propertyChooseData = this.buildDefaultPropertyChooseData() this.propertyChooseData.site = this.modalData.site this.propertyItemList = [] this.propertyItemSelections = [] this.loadPropertyModelList().then(() => { if (this.propertyModelList.length === 0) { this.$message.warning('请先在属性模板管理维护LAB模板') return } this.propertyChooseData.codeNo = this.propertyModelList[0].codeNo this.propertyChooseModalFlag = true this.$nextTick(() => { this.searchPropertyItemList(true) }) }) }, searchPropertyItemList (restoreSelection = false) { if (!this.propertyChooseData.codeNo) { this.propertyItemList = [] if (restoreSelection) { this.$nextTick(() => this.restorePropertySelection()) } this.$message.warning('请选择模板') return } const params = { site: this.modalData.site, functionType: 'LAB', codeNo: this.propertyChooseData.codeNo, itemNo: this.propertyChooseData.itemNo, itemDesc: this.propertyChooseData.itemDesc } api.getLabPropertyItemList(params).then(({data}) => { if (data && data.code === 0) { this.propertyItemList = (data.rows || []).map(item => this.normalizePropertyItem(item)) this.$nextTick(() => { this.restorePropertySelection() }) } else { this.propertyItemList = [] this.$message.warning((data && data.msg) || '查询属性清单失败') } }).catch(() => { this.propertyItemList = [] this.$message.error('查询属性清单失败') }) }, propertyItemClickRow (row) { if (!this.$refs.propertyItemTable) { return } this.$refs.propertyItemTable.toggleRowSelection(row) }, selectionPropertyItem (val) { this.propertyItemSelections = val || [] }, confirmPropertyItem () { if (!this.propertyItemSelections || this.propertyItemSelections.length === 0) { this.$message.warning('请勾选属性') return } const currentList = Array.isArray(this.modalData.propertyItemList) ? this.modalData.propertyItemList : [] const selectedNoSet = new Set(this.propertyItemSelections.map(item => item.itemNo)) const mergedList = []
currentList.forEach(item => { if (selectedNoSet.has(item.itemNo)) { mergedList.push(this.normalizePropertyItem(item)) } })
this.propertyItemSelections.forEach(selected => { if (!mergedList.some(item => item.itemNo === selected.itemNo)) { const normalized = this.normalizePropertyItem(selected) normalized.itemValue = this.resolvePropertyDefaultValue(normalized) mergedList.push(normalized) } })
this.$set(this.modalData, 'propertyItemList', mergedList.map((item, index) => ({ ...this.normalizePropertyItem(item), seqNo: index + 1 }))) this.propertyChooseModalFlag = false }, syncPropertyItemList () { const list = Array.isArray(this.modalData.propertyItemList) ? this.modalData.propertyItemList : [] this.$set(this.modalData, 'propertyItemList', list.map((item, index) => ({ ...this.normalizePropertyItem(item), site: this.modalData.site, referenceNo: this.modalData.referenceNo, seqNo: index + 1 }))) }, getLabSubmitFieldValue (fieldId) { if (fieldId === 'tester') { return this.modalData.testerCodeList } if (fieldId === 'labApprover') { return this.modalData.labApproverCodeList } return this.modalData[fieldId] }, isSubmitFieldEmpty (value) { if (Array.isArray(value)) { return value.length === 0 } if (typeof value === 'string') { return value.trim() === '' } return value === null || value === undefined || value === '' }, validateSubmitRequiredFields () { if (this.plmLabAuthorityArr && this.plmLabAuthorityArr.length > 0) { for (let i = 0; i < this.plmLabAuthorityArr.length; i++) { const fieldConfig = this.plmLabAuthorityArr[i] if (fieldConfig.required !== 'Y') { continue } const value = this.getLabSubmitFieldValue(fieldConfig.fieldId) if (this.isSubmitFieldEmpty(value)) { this.$message.warning((fieldConfig.fieldName || fieldConfig.fieldId) + '不能为空!') return false } } } return true }, normalizeTesterList (value) { const source = Array.isArray(value) ? value : String(value || '').split(';') const uniqueList = [] const seen = new Set() source.forEach(item => { const code = String(item || '').trim() if (!code || seen.has(code)) { return } seen.add(code) uniqueList.push(code) }) return uniqueList }, normalizeTesterOptionList (rows) { if (!Array.isArray(rows)) { return [] } return rows .map(item => { const operatorId = String(item.operatorId || item.operator_id || item.username || item.userName || '').trim() const operatorName = String(item.operatorName || item.operator_name || item.userDisplay || item.user_display || '').trim() if (!operatorId || !operatorName) { return null } return { operatorId, operatorName } }) .filter(item => !!item) }, resolveTesterNameById (operatorId) { const normalizedId = String(operatorId || '').trim() if (!normalizedId) { return '' } const target = (this.testerOptionList || []).find(item => String(item.operatorId || '').trim() === normalizedId) return target ? String(target.operatorName || '').trim() : normalizedId }, syncTesterField () { const testerList = this.normalizeTesterList(this.modalData.testerCodeList || this.modalData.testerList || this.modalData.tester) this.$set(this.modalData, 'testerCodeList', testerList) this.$set(this.modalData, 'testerList', testerList) this.$set(this.modalData, 'tester', testerList.join(';')) this.$set(this.modalData, 'testerName', testerList.map(item => this.resolveTesterNameById(item)).join(';')) }, resolveLabApproverNameById (operatorId) { const normalizedId = String(operatorId || '').trim() if (!normalizedId) { return '' } const target = (this.labApproverOptionList || []).find(item => String(item.operatorId || '').trim() === normalizedId) return target ? String(target.operatorName || '').trim() : normalizedId }, syncLabApproverField () { const labApproverList = this.normalizeTesterList(this.modalData.labApproverCodeList || this.modalData.labApproverList || this.modalData.labApprover) this.$set(this.modalData, 'labApproverCodeList', labApproverList) this.$set(this.modalData, 'labApproverList', labApproverList) this.$set(this.modalData, 'labApprover', labApproverList.join(';')) this.$set(this.modalData, 'labApproverName', labApproverList.map(item => this.resolveLabApproverNameById(item)).join(';')) }, filterTesterOptions () { const operatorIdKeyword = String(this.testerSearchData.operatorId || '').trim().toUpperCase() const operatorNameKeyword = String(this.testerSearchData.operatorName || '').trim().toUpperCase() this.testerDisplayList = (this.testerOptionList || []).filter(item => { const operatorId = String(item.operatorId || '').toUpperCase() const operatorName = String(item.operatorName || '').toUpperCase() const matchOperatorId = !operatorIdKeyword || operatorId.includes(operatorIdKeyword) const matchOperatorName = !operatorNameKeyword || operatorName.includes(operatorNameKeyword) return matchOperatorId && matchOperatorName }) }, loadTesterOptions () { if (!this.modalData || !this.modalData.site) { this.testerOptionList = [] this.testerDisplayList = [] this.testerSelectionCache = [] return Promise.resolve() } const params = { site: this.modalData.site, roleNo: 'R015', active: 'Y' } return searchUserListForRole(params).then(({data}) => { if (data && data.code === 0) { const roleUserSet = new Set( (Array.isArray(data.searchUserListForRole) ? data.searchUserListForRole : []) .map(item => String(item || '').trim()) .filter(item => !!item) ) const userList = (Array.isArray(data.userList) ? data.userList : []).filter(item => { const username = String(item.username || item.userName || '').trim() return !!username && roleUserSet.has(username) }) this.testerOptionList = this.normalizeTesterOptionList(userList) this.filterTesterOptions() this.testerSelectionCache = [] this.syncTesterField() } else { this.testerOptionList = [] this.testerDisplayList = [] this.testerSelectionCache = [] } }).catch(() => { this.testerOptionList = [] this.testerDisplayList = [] this.testerSelectionCache = [] }) }, openTesterChooseModal () { if (this.isLabFieldDisabled('tester')) { return } if (!this.modalData || !String(this.modalData.site || '').trim()) { this.$message.warning('请先选择工厂') return } this.loadTesterOptions().then(() => { if (!this.testerOptionList || this.testerOptionList.length === 0) { this.$message.warning('未查询到可选测试人') return } this.testerFlag = true }) }, openTesterDialog () { this.testerSearchData = { operatorId: '', operatorName: '' } this.filterTesterOptions() const selectedOperatorSet = new Set( (this.modalData.testerCodeList || []) .map(item => String(item || '').trim()) .filter(item => !!item) ) const selectedRows = (this.testerOptionList || []).filter(item => selectedOperatorSet.has(String(item.operatorId || '').trim())) this.testerSelectionCache = JSON.parse(JSON.stringify(selectedRows)) this.$nextTick(() => { if (!this.$refs.testerTable) { return } this.$refs.testerTable.clearSelection() selectedRows.forEach(item => { this.$refs.testerTable.toggleRowSelection(item, true) }) }) }, closeTesterDialog () { this.testerSelectionCache = [] }, handleTesterSelectionChange (rows) { this.testerSelectionCache = rows || [] }, handleTesterTableClick (row, column, event, tableRef) { if (this.$refs[tableRef]) { this.$refs[tableRef].toggleRowSelection(row) } }, saveTesterChooseModal () { const selectedCodes = (this.testerSelectionCache || []) .map(item => String(item.operatorId || '').trim()) .filter(item => !!item) this.$set(this.modalData, 'testerCodeList', selectedCodes) this.syncTesterField() this.testerFlag = false }, clearTesterSelection () { this.$set(this.modalData, 'testerCodeList', []) this.syncTesterField() }, filterLabApproverOptions () { const operatorIdKeyword = String(this.labApproverSearchData.operatorId || '').trim().toUpperCase() const operatorNameKeyword = String(this.labApproverSearchData.operatorName || '').trim().toUpperCase() this.labApproverDisplayList = (this.labApproverOptionList || []).filter(item => { const operatorId = String(item.operatorId || '').toUpperCase() const operatorName = String(item.operatorName || '').toUpperCase() const matchOperatorId = !operatorIdKeyword || operatorId.includes(operatorIdKeyword) const matchOperatorName = !operatorNameKeyword || operatorName.includes(operatorNameKeyword) return matchOperatorId && matchOperatorName }) }, loadLabApproverOptions () { if (!this.modalData || !this.modalData.site || !this.modalData.testLab) { this.resetLabApproverOptionState() return Promise.resolve() } const params = { site: this.modalData.site, roleNo: this.modalData.testLab, active: 'Y' } return searchUserListForRole(params).then(({data}) => { if (data && data.code === 0) { const roleUserSet = new Set( (Array.isArray(data.searchUserListForRole) ? data.searchUserListForRole : []) .map(item => String(item || '').trim()) .filter(item => !!item) ) const userList = (Array.isArray(data.userList) ? data.userList : []).filter(item => { const username = String(item.username || item.userName || '').trim() return !!username && roleUserSet.has(username) }) this.labApproverOptionList = this.normalizeTesterOptionList(userList) this.filterLabApproverOptions() this.labApproverSelectionCache = [] this.syncLabApproverField() } else { this.resetLabApproverOptionState() } }).catch(() => { this.resetLabApproverOptionState() }) }, openLabApproverChooseModal () { if (this.isLabFieldDisabled('labApprover')) { return } if (!this.modalData || !String(this.modalData.site || '').trim()) { this.$message.warning('请先选择工厂') return } if (!this.modalData.testLab) { this.$message.warning('请先选择Test Lab') return } this.loadLabApproverOptions().then(() => { if (!this.labApproverOptionList || this.labApproverOptionList.length === 0) { this.$message.warning('未查询到可选实验室审批人') return } this.labApproverFlag = true }) }, openLabApproverDialog () { this.labApproverSearchData = { operatorId: '', operatorName: '' } this.filterLabApproverOptions() const selectedOperatorSet = new Set( (this.modalData.labApproverCodeList || []) .map(item => String(item || '').trim()) .filter(item => !!item) ) const selectedRows = (this.labApproverOptionList || []).filter(item => selectedOperatorSet.has(String(item.operatorId || '').trim())) this.labApproverSelectionCache = JSON.parse(JSON.stringify(selectedRows)) this.$nextTick(() => { if (!this.$refs.labApproverTable) { return } this.$refs.labApproverTable.clearSelection() selectedRows.forEach(item => { this.$refs.labApproverTable.toggleRowSelection(item, true) }) }) }, closeLabApproverDialog () { this.labApproverSelectionCache = [] }, handleLabApproverSelectionChange (rows) { this.labApproverSelectionCache = rows || [] }, saveLabApproverChooseModal () { const selectedCodes = (this.labApproverSelectionCache || []) .map(item => String(item.operatorId || '').trim()) .filter(item => !!item) this.$set(this.modalData, 'labApproverCodeList', selectedCodes) this.syncLabApproverField() this.labApproverFlag = false }, clearLabApproverSelection () { this.$set(this.modalData, 'labApproverCodeList', []) this.syncLabApproverField() }, isCurrentApprover () { return this.superAdmin || (this.modalData.createBy2 && this.modalData.createBy2.split(';').includes(this.createBy2)) }, canSaveAction () { return !this.showModalFlag && (this.modalData.status === '草稿' || (this.modalData.status === '审批中' && this.isCurrentApprover())) }, canAgreeAction () { return this.authSubmit && this.isCurrentApprover() && this.modalData.status === '审批中' && this.modalData.tpProcessControl !== 'Y' && this.modalData.csProcessControl !== 'Y' }, canRejectAction () { return this.authReject && this.isCurrentApprover() && this.modalData.status === '审批中' && this.modalData.isReject === 'Y' }, getButtonAuthData () { this.authSearch = this.isAuth(this.menuId + ':search') this.authUpdate = this.isAuth(this.menuId + ':update') this.authIssue = this.isAuth(this.menuId + ':issue') this.authSubmit = this.isAuth(this.menuId + ':submit') this.authReject = this.isAuth(this.menuId + ':reject') this.authDelete = this.isAuth(this.menuId + ':delete') this.authFileSave = this.isAuth(this.menuId + ':fileSave') this.authFileDownLoad = this.isAuth(this.menuId + ':fileDownLoad') this.authFileRemove = this.isAuth(this.menuId + ':fileRemove') this.authFilePreview = this.isAuth(this.menuId + ':filePreview') this.authDataEntry = this.isAuth(this.menuId + ':dataEntry') }, checkSuperAdmin () { checkSuperAdmin().then(({data}) => { if (data && data.code === 0) { this.superAdmin = !!data.flag } }) }, rowStyle () { return { cursor: 'pointer' } }, dataListSelectionChange (rows) { this.dataListSelections = rows || [] }, changeClickRow (row) { this.handleCurrentRowChange(row) }, currentChange (row) { this.handleCurrentRowChange(row) }, handleCurrentRowChange (row) { const nextRow = row || {} const prevSite = (this.currentRow && this.currentRow.site) || '' const prevReferenceNo = (this.currentRow && this.currentRow.referenceNo) || '' const nextSite = nextRow.site || '' const nextReferenceNo = nextRow.referenceNo || '' this.currentRow = nextRow if (!nextSite || !nextReferenceNo) { this.currentDetailRequestId += 1 this.currentDetailLoading = false this.currentDetail = this.buildEmptyDetailData() this.currentJudgeCriteriaFileList = [] this.currentTestSpecFileList = [] this.currentTestReportFileList = [] this.refreshCurrentTabTable() return } if (prevSite !== nextSite || prevReferenceNo !== nextReferenceNo) { this.loadCurrentDetail(nextRow) } this.refreshCurrentTabTable() }, loadCurrentDetail (row) { if (!row || !row.site || !row.referenceNo) { this.currentDetailRequestId += 1 this.currentDetailLoading = false this.currentDetail = this.buildEmptyDetailData() this.currentJudgeCriteriaFileList = [] this.currentTestSpecFileList = [] this.currentTestReportFileList = [] return } const requestId = this.currentDetailRequestId + 1 this.currentDetailRequestId = requestId this.currentDetailLoading = true this.currentJudgeCriteriaFileList = [] this.currentTestSpecFileList = [] this.currentTestReportFileList = [] this.loadCurrentAttachmentFileLists(row.site, row.referenceNo, requestId) api.getLabDetail(row.site, row.referenceNo).then(({data}) => { if (requestId !== this.currentDetailRequestId) { return } if (data && data.code === 0) { const detail = data.data || {} const mergedDetail = { ...this.buildEmptyDetailData(), ...row, ...detail } this.fillDisplayFields(mergedDetail, row || {}) this.$set(mergedDetail, 'propertyItemList', (detail.propertyItemList || []).map(item => this.normalizePropertyItem(item))) this.$set(mergedDetail, 'testerList', this.normalizeTesterList(mergedDetail.tester)) this.$set(mergedDetail, 'labApproverList', this.normalizeTesterList(mergedDetail.labApprover)) this.currentDetail = mergedDetail } else { const fallbackDetail = { ...this.buildEmptyDetailData(), ...row } this.fillDisplayFields(fallbackDetail, row || {}) this.currentDetail = fallbackDetail } }).catch(() => { if (requestId !== this.currentDetailRequestId) { return } const fallbackDetail = { ...this.buildEmptyDetailData(), ...row } this.fillDisplayFields(fallbackDetail, row || {}) this.currentDetail = fallbackDetail }).finally(() => { if (requestId === this.currentDetailRequestId) { this.currentDetailLoading = false } }) }, tabClick () { this.refreshCurrentTabTable() }, refreshCurrentTabTable () { if (this.activeTable === 'approvalInformation') { this.getApprovalList() } }, getApprovalList () { if (!this.currentRow || !this.currentRow.site || !this.currentRow.referenceNo) { this.approvalList = [] return } const params = { site: this.currentRow.site, menuId: this.menuId, documentNo: this.currentRow.referenceNo } api.getLabApprovalList(params).then(({data}) => { if (data && data.code === 0) { this.approvalList = data.rows || [] } else { this.approvalList = [] } }).catch(() => { this.approvalList = [] }) }, getDataList () { if (!this.authSearch) { this.dataListSelections = [] this.dataList = [] this.totalPage = 0 this.currentRow = {} this.currentDetailRequestId += 1 this.currentDetail = this.buildEmptyDetailData() this.currentDetailLoading = false this.currentJudgeCriteriaFileList = [] this.currentTestSpecFileList = [] this.currentTestReportFileList = [] this.approvalList = [] return } this.dataListSelections = [] this.dataListLoading = true const params = { page: this.pageIndex, limit: this.pageSize, site: this.searchData.site || '', menuId: this.menuId, referenceNo: this.searchData.referenceNo, status: this.searchData.status, currentApprover: this.searchData.currentApprover, nodeId: this.searchData.nodeId } api.getLabList(params).then(({data}) => { if (data && data.code === 0) { const list = data.page.list || [] this.dataList = list.map(item => ({ applicantName: '', customerName: '', projectName: '', testerName: '', nodeId: '', nodeName: '', currentApprover: '', ...item })) this.totalPage = data.page.totalCount this.$nextTick(() => { if (this.$refs.labTable && this.dataList.length > 0) { this.$refs.labTable.setCurrentRow(this.dataList[0]) } else if (this.$refs.labTable) { this.$refs.labTable.setCurrentRow() } }) } else { this.dataListSelections = [] this.dataList = [] this.totalPage = 0 this.currentRow = {} this.currentDetailRequestId += 1 this.currentDetail = this.buildEmptyDetailData() this.currentDetailLoading = false this.currentJudgeCriteriaFileList = [] this.currentTestSpecFileList = [] this.currentTestReportFileList = [] this.approvalList = [] } this.dataListLoading = false }).catch(() => { this.dataListSelections = [] this.currentRow = {} this.currentDetailRequestId += 1 this.currentDetail = this.buildEmptyDetailData() this.currentDetailLoading = false this.currentJudgeCriteriaFileList = [] this.currentTestSpecFileList = [] this.currentTestReportFileList = [] this.approvalList = [] this.dataListLoading = false }) }, sizeChangeHandle (val) { this.pageSize = val this.pageIndex = 1 this.getDataList() }, currentChangeHandle (val) { this.pageIndex = val this.getDataList() }, searchHandle () { if (!this.authSearch) { return } this.pageIndex = 1 this.getDataList() }, buildExportName () { const now = new Date() const year = String(now.getFullYear()) const month = String(now.getMonth() + 1).padStart(2, '0') const day = String(now.getDate()).padStart(2, '0') const hour = String(now.getHours()).padStart(2, '0') const minute = String(now.getMinutes()).padStart(2, '0') const second = String(now.getSeconds()).padStart(2, '0') return 'Lab记录' + year + month + day + hour + minute + second }, async createExportData () { const params = { ...this.searchData, site: this.searchData.site || '', menuId: this.menuId, page: 1, limit: -1 } this.resultList = [] await api.getLabList(params).then(({data}) => { if (data && data.code === 0 && data.page && Array.isArray(data.page.list)) { this.resultList = (data.page.list || []).map(item => { const row = { ...item } row.applicationDate = this.normalizeDateOnly(row.applicationDate) row.requestedDate = this.normalizeDateOnly(row.requestedDate) row.testStartDate = this.normalizeDateOnly(row.testStartDate) row.completedDate = this.normalizeDateOnly(row.completedDate) row.returnSample = this.displayYesNo(row.returnSample) row.testerName = row.testerName || row.tester || '' return row }) } else { this.$message.warning((data && data.msg) || '导出数据获取失败') } }).catch(() => { this.$message.error('导出数据获取失败') }) return this.resultList }, startDownload () { this.exportName = this.buildExportName() this.exportFieldMap = this.buildExportFields() this.exportLoading = true }, finishDownload () { this.exportLoading = false }, buildExportFields () { const tableRef = this.$refs.labTable if (!tableRef || !Array.isArray(tableRef.columns)) { return {} } const fields = {} tableRef.columns.forEach(column => { const label = column && column.label ? String(column.label).trim() : '' const property = column && column.property ? String(column.property).trim() : '' if (!label || !property || label === '操作') { return } fields[label] = property }) return fields }, radioClick (field, value) { if (this.modalData[field] === value) { this.modalData[field] = '' } else { this.modalData[field] = value } }, addOrUpdateHandle (row) { if (!row && !this.authUpdate) { this.$message.warning('没有新增权限') return } if (row && !this.authUpdate && !this.authDataEntry) { this.$message.warning('没有编辑权限') return } this.modalFlag = true this.activeName = 'basicInfo' this.submitModalFlag = false this.rejectOpinion = '' this.testerFlag = false this.testerOptionList = [] this.testerDisplayList = [] this.testerSelectionCache = [] this.testerSearchData = { operatorId: '', operatorName: '' } this.resetLabApproverOptionState() this.plmLabAuthorityArr = [] this.nodeAuthorityLoaded = !row this.isEditMode = !!row this.showModalFlag = !!(row && (row.status === '已完成' || !this.authUpdate)) this.judgeCriteriaFileList = [] this.testSpecFileList = [] this.testReportFileList = []
if (row) { this.modalTitle = 'Lab 编辑' api.getLabDetail(row.site, row.referenceNo).then(({data}) => { if (data && data.code === 0) { const detail = data.data || {} this.modalData = this.buildDefaultModalData() this.modalData = { ...this.modalData, ...detail } this.fillDisplayFields(this.modalData, row || {}) this.$set(this.modalData, 'propertyItemList', (detail.propertyItemList || []).map(item => this.normalizePropertyItem(item))) this.$set(this.modalData, 'testerCodeList', this.normalizeTesterList(this.modalData.tester)) this.$set(this.modalData, 'testerList', this.modalData.testerCodeList || []) this.$set(this.modalData, 'labApproverCodeList', this.normalizeTesterList(this.modalData.labApprover)) this.$set(this.modalData, 'labApproverList', this.modalData.labApproverCodeList || []) this.$set(this.modalData, 'customerIdFlag', true) this.$set(this.modalData, 'projectIdFlag', true) this.$set(this.modalData, 'createBy2', '') this.$set(this.modalData, 'isReject', 'Y') this.$set(this.modalData, 'tpProcessControl', 'N') this.$set(this.modalData, 'csProcessControl', 'N') this.$set(this.modalData, 'testerName', this.modalData.testerName || this.modalData.tester || '') this.$set(this.modalData, 'labApproverName', this.modalData.labApproverName || this.modalData.labApprover || '') this.loadTesterOptions() this.loadLabApproverOptions() this.loadModalButtonCondition() this.loadNodeAuthority(this.modalData.site || row.site, this.modalData.stepId !== null && this.modalData.stepId !== undefined ? this.modalData.stepId : 10) this.refreshJudgeCriteriaFileList() this.refreshTestSpecFileList() this.refreshTestReportFileList() } }).catch(() => { this.loadNodeAuthority(row.site, row.stepId !== null && row.stepId !== undefined ? row.stepId : 10) this.judgeCriteriaFileList = [] this.testSpecFileList = [] this.testReportFileList = [] }) } else { this.modalTitle = 'Lab 新增' this.showModalFlag = false this.loadSiteOptions() const tempReferenceNo = 'TEMP-' + new Date().getTime() + '-' + Math.floor(Math.random() * 1000) const defaultData = this.buildDefaultModalData() const defaultSite = this.getDefaultSiteValue() this.modalData = { ...defaultData, site: defaultSite, referenceNo: tempReferenceNo, applicant: this.$store.state.user.name || '', applicantName: this.$store.state.user.userDisplay || this.$store.state.user.user_display || '', applicationDate: this.getCurrentDateString(), customerIdFlag: false, projectIdFlag: true, status: '草稿', stepId: 10, rejectFlag: 'N' } this.$set(this.modalData, 'propertyItemList', []) this.$set(this.modalData, 'testerCodeList', []) this.$set(this.modalData, 'testerList', []) this.$set(this.modalData, 'testerName', '') this.$set(this.modalData, 'labApproverCodeList', []) this.$set(this.modalData, 'labApproverList', []) this.$set(this.modalData, 'labApproverName', '') this.searchProjectData.site = defaultSite this.nodeAuthorityLoaded = true this.loadNodeAuthority(this.modalData.site, 10) } }, fillDisplayFields (target, source) { this.$set(target, 'applicantName', target.applicantName || source.applicantName || '') this.$set(target, 'customerName', target.customerName || source.customerName || '') this.$set(target, 'projectName', target.projectName || source.projectName || '') }, loadModalButtonCondition () { if (!this.modalData || !this.modalData.site || !this.modalData.referenceNo) { return } const params = { site: this.modalData.site, referenceNo: this.modalData.referenceNo } api.getLabButtonCondition(params).then(({data}) => { if (data && data.code === 0 && data.data) { this.$set(this.modalData, 'createBy2', data.data.createBy2 || '') this.$set(this.modalData, 'isReject', data.data.isReject || 'Y') this.$set(this.modalData, 'tpProcessControl', data.data.tpProcessControl || 'N') this.$set(this.modalData, 'csProcessControl', data.data.csProcessControl || 'N') } }) }, handleModalClose () { this.judgeCriteriaDialogVisible = false this.testSpecDialogVisible = false this.testReportDialogVisible = false this.testerFlag = false this.labApproverFlag = false this.modalFlag = false }, buildLabPayload (source) { const fields = [ 'site', 'referenceNo', 'applicant', 'applicationDate', 'applyDepartment', 'requestedDate', 'projectId', 'customerId', 'sampleName', 'sampleModel', 'sampleQty', 'testPurpose', 'productStage', 'testType', 'reportDocument', 'returnSample', 'applicationSurface', 'testLab', 'labApprover', 'attention', 'testStartDate', 'completedDate', 'unnormalSymptomAndDescription', 'testNumber', 'testerComments', 'departmentManagerComments', 'labComments', 'tester', 'propertyItemList', 'status', 'stepId', 'rejectFlag', 'rejectStepId', 'createDate', 'createBy', 'updateDate', 'updateBy' ] const payload = {} fields.forEach(field => { payload[field] = source[field] }) return payload }, dataFormSubmit () { if (!this.canSaveAction()) { this.$message.warning('当前状态不允许保存') return } this.syncTesterField() this.syncLabApproverField() this.syncPropertyItemList() const payload = this.buildLabPayload(this.modalData) const submitMethod = this.modalTitle === 'Lab 新增' ? api.saveLab : api.updateLab submitMethod(payload).then(({data}) => { if (data && data.code === 0) { this.$message.success('操作成功') this.modalFlag = false this.getDataList() } else { this.$message.error(data.msg || '操作失败') } }) }, agreeSubmit () { if (!this.canAgreeAction()) { this.$message.warning('当前状态不允许同意') return } this.$confirm('确认同意该申请单?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => { this.submitLab('Y') }) }, openRejectModal () { if (!this.canRejectAction()) { this.$message.warning('当前状态不允许驳回') return } this.rejectOpinion = '' this.submitModalFlag = true }, rejectSubmit () { if (!this.rejectOpinion || !this.rejectOpinion.trim()) { this.$message.warning('请填写驳回意见') return } this.submitLab('N') }, submitLab (nodeConclusion) { if (nodeConclusion === 'Y' && !this.canAgreeAction()) { this.$message.warning('当前状态不允许同意') return } if (nodeConclusion === 'N' && !this.canRejectAction()) { this.$message.warning('当前状态不允许驳回') return } if (!this.modalData.site || !this.modalData.referenceNo) { this.$message.warning('单据主键信息缺失,无法提交审批') return } this.syncTesterField() this.syncLabApproverField() this.syncPropertyItemList() if (!this.nodeAuthorityLoaded) { this.$message.warning('节点权限加载中,请稍后重试') return } if (!this.validateSubmitRequiredFields()) { return } this.submitLoading = true const payload = this.buildLabPayload(this.modalData) const params = { ...payload, site: this.modalData.site, referenceNo: this.modalData.referenceNo, nodeConclusion: nodeConclusion, rejectOpinion: nodeConclusion === 'N' ? this.rejectOpinion : '', menuId: this.menuId, documentNo: this.modalData.referenceNo } api.submitLab(params).then(({data}) => { if (data && data.code === 0) { this.$message.success(nodeConclusion === 'Y' ? '同意成功' : '驳回成功') this.submitModalFlag = false this.modalFlag = false this.getDataList() } else { this.$message.error(data.msg || '提交失败') } this.submitLoading = false }).catch(() => { this.submitLoading = false }) }, issueModal (row) { if (!this.authIssue) { this.$message.warning('没有下达权限') return } this.$confirm('确认下达该申请单?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => { const params = { site: row.site, referenceNo: row.referenceNo, menuId: this.menuId } api.issueLab(params).then(({data}) => { if (data && data.code === 0) { this.$message.success('下达成功') if (this.modalFlag && this.modalData.referenceNo === row.referenceNo) { this.modalData.status = '审批中' } this.getDataList() } else { this.$message.error(data.msg || '下达失败') } }) }) }, deleteHandle () { if (!this.authDelete) { this.$message.warning('没有删除权限') return } const selectedRows = (this.dataListSelections || []).filter(item => item && item.site && item.referenceNo) if (!selectedRows.length) { this.$message.warning('请先勾选要删除的单据') return } const nonDraftRows = selectedRows.filter(item => item.status !== '草稿') if (nonDraftRows.length) { const previewText = nonDraftRows.slice(0, 3).map(item => item.referenceNo).join('、') const suffix = nonDraftRows.length > 3 ? (' 等' + nonDraftRows.length + '条') : '' this.$message.warning('仅草稿状态的单据允许删除,当前勾选包含非草稿单据:' + previewText + suffix) return } this.$confirm('确认删除选中的' + selectedRows.length + '条Lab单据?删除后会同步删除属性和附件数据。', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => { const deleteTasks = selectedRows.map(item => { return api.deleteLab({ site: item.site, referenceNo: item.referenceNo }).then(({data}) => { if (data && data.code === 0) { return { success: true, site: item.site, referenceNo: item.referenceNo } } return { success: false, referenceNo: item.referenceNo, msg: (data && data.msg) || '删除失败' } }).catch(() => { return { success: false, referenceNo: item.referenceNo, msg: '删除失败' } }) }) Promise.all(deleteTasks).then(results => { const successRows = results.filter(item => item.success) const failRows = results.filter(item => !item.success) if (this.modalFlag && successRows.some(item => item.site === this.modalData.site && item.referenceNo === this.modalData.referenceNo)) { this.modalFlag = false } if (!failRows.length) { this.$message.success('删除成功,共' + successRows.length + '条') } else if (!successRows.length) { this.$message.error(failRows[0].msg || '删除失败') } else { this.$message.warning('已删除' + successRows.length + '条,失败' + failRows.length + '条') } this.getDataList() }) }).catch(() => {}) }, getBaseList (val, type) { this.tagNo = val this.tagNo1 = type this.$nextTick(() => { let strVal = '' let conSql = '' if (val === 102) { if (type === 1) { strVal = this.modalData.customerId conSql = ' order by Customer_no ' } } if (val === 103) { if (type === 1) { strVal = this.modalData.applicant } conSql = " and b.site = '" + this.modalData.site + "'" } this.$refs.baseList.init(val, strVal, conSql) }) }, getBaseData (val) { if (this.tagNo === 102 && this.tagNo1 === 1) { if (val.Customer_no === this.modalData.customerId) { return } if (this.modalData.projectIdFlag) { this.modalData.projectIdFlag = false } this.modalData.customerId = val.Customer_no this.modalData.customerName = val.Customer_desc this.modalData.projectId = '' this.modalData.projectName = '' } if (this.tagNo === 103 && this.tagNo1 === 1) { this.modalData.applicant = val.username this.modalData.applicantName = val.user_display } }, handleQueryCustomer () { if (!this.modalData.customerId) { this.modalData.customerName = '' this.modalData.projectId = '' this.modalData.projectName = '' this.modalData.projectIdFlag = true return } const params = { site: this.modalData.site, customerNo: this.modalData.customerId } queryCustomer(params).then(({data}) => { if (data && data.code === 0 && data.rows && data.rows.length === 1) { const customer = data.rows[0] this.modalData.customerName = customer.customerDesc || customer.Customer_desc || customer.customerName || '' this.modalData.projectIdFlag = !!this.modalData.customerIdFlag } else { this.modalData.customerName = '' this.modalData.projectId = '' this.modalData.projectName = '' this.modalData.projectIdFlag = true } }).catch(() => { this.modalData.customerName = '' this.modalData.projectId = '' this.modalData.projectName = '' this.modalData.projectIdFlag = true }) }, handleQueryProjectByCustomer () { if (!this.modalData.projectId) { this.modalData.projectName = '' return } const params = { site: this.modalData.site, projectId: this.modalData.projectId } if (this.modalData.customerId) { params.customerId = this.modalData.customerId } queryProjectByCustomer(params).then(({data}) => { if (data && data.code === 0 && data.rows && data.rows.length === 1) { const project = data.rows[0] this.modalData.projectName = project.projectName || project.Project_name || '' } else { this.modalData.projectName = '' } }).catch(() => { this.modalData.projectName = '' }) }, projectClickRow (row) { this.modalData.projectId = row.projectId this.modalData.projectName = row.projectName if (!this.modalData.customerId) { this.modalData.customerId = row.customerId this.modalData.customerName = row.customerName } this.chooseProjectListFlag = false }, searchProjectInfoList () { this.projectList = [] if (this.modalData.customerId && this.modalData.customerId !== '') { this.searchProjectData.customerId = this.modalData.customerId } else { this.searchProjectData.customerId = undefined } this.searchProjectData.site = this.modalData.site searchProjectInfoList(this.searchProjectData).then(({data}) => { if (data && data.code === 0) { this.projectList = data.rows || [] } else { this.projectList = [] } }).catch(() => { this.$message.error('查询项目信息失败') }) }, closeProjectInfoDialog () { if (this.$refs.closeProjectInfoForm) { this.$refs.closeProjectInfoForm.resetFields() } this.searchProjectData = { site: this.modalData.site || this.$store.state.user.site, projectId: undefined, projectName: undefined, customerId: undefined } }, applicantBlur (tagNo) { if (this.modalData.applicant != null && this.modalData.applicant !== '') { const tempData = { tagno: tagNo, conditionSql: " and a.username = '" + this.modalData.applicant + "'" + " and b.site = '" + this.modalData.site + "'" } verifyData(tempData).then(({data}) => { if (data && data.code === 0 && data.baseListData.length > 0) { this.modalData.applicant = data.baseListData[0].username this.modalData.applicantName = data.baseListData[0].user_display return } this.modalData.applicantName = '' }) } else { this.modalData.applicantName = '' } } }}</script>
<style scoped>/deep/ .customer-tab .el-tabs__content { padding: 0 !important;}
.mod-config /deep/ .el-tabs--border-card > .el-tabs__content { padding-top: 8px;}
.judge-criteria-label { color: #409EFF; text-decoration: underline; cursor: pointer; font-weight: 600;}
.judge-criteria-box { width: 772px; min-height: 38px; border: 1px solid #DCDFE6; border-radius: 4px; padding: 8px 10px; box-sizing: border-box; cursor: pointer; background: #fff;}
.judge-criteria-placeholder { color: #C0C4CC;}</style>
|