| | |
| | | <template> |
| | | <!-- 7.7质量监控计划--> |
| | | <div class="app-container"> |
| | | <div class="table-card"> |
| | | <div style="display: flex;justify-content: space-between"> |
| | | <div style="display: flex;"> |
| | | <div style="margin-bottom: 18px;margin-right: 10px;display: flex;align-items: center;line-height: 32px;"> |
| | | <span style="width: 88px;font-size: 14px;font-weight: 700;color: var(--lims-text-2);">计划名称</span> |
| | | <el-input size="small" placeholder="请输入" clearable v-model="yearForm.monitorName" |
| | | @keyup.enter="getYearPlanList"></el-input> |
| | | </div> |
| | | <div style="line-height: 30px;"> |
| | | <el-button type="primary" size="small" @click="getYearPlanList">查询</el-button> |
| | | <el-button size="small" @click="clearYear">重置</el-button> |
| | | </div> |
| | | <section v-if="pageMode === 'list'" class="plan-list-card"> |
| | | <div class="plan-list-toolbar"> |
| | | <div class="plan-list-filters"> |
| | | <span class="annual-plan-label">计划年度</span> |
| | | <el-date-picker v-model="selectedYear" type="year" value-format="YYYY" format="YYYY年" :clearable="false" |
| | | size="small" style="width: 130px" @change="handleYearChange" /> |
| | | <span class="filter-label">计划名称</span> |
| | | <el-input v-model="yearForm.monitorName" clearable placeholder="请输入" size="small" style="width: 220px" |
| | | @keyup.enter="getYearPlanList" /> |
| | | <el-button type="primary" size="small" @click="getYearPlanList">查询</el-button> |
| | | <el-button size="small" @click="clearYear">重置</el-button> |
| | | </div> |
| | | <div style="line-height: 30px;"> |
| | | <el-button size="small" type="primary" @click="leadInto">导入</el-button> |
| | | <div class="plan-list-actions"> |
| | | <el-button size="small" @click="leadInto">导入</el-button> |
| | | <el-button type="primary" size="small" @click="openCreatePlan">新建年度计划</el-button> |
| | | </div> |
| | | </div> |
| | | <lims-table :tableData="yearTableData" :column="yearColumnData" :page="yearPage" :tableLoading="yearLoading" |
| | | :height="'calc(100vh - 34em)'" @pagination="pagination" :rowClick="rowClick" key="yearTableData"></lims-table> |
| | | <lims-table :tableData="yearTableData" :column="yearColumnData" :page="yearPage" |
| | | :tableLoading="yearLoading" :height="'calc(100vh - 11em)'" @pagination="pagination" key="yearTableData"> |
| | | <template #planActions="{ row }"> |
| | | <div class="detail-actions"> |
| | | <el-button link type="primary" size="small" @click="openPlan(row)">查看计划</el-button> |
| | | <el-button v-if="canReviewRow(row)" link type="primary" size="small" @click="examinePlan(row)">审核</el-button> |
| | | <el-button v-if="canApproveRow(row)" link type="primary" size="small" @click="approvalPlan(row)">批准</el-button> |
| | | <el-dropdown trigger="click" @command="command => handlePlanCommand(command, row)"> |
| | | <el-button link type="primary" size="small">更多⌄</el-button> |
| | | <template #dropdown> |
| | | <el-dropdown-menu> |
| | | <el-dropdown-item command="export" :disabled="row.ratifyStatus !== 1">导出年度计划</el-dropdown-item> |
| | | <el-dropdown-item command="delete" divided :disabled="!canDeleteRow(row)">删除</el-dropdown-item> |
| | | </el-dropdown-menu> |
| | | </template> |
| | | </el-dropdown> |
| | | </div> |
| | | </template> |
| | | </lims-table> |
| | | </section> |
| | | |
| | | <template v-else> |
| | | <div class="annual-plan-header"> |
| | | <div class="annual-plan-main"> |
| | | <el-button link type="primary" size="small" @click="backToPlanList">← 返回年度计划</el-button> |
| | | <span class="annual-plan-label">{{ selectedYear }}年度</span> |
| | | <template v-if="currentPlan"> |
| | | <strong>{{ currentPlan.monitorName }}</strong> |
| | | <el-tag :type="planStatusType">{{ planStatusText }}</el-tag> |
| | | <span>编制:{{ currentPlan.writeName || '-' }} {{ formatDate(currentPlan.writeTime) }}</span> |
| | | <span>审核:{{ currentPlan.examineName || '-' }}</span> |
| | | <span>批准:{{ currentPlan.ratifyName || '-' }}</span> |
| | | </template> |
| | | <el-tag v-else type="info">该年度尚未建立计划</el-tag> |
| | | </div> |
| | | <div class="annual-plan-actions"> |
| | | <el-button v-if="canEditPlan" type="primary" size="small" @click="submitPlan">提交审核</el-button> |
| | | <el-button v-if="canReviewPlan" type="primary" size="small" @click="examinePlan(currentPlan)">审核</el-button> |
| | | <el-button v-if="canApprovePlan" type="primary" size="small" @click="approvalPlan(currentPlan)">批准</el-button> |
| | | <el-button size="small" @click="leadInto">导入</el-button> |
| | | <el-button v-if="currentPlan" size="small" :disabled="currentPlan.ratifyStatus !== 1" @click="handleDown(currentPlan)">导出年度计划</el-button> |
| | | </div> |
| | | </div> |
| | | <div style="margin-top: 20px"> |
| | | <div style="display: flex;justify-content: space-between"> |
| | | <div class="plan-detail-card"> |
| | | <div class="plan-detail-toolbar"> |
| | | <div style="display: flex;"> |
| | | <span class="section-title">质控项目</span> |
| | | <div style="margin-bottom: 18px;margin-right: 10px;display: flex;align-items: center;line-height: 32px;"> |
| | | <span style="width: 88px;font-size: 14px;font-weight: 700;color: var(--lims-text-2);">监控目的</span> |
| | | <el-input v-model="yearDetailForm.monitorPurpose" placeholder="请输入" size="small" |
| | | <span style="width: 88px;font-size: 14px;font-weight: 700;color: var(--lims-text-2);">质控项目</span> |
| | | <el-input v-model="yearDetailForm.monitorProject" placeholder="请输入" size="small" |
| | | @keyup.enter="getYearDetailPlanList"></el-input> |
| | | </div> |
| | | <div style="margin-bottom: 18px;margin-right: 10px;display: flex;align-items: center;line-height: 32px;"> |
| | | <span style="width: 88px;font-size: 14px;font-weight: 700;color: var(--lims-text-2);">监控项目</span> |
| | | <el-input v-model="yearDetailForm.monitorProject" placeholder="请输入" size="small" |
| | | @keyup.enter="getYearDetailPlanList"></el-input> |
| | | <span style="width: 70px;font-size: 14px;font-weight: 700;color: var(--lims-text-2);">负责人</span> |
| | | <el-select v-model="yearDetailForm.responsibleUserId" clearable filterable size="small" style="width: 160px"> |
| | | <el-option v-for="item in responsibleOptions" :key="item.id" :label="item.name" :value="item.id" /> |
| | | </el-select> |
| | | </div> |
| | | <div style="line-height: 30px;"> |
| | | <el-button type="primary" size="small" @click="getYearDetailPlanList">查询</el-button> |
| | |
| | | </div> |
| | | </div> |
| | | <div style="line-height: 30px;"> |
| | | <el-button size="small" type="primary" @click="exportSignatureTemplate">导出签名模板</el-button> |
| | | <el-button size="small" type="primary" @click="showDialog('add')">新增</el-button> |
| | | <!-- <el-button size="small" type="primary" @click="exportSignatureTemplate">导出签名模板</el-button>--> |
| | | <el-button size="small" type="primary" :disabled="!canEditPlan" @click="showDialog('add')">新增质控项目</el-button> |
| | | </div> |
| | | </div> |
| | | <lims-table :tableData="yearDetailTableData" :column="yearDetailColumnData" :page="yearDetailPage" |
| | | :tableLoading="yearDetailLoading" :height="'calc(100vh - 34em)'" @pagination="pagination1" ref="yearDetailTableData" |
| | | key="yearDetailTableData"></lims-table> |
| | | :tableLoading="yearDetailLoading" :height="'calc(100vh - 15em)'" @pagination="pagination1" ref="yearDetailTableData" |
| | | key="yearDetailTableData"> |
| | | <template #detailActions="{ row }"> |
| | | <div class="detail-actions"> |
| | | <el-button link type="primary" size="small" :disabled="!canEditPlan || !!row.inspectionTaskId" |
| | | @click="showDialog('edit', row)">编辑</el-button> |
| | | |
| | | <el-button v-if="row.itemKind !== 'INSPECTION'" link type="primary" size="small" |
| | | @click="carryOut(row)">实施</el-button> |
| | | <el-button v-else-if="!row.inspectionTaskId" link type="primary" size="small" |
| | | :disabled="row.planRatifyStatus !== 1" @click="dispatchTask(row)">下发任务</el-button> |
| | | <el-button v-else link type="primary" size="small" @click="evaluate(row)"> |
| | | {{ row.inspectionTaskState === 5 ? '评价记录' : '评价要求' }} |
| | | </el-button> |
| | | |
| | | <el-dropdown trigger="click" @command="command => handleDetailCommand(command, row)"> |
| | | <el-button link type="primary" size="small">更多⌄</el-button> |
| | | <template #dropdown> |
| | | <el-dropdown-menu> |
| | | <el-dropdown-item v-if="row.itemKind !== 'INSPECTION'" command="complete">完成报告</el-dropdown-item> |
| | | <el-dropdown-item v-if="row.itemKind !== 'INSPECTION'" command="evaluate">评价</el-dropdown-item> |
| | | <el-dropdown-item v-if="row.itemKind === 'INSPECTION' && !row.inspectionTaskId" command="requirement">评价要求</el-dropdown-item> |
| | | <el-dropdown-item v-if="row.itemKind === 'INSPECTION' && row.inspectionTaskId" command="cancel" |
| | | :disabled="row.inspectionTaskOrderState !== 1 || row.inspectionTaskState !== 0">取消任务</el-dropdown-item> |
| | | <el-dropdown-item command="attachment">附件上传</el-dropdown-item> |
| | | <el-dropdown-item command="export">导出</el-dropdown-item> |
| | | <el-dropdown-item command="delete" divided |
| | | :disabled="!canEditPlan || !!row.inspectionTaskId">删除</el-dropdown-item> |
| | | </el-dropdown-menu> |
| | | </template> |
| | | </el-dropdown> |
| | | </div> |
| | | </template> |
| | | </lims-table> |
| | | </div> |
| | | </template> |
| | | <el-dialog v-model="createPlanDialog" title="新建年度质量控制计划" width="520px"> |
| | | <el-form :model="planForm" label-width="90px"> |
| | | <el-form-item label="年度"> |
| | | <el-date-picker v-model="planForm.monitorYear" type="year" value-format="YYYY" format="YYYY年" |
| | | :clearable="false" style="width: 100%" placeholder="请选择年度" /> |
| | | </el-form-item> |
| | | <el-form-item label="计划名称"><el-input v-model="planForm.monitorName" /></el-form-item> |
| | | <el-form-item label="审核人"> |
| | | <el-select v-model="planForm.examineUserId" filterable style="width:100%"> |
| | | <el-option v-for="item in responsibleOptions" :key="item.id" :label="item.name" :value="item.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button @click="createPlanDialog=false">取消</el-button> |
| | | <el-button type="primary" :loading="createPlanLoading" @click="createPlan">确定</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | <!--新增修改弹框--> |
| | | <detail-form-dialog v-if="formDia" ref="formDia" :qualityMonitorId="qualityMonitorId" |
| | | @closeDia="closeDia"></detail-form-dialog> |
| | |
| | | @closeCarryOutDia="closeCarryOutDia"></carry-out-dialog> |
| | | <!--评价流程弹框--> |
| | | <evaluate-dialog v-if="evaluateDialog" ref="evaluateDialog" @closeEvaDia="closeEvaDia"></evaluate-dialog> |
| | | <inspection-evaluation-dialog v-if="inspectionEvaluateDialog" ref="inspectionEvaluateDialog" |
| | | @close="closeInspectionEvaluateDialog" /> |
| | | <el-dialog v-model="examineDialog" title="审核" width="30%" @close="closeExamineDia"> |
| | | <span> |
| | | 审核备注: |
| | |
| | | |
| | | <script> |
| | | import DetailFormDialog from './components/detailFormDialog.vue'; |
| | | import InspectionEvaluationDialog from './components/inspectionEvaluationDialog.vue'; |
| | | import CarryOutDialog from './components/carryOutDialog.vue'; |
| | | import EvaluateDialog from './components/evaluateDialog.vue'; |
| | | import filePreview from "@/components/Preview/filePreview.vue"; |
| | | import limsTable from "@/components/Table/lims-table.vue"; |
| | | import { |
| | | createAnnualPlan, getAnnualPlan, submitAnnualPlan, |
| | | delQualityMonitorDetail, |
| | | delQualitySupervise, |
| | | examineQualityMonitor, exportQualityMonitorDetail, exportQualityMonitorEvaluate, exportQualityMonitorRatify, |
| | | pageQualityMonitor, pageQualityMonitorDetail, ratifyFinishReport, |
| | | ratifyQualityMonitor |
| | | } from "@/api/cnas/process/ensureResults/qualityMonitor"; |
| | | import { dispatchInspectionTask, cancelInspectionTask } from "@/api/cnas/process/ensureResults/qualityMonitor"; |
| | | import { selectUserCondition } from "@/api/performance/class"; |
| | | import { mapGetters } from "@/utils/store-compat"; |
| | | import ViewRecord from "./components/ViewRecord.vue"; |
| | |
| | | export default { |
| | | name: 'EnsureResultsValidity', |
| | | // import 引入的组件需要注入到对象中才能使用 |
| | | components: {ViewRecord, limsTable, filePreview, EvaluateDialog, CarryOutDialog, DetailFormDialog }, |
| | | components: {ViewRecord, limsTable, filePreview, EvaluateDialog, CarryOutDialog, DetailFormDialog, InspectionEvaluationDialog }, |
| | | data() { |
| | | // 这里存放数据 |
| | | return { |
| | | ViewRecord: false, |
| | | inspectionEvaluateDialog: false, |
| | | pageMode: 'list', |
| | | selectedYear: String(new Date().getFullYear()), |
| | | currentPlan: null, |
| | | selectedPlanId: null, |
| | | createPlanDialog: false, |
| | | createPlanLoading: false, |
| | | planForm: { monitorYear: String(new Date().getFullYear()), monitorName: '', examineUserId: null }, |
| | | examineUserId: '', |
| | | responsibleOptions: [], |
| | | yearForm: { |
| | |
| | | { |
| | | label: '计划名称', |
| | | prop: 'monitorName', |
| | | width: '150px' |
| | | minWidth: '220px' |
| | | }, { |
| | | label: '计划年度', |
| | | prop: 'monitorYear', |
| | | width: '100px' |
| | | }, { |
| | | dataType: 'tag', |
| | | label: '计划状态', |
| | | prop: 'workflowStatus', |
| | | width: '110px', |
| | | formatData: (value, row) => this.planWorkflowText(value), |
| | | formatType: value => this.planWorkflowType(value) |
| | | }, { |
| | | label: '编制人', |
| | | prop: 'writeName', |
| | | width: '100' |
| | | minWidth: '100px' |
| | | }, { |
| | | label: '编制日期', |
| | | prop: 'writeTime', |
| | | width: '160' |
| | | }, { |
| | | dataType: 'tag', |
| | | label: '审核状态', |
| | | prop: 'examineStatus', |
| | | width: '100', |
| | | formatData: (params) => { |
| | | if (params === 0) { |
| | | return '不通过'; |
| | | } else if (params === 1) { |
| | | return '通过'; |
| | | } else { |
| | | return null; |
| | | } |
| | | }, |
| | | formatType: (params) => { |
| | | if (params === 0) { |
| | | return 'danger'; |
| | | } else if (params === 1) { |
| | | return 'success'; |
| | | } else { |
| | | return null; |
| | | } |
| | | } |
| | | }, { |
| | | label: '审核内容', |
| | | prop: 'examineRemark', |
| | | width: '100' |
| | | minWidth: '150px', |
| | | formatData: value => this.formatDate(value) |
| | | }, { |
| | | label: '审核人', |
| | | prop: 'examineName', |
| | | width: '100' |
| | | minWidth: '100px' |
| | | }, { |
| | | label: '审核日期', |
| | | prop: 'examineTime', |
| | | width: '160' |
| | | }, { |
| | | dataType: 'tag', |
| | | label: '批准状态', |
| | | prop: 'ratifyStatus', |
| | | width: '100', |
| | | formatData: (params) => { |
| | | if (params === 0) { |
| | | return '不批准'; |
| | | } else if (params === 1) { |
| | | return '批准'; |
| | | } else { |
| | | return null; |
| | | } |
| | | }, |
| | | formatType: (params) => { |
| | | if (params === 0) { |
| | | return 'danger'; |
| | | } else if (params === 1) { |
| | | return 'success'; |
| | | } else { |
| | | return null; |
| | | } |
| | | } |
| | | }, { |
| | | label: '批准内容', |
| | | prop: 'ratifyRemark', |
| | | width: '100' |
| | | minWidth: '150px', |
| | | formatData: value => this.formatDate(value) |
| | | }, { |
| | | label: '批准人', |
| | | prop: 'ratifyName', |
| | | width: '100' |
| | | minWidth: '100px' |
| | | }, { |
| | | label: '批准日期', |
| | | prop: 'ratifyTime', |
| | | width: '160' |
| | | minWidth: '150px', |
| | | formatData: value => this.formatDate(value) |
| | | }, { |
| | | dataType: 'action', |
| | | dataType: 'slot', |
| | | slot: 'planActions', |
| | | label: '操作', |
| | | fixed: 'right', |
| | | operation: [ |
| | | { |
| | | name: '审核', |
| | | type: 'text', |
| | | disabled: (row) => { |
| | | if (row.examineStatus === 1 || this.userId != row.examineUserId) { |
| | | return true |
| | | } else { |
| | | return false |
| | | } |
| | | }, |
| | | clickFun: (row) => { |
| | | this.examinePlan(row) |
| | | } |
| | | }, |
| | | { |
| | | name: '批准', |
| | | type: 'text', |
| | | disabled: (row) => { |
| | | if (row.ratifyStatus === 1 || row.examineStatus !== 1 || this.userId != row.ratifyUserId) { |
| | | return true |
| | | } else { |
| | | return false |
| | | } |
| | | }, |
| | | clickFun: (row) => { |
| | | this.approvalPlan(row) |
| | | } |
| | | }, |
| | | { |
| | | name: '导出', |
| | | type: 'text', |
| | | clickFun: (row) => { |
| | | this.handleDown(row) |
| | | }, |
| | | disabled: (row) => { |
| | | if (row.ratifyStatus !== 1) { |
| | | return true |
| | | } else { |
| | | return false |
| | | } |
| | | }, |
| | | }, |
| | | { |
| | | name: '删除', |
| | | type: 'text', |
| | | color: 'var(--el-color-danger)', |
| | | clickFun: (row) => { |
| | | this.delPlan(row) |
| | | }, |
| | | disabled: (row) => { |
| | | if (row.examineStatus === 1) { |
| | | return true; |
| | | } else { |
| | | return false; |
| | | } |
| | | }, |
| | | } |
| | | ] |
| | | width: '220px' |
| | | }], |
| | | yearTableData: [], // 年表 |
| | | yearLoading: false, |
| | | yearDetailForm: { |
| | | monitorPurpose: '', |
| | | monitorProject: '', |
| | | responsibleUserId: null, |
| | | }, |
| | | yearDetailColumnData: [ |
| | | { |
| | | label: '监控目的', |
| | | prop: 'monitorPurpose', |
| | | width: '150px', |
| | | showOverflowTooltip: true, |
| | | }, { |
| | | label: '计划开展时间', |
| | | prop: 'plannedTime', |
| | | width: '150px' |
| | | }, { |
| | | label: '监控项目', |
| | | label: '质控项目', |
| | | prop: 'monitorProject', |
| | | width: '150px' |
| | | minWidth: '140px' |
| | | }, { |
| | | label: '参加单位(人员)', |
| | | prop: 'participant', |
| | | width: '190px' |
| | | label: '技术标准', |
| | | prop: 'technicalStandardText', |
| | | minWidth: '220px' |
| | | }, { |
| | | label: '预算(元)', |
| | | prop: 'budget', |
| | | width: '150px' |
| | | }, { |
| | | label: '组织人员', |
| | | prop: 'organization', |
| | | width: '150px' |
| | | }, { |
| | | label: '监控方式', |
| | | label: '质控方式', |
| | | prop: 'monitorWay', |
| | | width: '150px' |
| | | },{ |
| | | dataType: 'tag', |
| | | label: '实施状态', |
| | | prop: 'detailsRatifyStatus', |
| | | width: '100', |
| | | formatData: (params) => { |
| | | if (params === 0) { |
| | | return '未开始'; |
| | | } else if (params === 1) { |
| | | return '待评价'; |
| | | } else if (params === 2) { |
| | | return '不批准'; |
| | | } else if (params === 3) { |
| | | return '已批准'; |
| | | } else { |
| | | return null; |
| | | } |
| | | }, |
| | | formatType: (params) => { |
| | | if (params === 0) { |
| | | return ''; |
| | | } else if (params === 1) { |
| | | return 'warning'; |
| | | } else if (params === 2) { |
| | | return 'danger'; |
| | | } else if (params === 3) { |
| | | return 'success'; |
| | | } else { |
| | | return null; |
| | | } |
| | | } |
| | | },{ |
| | | dataType: 'tag', |
| | | label: '报告状态', |
| | | prop: 'reportStatus', |
| | | width: '100', |
| | | formatData: (params) => { |
| | | if (params === 0) { |
| | | return '未开始'; |
| | | } else if (params === 1) { |
| | | return '待评价'; |
| | | } else if (params === 2) { |
| | | return '不批准'; |
| | | } else if (params === 3) { |
| | | return '已批准'; |
| | | } else { |
| | | return null; |
| | | } |
| | | }, |
| | | formatType: (params) => { |
| | | if (params === 0) { |
| | | return ''; |
| | | } else if (params === 1) { |
| | | return 'warning'; |
| | | } else if (params === 2) { |
| | | return 'danger'; |
| | | } else if (params === 3) { |
| | | return 'success'; |
| | | } else { |
| | | return null; |
| | | } |
| | | } |
| | | minWidth: '120px' |
| | | }, { |
| | | label: '完成时限', |
| | | prop: 'completionMonth', |
| | | width: '110px', |
| | | formatData: value => value ? value.replace('-', '.') : '' |
| | | }, { |
| | | label: '负责人', |
| | | prop: 'responsibleName', |
| | | minWidth: '100px' |
| | | }, { |
| | | label: '评价人', |
| | | prop: 'evaluatorName', |
| | | minWidth: '100px' |
| | | }, { |
| | | label: '事项类别', prop: 'itemKind', width: '100px', |
| | | formatData: value => value === 'INSPECTION' ? '检测类' : '非检测类' |
| | | }, { |
| | | label: '监控任务编号', prop: 'inspectionTaskCode', minWidth: '150px' |
| | | }, { |
| | | label: '任务状态', prop: 'inspectionTaskState', width: '100px', |
| | | formatData: value => this.inspectionTaskStatus(value) |
| | | },{ |
| | | dataType: 'tag', |
| | | label: '评价状态', |
| | |
| | | } |
| | | } |
| | | }, { |
| | | dataType: 'action', |
| | | dataType: 'slot', |
| | | slot: 'detailActions', |
| | | label: '操作', |
| | | fixed: 'right', |
| | | operation: [ |
| | | { |
| | | name: '编辑', |
| | | type: 'text', |
| | | clickFun: (row) => { |
| | | this.showDialog('edit', row) |
| | | } |
| | | }, |
| | | { |
| | | name: '实施', |
| | | type: 'text', |
| | | clickFun: (row) => { |
| | | this.carryOut(row) |
| | | } |
| | | }, |
| | | { |
| | | name: '完成报告', |
| | | type: 'text', |
| | | clickFun: (row) => { |
| | | this.record(row) |
| | | }, |
| | | }, |
| | | { |
| | | name: '评价', |
| | | type: 'text', |
| | | clickFun: (row) => { |
| | | this.evaluate(row) |
| | | } |
| | | }, |
| | | { |
| | | name: '附件上传', |
| | | type: 'text', |
| | | clickFun: (row) => { |
| | | this.viewTestRecord(row) |
| | | } |
| | | }, |
| | | { |
| | | name: '导出', |
| | | type: 'text', |
| | | clickFun: (row) => { |
| | | this.downLoadPost(row); |
| | | }, |
| | | }, |
| | | { |
| | | name: '删除', |
| | | type: 'text', |
| | | color: 'var(--el-color-danger)', |
| | | clickFun: (row) => { |
| | | this.delYearPlanDetail(row) |
| | | } |
| | | } |
| | | ] |
| | | width: '220px' |
| | | } |
| | | ], |
| | | yearDetailTableData: [], // 年明细表 |
| | |
| | | }; |
| | | }, |
| | | mounted() { |
| | | this.getUserList() |
| | | this.getYearPlanList() |
| | | }, |
| | | // 方法集合 |
| | | methods: { |
| | | // 查询年度计划表 |
| | | getYearPlanList() { |
| | | const entity = { |
| | | monitorName: this.yearForm.monitorName, |
| | | } |
| | | const page = this.yearPage |
| | | this.yearLoading = true |
| | | pageQualityMonitor({ ...entity, ...page }).then(res => { |
| | | this.yearLoading = false |
| | | this.yearTableData = res.data.records |
| | | this.yearPage.total = res.data.total |
| | | if (this.yearTableData.length > 0) { |
| | | this.rowClick(this.yearTableData[0]) |
| | | } |
| | | }).catch(err => { |
| | | console.log('err---', err); |
| | | const entity = { |
| | | monitorYear: this.selectedYear, |
| | | monitorName: this.yearForm.monitorName |
| | | } |
| | | return pageQualityMonitor({ ...entity, ...this.yearPage }).then(res => { |
| | | this.yearTableData = res.data?.records || [] |
| | | this.yearPage.total = res.data?.total || 0 |
| | | }).finally(() => { |
| | | this.yearLoading = false |
| | | }) |
| | | }, |
| | | loadAnnualPlan() { |
| | | if (!this.selectedPlanId) return Promise.resolve() |
| | | return this.loadPlanVersion() |
| | | }, |
| | | loadPlanVersion() { |
| | | if (!this.selectedPlanId) return Promise.resolve() |
| | | return getAnnualPlan({ monitorYear: this.selectedYear, qualityMonitorId: this.selectedPlanId }).then(res => { |
| | | this.currentPlan = res.data || null |
| | | this.qualityMonitorId = this.currentPlan?.qualityMonitorId || '' |
| | | this.yearDetailPage.current = 1 |
| | | return this.getYearDetailPlanList() |
| | | }) |
| | | }, |
| | | openPlan(row, addFirstDetail = false) { |
| | | this.selectedYear = String(row.monitorYear || this.selectedYear) |
| | | this.selectedPlanId = row.qualityMonitorId |
| | | this.pageMode = 'detail' |
| | | return this.loadPlanVersion().then(() => { |
| | | if (addFirstDetail) this.showDialog('add') |
| | | }) |
| | | }, |
| | | backToPlanList() { |
| | | this.pageMode = 'list' |
| | | this.currentPlan = null |
| | | this.qualityMonitorId = '' |
| | | this.yearDetailForm = { monitorProject: '', responsibleUserId: null } |
| | | this.getYearPlanList() |
| | | }, |
| | | handleYearChange() { |
| | | this.yearPage.current = 1 |
| | | this.getYearPlanList() |
| | | }, |
| | | openCreatePlan() { |
| | | this.planForm = { |
| | | monitorYear: String(new Date().getFullYear()), |
| | | monitorName: '', |
| | | examineUserId: null |
| | | } |
| | | this.createPlanDialog = true |
| | | }, |
| | | createPlan() { |
| | | if (!this.planForm.monitorYear || !this.planForm.monitorName || !this.planForm.examineUserId) { |
| | | this.$message.warning('请选择年度、填写计划名称并选择审核人') |
| | | return |
| | | } |
| | | this.createPlanLoading = true |
| | | createAnnualPlan({ ...this.planForm }).then(res => { |
| | | this.createPlanDialog = false |
| | | this.selectedYear = String(res.data.monitorYear) |
| | | this.yearPage.current = 1 |
| | | this.$message.success('年度计划已创建,请填写第一个质控项目') |
| | | return this.getYearPlanList().then(() => this.openPlan(res.data, true)) |
| | | }).finally(() => { this.createPlanLoading = false }) |
| | | }, |
| | | submitPlan() { |
| | | this.$confirm('提交后质控项目将锁定,确认提交审核?', '提交审核').then(() => { |
| | | submitAnnualPlan(this.qualityMonitorId).then(() => { |
| | | this.$message.success('已提交审核') |
| | | this.loadPlanVersion() |
| | | this.getYearPlanList() |
| | | }) |
| | | }).catch(() => {}) |
| | | }, |
| | | clearYear() { |
| | | this.yearForm.monitorName = '' |
| | | this.yearPage.current = 1 |
| | | this.getYearPlanList() |
| | | }, |
| | | pagination({ page, limit }) { |
| | |
| | | pagination1({ page, limit }) { |
| | | this.yearDetailPage.current = page; |
| | | this.yearDetailPage.size = limit; |
| | | this.getYearPlanList(); |
| | | this.getYearDetailPlanList(); |
| | | }, |
| | | leadInto() { |
| | | this.uploadDia = true |
| | | this.planYear = this.selectedYear |
| | | this.getUserList() |
| | | }, |
| | | // 导入流程 |
| | |
| | | this.timer = setTimeout(() => { |
| | | this.uploadDia = false |
| | | this.fileList = [] |
| | | this.planYear = '' |
| | | this.planYear = this.selectedYear |
| | | this.examineUserId = '' |
| | | this.getYearPlanList() |
| | | }, 1000) |
| | |
| | | return; |
| | | } |
| | | if (!this.examineUserId) { |
| | | this.$message.warning('请选择批准人') |
| | | this.$message.warning('请选择审核人') |
| | | return; |
| | | } |
| | | this.$refs.upload.submit(); |
| | |
| | | closeExamineDia() { |
| | | this.examineDialog = false |
| | | this.examineInfo.examineRemark = '' |
| | | this.getYearPlanList() |
| | | this.refreshPlanData() |
| | | }, |
| | | // 批准 |
| | | approvalPlan(row) { |
| | |
| | | closeRatifyDia() { |
| | | this.ratifyDialog = false |
| | | this.ratifyInfo.ratifyRemark = '' |
| | | this.getYearPlanList() |
| | | this.refreshPlanData() |
| | | }, |
| | | refreshPlanData() { |
| | | return this.getYearPlanList().then(() => { |
| | | if (this.pageMode === 'detail' && this.selectedPlanId) { |
| | | return this.loadPlanVersion() |
| | | } |
| | | }) |
| | | }, |
| | | // 批准报告 |
| | | handleApproval(status) { |
| | |
| | | getYearDetailPlanList() { |
| | | const entity = { |
| | | qualityMonitorId: this.qualityMonitorId, |
| | | monitorPurpose: this.yearDetailForm.monitorPurpose, |
| | | monitorProject: this.yearDetailForm.monitorProject, |
| | | responsibleUserId: this.yearDetailForm.responsibleUserId, |
| | | } |
| | | const page = this.yearDetailPage |
| | | this.yearDetailLoading = true |
| | |
| | | this.yearDetailLoading = false |
| | | this.yearDetailTableData = res.data.records |
| | | this.yearDetailPage.total = res.data.total |
| | | this.$refs.yearDetailTableData.$refs.multipleTable.doLayout() |
| | | this.$nextTick(() => this.$refs.yearDetailTableData?.$refs?.multipleTable?.doLayout()) |
| | | }).catch(err => { |
| | | console.log('err---', err); |
| | | this.yearDetailLoading = false |
| | |
| | | // 重置明细表 |
| | | clearDetail() { |
| | | this.yearDetailForm = { |
| | | monitorPurpose: '', |
| | | monitorProject: '' |
| | | monitorProject: '', |
| | | responsibleUserId: null |
| | | } |
| | | this.getYearDetailPlanList() |
| | | }, |
| | |
| | | // end |
| | | // 打开评价弹框 |
| | | evaluate(row) { |
| | | if (row.itemKind === 'INSPECTION') { |
| | | this.inspectionEvaluateDialog = true |
| | | this.$nextTick(() => this.$refs.inspectionEvaluateDialog.open(row)) |
| | | return |
| | | } |
| | | this.evaluateDialog = true |
| | | this.$nextTick(() => { |
| | | this.$refs.evaluateDialog.openDia(row) |
| | |
| | | closeEvaDia() { |
| | | this.evaluateDialog = false |
| | | this.getYearDetailPlanList() |
| | | }, |
| | | closeInspectionEvaluateDialog() { |
| | | this.inspectionEvaluateDialog = false |
| | | this.getYearDetailPlanList() |
| | | }, |
| | | dispatchTask(row) { |
| | | this.$confirm(`确认下发“${row.monitorProject}”的质量监控检验任务?`, '下发任务').then(() => { |
| | | dispatchInspectionTask(row.qualityMonitorDetailsId).then(res => { |
| | | this.$message.success(`已下发监控任务:${res.data.entrustCode}`) |
| | | this.getYearDetailPlanList() |
| | | }) |
| | | }).catch(() => {}) |
| | | }, |
| | | cancelTask(row) { |
| | | this.$confirm(`确认取消监控任务“${row.inspectionTaskCode}”?已取消任务会保留历史记录。`, '取消任务').then(() => { |
| | | cancelInspectionTask(row.qualityMonitorDetailsId).then(() => { |
| | | this.$message.success('任务已取消') |
| | | this.getYearDetailPlanList() |
| | | }) |
| | | }).catch(() => {}) |
| | | }, |
| | | // 附件上传 |
| | | viewTestRecord (row) { |
| | |
| | | }, |
| | | // 打开年度明细新增、修改弹框 |
| | | showDialog(type, row) { |
| | | if (!this.qualityMonitorId) { |
| | | this.$message.warning('请先新建年度质量控制计划') |
| | | return |
| | | } |
| | | if (!this.canEditPlan) { |
| | | this.$message.warning('当前计划状态不能维护质控项目') |
| | | return |
| | | } |
| | | this.formDia = true |
| | | this.$nextTick(() => { |
| | | this.$refs.formDia.openDia(type, row) |
| | |
| | | link.target = '_blank'; |
| | | document.body.appendChild(link); |
| | | link.click(); |
| | | }, |
| | | formatDate(value) { |
| | | return value ? String(value).slice(0, 10) : '-' |
| | | }, |
| | | planWorkflowText(value) { |
| | | return ({ |
| | | DRAFT: '草稿', |
| | | PENDING_REVIEW: '待审核', |
| | | REVIEW_REJECTED: '审核退回', |
| | | PENDING_APPROVAL: '待批准', |
| | | APPROVAL_REJECTED: '批准退回', |
| | | APPROVED: '已批准' |
| | | })[value] || '历史计划' |
| | | }, |
| | | planWorkflowType(value) { |
| | | return ({ |
| | | DRAFT: 'info', |
| | | PENDING_REVIEW: 'warning', |
| | | REVIEW_REJECTED: 'danger', |
| | | PENDING_APPROVAL: 'warning', |
| | | APPROVAL_REJECTED: 'danger', |
| | | APPROVED: 'success' |
| | | })[value] || 'info' |
| | | }, |
| | | canReviewRow(row) { |
| | | return row.workflowStatus === 'PENDING_REVIEW' |
| | | && Number(this.userId) === Number(row.examineUserId) |
| | | }, |
| | | canApproveRow(row) { |
| | | return row.workflowStatus === 'PENDING_APPROVAL' |
| | | && Number(this.userId) === Number(row.ratifyUserId) |
| | | }, |
| | | canDeleteRow(row) { |
| | | return Number(this.userId) === Number(row.writeUserId) |
| | | && ['DRAFT', 'REVIEW_REJECTED', 'APPROVAL_REJECTED'].includes(row.workflowStatus || 'DRAFT') |
| | | }, |
| | | handlePlanCommand(command, row) { |
| | | if (command === 'export') this.handleDown(row) |
| | | if (command === 'delete') this.delPlan(row) |
| | | }, |
| | | inspectionTaskStatus(value) { |
| | | const map = { 0: '待检测', 1: '检测中', 2: '检测中', 3: '待复核', 4: '复核退回', 5: '待评价' } |
| | | return value === null || value === undefined ? '未下发' : (map[value] || '处理中') |
| | | }, |
| | | handleDetailCommand(command, row) { |
| | | const handlers = { |
| | | complete: () => this.record(row), |
| | | evaluate: () => this.evaluate(row), |
| | | requirement: () => this.evaluate(row), |
| | | cancel: () => this.cancelTask(row), |
| | | attachment: () => this.viewTestRecord(row), |
| | | export: () => this.downLoadPost(row), |
| | | delete: () => this.delYearPlanDetail(row) |
| | | } |
| | | handlers[command]?.() |
| | | } |
| | | }, |
| | | // 用于上传文件的信息 |
| | | computed: { |
| | | ...mapGetters(["userId", "nickName"]), |
| | | effectivePlanStatus() { |
| | | if (!this.currentPlan) return '' |
| | | if (this.currentPlan.workflowStatus) return this.currentPlan.workflowStatus |
| | | if (this.currentPlan.ratifyStatus === 1) return 'APPROVED' |
| | | if (this.currentPlan.ratifyStatus === 0) return 'APPROVAL_REJECTED' |
| | | if (this.currentPlan.examineStatus === 1) return 'PENDING_APPROVAL' |
| | | if (this.currentPlan.examineStatus === 0) return 'REVIEW_REJECTED' |
| | | return 'DRAFT' |
| | | }, |
| | | planStatusText() { |
| | | return ({DRAFT:'草稿',PENDING_REVIEW:'待审核',REVIEW_REJECTED:'审核退回',PENDING_APPROVAL:'待批准',APPROVAL_REJECTED:'批准退回',APPROVED:'已批准'})[this.effectivePlanStatus] || '历史计划' |
| | | }, |
| | | planStatusType() { |
| | | return ({DRAFT:'info',PENDING_REVIEW:'warning',REVIEW_REJECTED:'danger',PENDING_APPROVAL:'warning',APPROVAL_REJECTED:'danger',APPROVED:'success'})[this.effectivePlanStatus] || 'info' |
| | | }, |
| | | canEditPlan() { |
| | | return !!this.currentPlan && Number(this.userId) === Number(this.currentPlan.writeUserId) |
| | | && ['DRAFT','REVIEW_REJECTED','APPROVAL_REJECTED'].includes(this.effectivePlanStatus) |
| | | }, |
| | | canReviewPlan() { |
| | | return !!this.currentPlan && this.effectivePlanStatus === 'PENDING_REVIEW' |
| | | && Number(this.userId) === Number(this.currentPlan.examineUserId) |
| | | }, |
| | | canApprovePlan() { |
| | | return !!this.currentPlan && this.effectivePlanStatus === 'PENDING_APPROVAL' |
| | | && Number(this.userId) === Number(this.currentPlan.ratifyUserId) |
| | | }, |
| | | action() { |
| | | return this.javaApi + '/qualityMonitor/importQualityMonitor' |
| | | }, |
| | |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped></style> |
| | | <style scoped> |
| | | .plan-list-card { |
| | | min-width: 0; |
| | | padding: 14px 16px; |
| | | background: var(--lims-card-bg, var(--el-bg-color)); |
| | | border: 1px solid var(--el-border-color-light); |
| | | border-radius: 4px; |
| | | } |
| | | .plan-list-toolbar, |
| | | .plan-list-filters, |
| | | .plan-list-actions { |
| | | display: flex; |
| | | align-items: center; |
| | | flex-wrap: wrap; |
| | | gap: 10px; |
| | | } |
| | | .plan-list-toolbar { |
| | | justify-content: space-between; |
| | | margin-bottom: 14px; |
| | | } |
| | | .filter-label { |
| | | margin-left: 8px; |
| | | font-size: 14px; |
| | | font-weight: 700; |
| | | color: var(--lims-text-2); |
| | | white-space: nowrap; |
| | | } |
| | | .annual-plan-header { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | gap: 16px; |
| | | padding: 14px 16px; |
| | | margin-bottom: 16px; |
| | | background: var(--lims-card-bg, var(--el-bg-color)); |
| | | border: 1px solid var(--el-border-color-light); |
| | | border-radius: 4px; |
| | | } |
| | | .annual-plan-main, .annual-plan-actions { |
| | | display: flex; |
| | | align-items: center; |
| | | flex-wrap: wrap; |
| | | gap: 10px; |
| | | } |
| | | .annual-plan-label { font-weight: 700; color: var(--lims-text-2); } |
| | | .plan-detail-card { |
| | | min-width: 0; |
| | | background: var(--lims-card-bg, var(--el-bg-color)); |
| | | } |
| | | .plan-detail-toolbar { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | flex-wrap: wrap; |
| | | gap: 10px; |
| | | } |
| | | .section-title { |
| | | display: inline-flex; |
| | | align-items: center; |
| | | margin-right: 18px; |
| | | font-size: 15px; |
| | | font-weight: 700; |
| | | color: var(--lims-text-1, var(--el-text-color-primary)); |
| | | white-space: nowrap; |
| | | } |
| | | .detail-actions { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | white-space: nowrap; |
| | | } |
| | | @media (max-width: 1200px) { |
| | | .annual-plan-header { |
| | | align-items: flex-start; |
| | | flex-direction: column; |
| | | } |
| | | .annual-plan-actions { |
| | | width: 100%; |
| | | } |
| | | } |
| | | </style> |