<template>
|
<div>
|
<el-dialog :close-on-click-modal="false" :close-on-press-escape="false"
|
v-model="formDia"
|
title="日常监督检查记录表"
|
width="70%" @close="closeRecordsDia">
|
<el-steps :active="currentStep" align-center finish-status="success">
|
<el-step title="实施"></el-step>
|
<el-step title="批准"></el-step>
|
</el-steps>
|
<div style="height: 470px;overflow-y: auto">
|
<table border="1" cellspacing="10" class="tables">
|
<tr>
|
<td class="td-title">
|
<p><span class="required-span">* </span>监督检测项目:</p>
|
</td>
|
<td colspan="2">
|
<el-input v-if="currentStep === 0" v-model="form.testItem"
|
placeholder="请输入内容"
|
size="small">
|
</el-input>
|
<span v-else class="td-info"> {{ form.testItem }}</span>
|
</td>
|
<td class="td-title">
|
<p><span class="required-span">* </span>监督检测日期:</p>
|
</td>
|
<td colspan="2">
|
<el-input v-if="currentStep === 0" v-model="form.testDate"
|
placeholder="请输入内容"
|
size="small">
|
</el-input>
|
<span v-else class="td-info"> {{ form.testDate }}</span>
|
</td>
|
</tr>
|
<tr>
|
<td class="td-title">
|
<p><span class="required-span">* </span>受监督人:</p>
|
</td>
|
<td colspan="2">
|
<el-select v-if="currentStep === 0" v-model="superviseeList" multiple filterable collapse-tags
|
placeholder="请选择" size="small" style="width: 100%">
|
<el-option v-for="item in personList" :key="item.value" :label="item.label"
|
:value="item.label"></el-option>
|
</el-select>
|
<span v-else class="td-info"> {{ form.testMember }}</span>
|
</td>
|
<td class="td-title">
|
<p><span class="required-span">* </span>监督员:</p>
|
</td>
|
<td colspan="2">
|
<el-select v-if="currentStep === 0" v-model="form.supervisor" placeholder="请选择" size="small" style="width: 100%">
|
<el-option v-for="item in recordUserList" :key="item.userId" :label="item.userName" :value="item.userName"></el-option>
|
</el-select>
|
<span v-else class="td-info"> {{ form.supervisor }}</span>
|
</td>
|
</tr>
|
<tr>
|
<td class="td-title">
|
<p>监督内容:</p>
|
</td>
|
<td colspan="5">
|
<template v-if="currentStep === 0">
|
<div v-for="(rowItems, rowIndex) in contentRows" :key="rowIndex" style="display: flex;">
|
<el-checkbox v-for="item in rowItems" :key="item" v-model="superviseContentList"
|
:value="item" style="flex: 1;">{{ item }}</el-checkbox>
|
</div>
|
</template>
|
<span v-else class="td-info"> {{ form.superviseContent }}</span>
|
</td>
|
</tr>
|
<tr>
|
<td class="td-title">
|
<p>监督方式:</p>
|
</td>
|
<td colspan="5">
|
<el-select v-if="currentStep === 0" v-model="superviseModeList" multiple filterable collapse-tags
|
placeholder="请选择监督方式(程序4.2.4)" size="small" style="width: 100%">
|
<el-option v-for="item in superviseModeItems" :key="item" :label="item" :value="item"></el-option>
|
</el-select>
|
<span v-else class="td-info"> {{ form.superviseMethod }}</span>
|
</td>
|
</tr>
|
<tr>
|
<td class="td-title">
|
<p><span class="required-span">* </span>监督记录:</p>
|
</td>
|
<td colspan="5">
|
<el-input v-if="currentStep === 0" v-model="form.superviseRecord"
|
:rows="4"
|
placeholder="请输入内容"
|
size="small"
|
type="textarea">
|
</el-input>
|
<span v-else class="td-info"> {{ form.superviseRecord }}</span>
|
</td>
|
</tr>
|
<tr>
|
<td class="td-title">
|
<p>存在问题:</p>
|
</td>
|
<td colspan="5">
|
<el-input v-if="currentStep === 0" v-model="form.problemDesc"
|
:rows="3"
|
placeholder="不符合问题描述,无则填“无”"
|
size="small"
|
type="textarea">
|
</el-input>
|
<span v-else class="td-info"> {{ form.problemDesc }}</span>
|
</td>
|
</tr>
|
<tr>
|
<td class="td-title">
|
<p>整改意见:</p>
|
</td>
|
<td colspan="5">
|
<el-input v-if="currentStep === 0" v-model="form.rectifyAdvice"
|
:rows="3"
|
placeholder="请输入内容"
|
size="small"
|
type="textarea">
|
</el-input>
|
<span v-else class="td-info"> {{ form.rectifyAdvice }}</span>
|
</td>
|
</tr>
|
<tr>
|
<td class="td-title">
|
<p>被监督人员确认意见:</p>
|
</td>
|
<td colspan="5">
|
<span v-if="form.confirmOpinion" class="td-info">{{ form.confirmOpinion }}</span>
|
<template v-else-if="canConfirm">
|
<el-input v-model="confirmOpinion" :rows="2" size="small" type="textarea"
|
placeholder="对监督记录真实性表示认可。"/>
|
<el-button :loading="confirming" size="small" type="primary" style="margin-top: 6px"
|
@click="confirmRecord">确 认</el-button>
|
</template>
|
<span v-else class="td-info">
|
{{ form.superviseDetailsRecordId ? '待被监督人员确认' : '监督员提交后由被监督人员确认' }}
|
</span>
|
</td>
|
</tr>
|
<tr>
|
<td v-if="currentStep === 0" class="td-title">
|
<p><span class="required-span">* </span>请选择下一步批准人:</p>
|
</td>
|
<td v-if="currentStep === 0" colspan="5">
|
<el-select v-model="form.ratifyUserId" clearable filterable
|
placeholder="请选择" size="small">
|
<el-option v-for="(item,i) in personList" :key="i" :label="item.label" :value="item.value">
|
</el-option>
|
</el-select>
|
</td>
|
<td v-if="currentStep === 1" class="td-title">
|
<p>批准负责人:</p>
|
</td>
|
<td v-if="currentStep === 1" class="td-info" colspan="5">
|
{{form.ratifyUserName}}
|
</td>
|
</tr>
|
<tr v-if="currentStep === 1 || currentStep === 2">
|
<td class="td-title">
|
<p><span class="required-span">* </span>审批结论:</p>
|
</td>
|
<td colspan="2">
|
<el-input v-if="currentStep === 1"
|
v-model="form.ratifyOpinion"
|
:rows="4"
|
placeholder="请输入内容"
|
size="small"
|
type="textarea">
|
</el-input>
|
<span v-if="currentStep === 2" class="td-info"> {{ form.ratifyOpinion }}</span>
|
</td>
|
<td class="td-title">
|
<p v-if="currentStep === 1">请选择是否符合:</p>
|
<p v-if="currentStep === 2">是否符合:</p>
|
</td>
|
<td colspan="2">
|
<el-radio-group v-if="currentStep === 1" v-model="form.isAccording">
|
<el-radio :value="0">不符合</el-radio>
|
<el-radio :value="1">符合</el-radio>
|
</el-radio-group>
|
<span v-if="currentStep === 2" class="td-info"> {{ form.isAccording === 0 ? '不符合' : '符合' }}</span>
|
</td>
|
</tr>
|
</table>
|
</div>
|
<template #footer><span class="dialog-footer">
|
<el-button @click="closeRecordsDia">取 消</el-button>
|
<el-button v-if="currentStep === 0 && canSubmitRecord" :loading="editLoad" type="primary" @click="handleEdit">提 交</el-button>
|
<el-button v-if="currentStep === 1 && userId == ratifyUserId" :loading="editLoad" @click="handleEdit(0)">不通过</el-button>
|
<el-button v-if="currentStep === 1 && userId == ratifyUserId" :loading="editLoad" type="primary" @click="handleEdit(1)">通
|
过</el-button>
|
</span></template>
|
</el-dialog>
|
</div>
|
</template>
|
|
<script>
|
import {
|
addSuperviseDetailRecord,
|
addSuperviseRecordOpinion, confirmSuperviseRecord, getRecordUser,
|
getSuperviseDetailRecord
|
} from "@/api/cnas/process/ensureResults/qualitySupervise";
|
import {selectUserCondition} from "@/api/business/inspectionTask";
|
import {mapGetters} from "@/utils/store-compat";
|
|
// 监督内容9项,与受控记录表 LMSY-CX29-JL02 的文字及横排顺序完全一致
|
const SUPERVISE_CONTENT_ITEMS = [
|
'人员持证及培训', '设施及环境条件', '检测方法',
|
'仪器设备管理', '测量溯源性', '标准物质管理',
|
'样品制备和处置', '检测数据处理', '结果报告结果'
|
]
|
// 监督方式,对应《质量监督程序》4.2.4
|
const SUPERVISE_MODE_ITEMS = [
|
'核查原始记录和报告',
|
'现场监督实际操作过程',
|
'与被监督对象交流',
|
'内部质量控制/外部质量评估',
|
'培训效果评价'
|
]
|
|
export default {
|
name: 'recordsDialog',
|
// import 引入的组件需要注入到对象中才能使用
|
components: {},
|
data() {
|
// 这里存放数据
|
return {
|
formDia: false,
|
form: {
|
superviseDetailsId: '',
|
superviseDetailsRecordId: '',
|
testMember: '',
|
supervisor: '',
|
superviseContent: '',
|
superviseRecord: '',
|
problemDesc: '',
|
rectifyAdvice: '',
|
testItem: '',
|
testDate: '',
|
ratifyUserId: '',
|
ratifyUserName: '',
|
ratifyOpinion: '',
|
isAccording: '',
|
isFinish: '',
|
superviseMethod: '',
|
confirmOpinion: '',
|
},
|
currentStep: 0,
|
editLoad: false,
|
personList: [],
|
recordUserList: [],
|
supervisedUserId: '',
|
ratifyUserId: '',
|
superviseeList: [],
|
superviseContentList: [],
|
superviseContentItems: SUPERVISE_CONTENT_ITEMS,
|
superviseModeItems: SUPERVISE_MODE_ITEMS,
|
superviseModeList: [],
|
confirmOpinion: '',
|
confirming: false,
|
};
|
},
|
computed: {
|
...mapGetters(["userId", "nickName"]),
|
// 记录已提交且尚未确认时,只有被监督人员本人可以确认(程序4.2.5)
|
canConfirm() {
|
if (!this.form.superviseDetailsRecordId || this.form.confirmOpinion) {
|
return false
|
}
|
const members = (this.form.testMember || '').split('、').map(item => item.trim()).filter(Boolean)
|
if (this.nickName && members.includes(this.nickName)) {
|
return true
|
}
|
// 兜底:计划明细中登记的被监督人员
|
return !!this.supervisedUserId && Number(this.supervisedUserId) === Number(this.userId)
|
},
|
contentRows() {
|
const rows = []
|
for (let i = 0; i < this.superviseContentItems.length; i += 3) {
|
rows.push(this.superviseContentItems.slice(i, i + 3))
|
}
|
return rows
|
},
|
canSubmitRecord() {
|
if (this.userId == this.supervisedUserId) {
|
return true
|
}
|
return this.recordUserList.some(item => item.userId == this.userId)
|
},
|
},
|
// 方法集合
|
methods: {
|
openDia(row) {
|
this.formDia = true
|
this.supervisedUserId = row.supervisedUserId
|
this.searchInfo(row)
|
this.getAuthorizedPerson()
|
},
|
// 查询监督计划详情记录流程信息
|
searchInfo (row) {
|
getSuperviseDetailRecord({superviseDetailsId: row.superviseDetailsId}).then(res => {
|
// 有superviseDetailsRecordId说明提交过记录
|
if (res.data.ratifyUserId) {
|
// 是否结束0:未结束, 1:已结束
|
if (res.data.isFinish != 1) {
|
this.currentStep = 1
|
} else if (res.data.isFinish == 1) {
|
this.currentStep = 2
|
}
|
} else {
|
this.currentStep = 0
|
}
|
this.form = res.data
|
this.form.superviseDetailsId = row.superviseDetailsId
|
this.ratifyUserId = res.data.ratifyUserId
|
this.superviseeList = this.form.testMember ? this.form.testMember.split('、').filter(i => i) : []
|
this.superviseContentList = this.form.superviseContent ? this.form.superviseContent.split('、').filter(i => i) : []
|
this.superviseModeList = this.form.superviseMethod ? this.form.superviseMethod.split('、').filter(i => i) : []
|
this.confirmOpinion = this.form.confirmOpinion || ''
|
this.getRecordUser()
|
}).catch(err => {
|
console.log('err---', err);
|
})
|
},
|
// 提交流程
|
handleEdit (isFinish) {
|
if (this.currentStep === 0) {
|
if (!this.form.testItem || !this.form.testDate || this.superviseeList.length === 0 || !this.form.supervisor) {
|
this.$message.warning('请填写完整')
|
return
|
}
|
if (!this.form.superviseRecord) {
|
this.$message.warning('请填写监督记录')
|
return
|
}
|
this.form.testMember = this.superviseeList.join('、')
|
this.form.superviseContent = this.superviseContentList.join('、')
|
this.form.superviseMethod = this.superviseModeList.join('、')
|
this.addInfo()
|
} else {
|
this.editInfo(isFinish)
|
}
|
},
|
// 提交记录
|
addInfo () {
|
this.editLoad = true
|
addSuperviseDetailRecord(this.form).then(res => {
|
this.editLoad = false
|
this.$message.success('操作成功')
|
this.closeRecordsDia()
|
}).catch(err => {
|
console.log('err---', err);
|
this.editLoad = false
|
})
|
},
|
// 提交批准
|
editInfo (isFinish) {
|
if (!this.form.ratifyOpinion) {
|
this.$message.warning('请填写审批意见')
|
return
|
}
|
if (this.form.isAccording !== 0 && this.form.isAccording !== 1) {
|
this.$message.warning('请选择是否符合')
|
return
|
}
|
this.editLoad = true
|
this.form.isFinish = isFinish
|
addSuperviseRecordOpinion(this.form).then(res => {
|
this.editLoad = false
|
this.$message.success('操作成功')
|
this.closeRecordsDia()
|
}).catch(err => {
|
console.log('err---', err);
|
this.editLoad = false
|
})
|
},
|
// 被监督人员确认监督记录(程序4.2.5)
|
confirmRecord () {
|
const opinion = (this.confirmOpinion || '').trim() || '对监督记录真实性表示认可。'
|
this.confirming = true
|
confirmSuperviseRecord({
|
superviseDetailsId: this.form.superviseDetailsId,
|
confirmOpinion: opinion
|
}).then(() => {
|
this.form.confirmOpinion = opinion
|
this.$message.success('已确认监督记录')
|
}).finally(() => {
|
this.confirming = false
|
})
|
},
|
// 关闭弹框
|
closeRecordsDia () {
|
this.formDia = false
|
this.$emit('closeRecordsDia')
|
},
|
getAuthorizedPerson() {
|
// 质量监督面向全实验室, 人员列表不按部门筛选
|
selectUserCondition({ type: 1 }).then((res) => {
|
let data = [];
|
(res.data || []).forEach((a) => {
|
data.push({
|
label: a.name,
|
value: a.id,
|
});
|
});
|
this.personList = data;
|
});
|
},
|
getRecordUser () {
|
getRecordUser({superviseDetailsId: this.form.superviseDetailsId}).then(res => {
|
this.recordUserList = res.data || []
|
// 计划已指定监督员但尚未产生记录时,默认反显第一位监督员;
|
// 后端只有在存在上月记录时才会自动带出监督员,首次填写会为空。
|
if (this.currentStep === 0 && !this.form.supervisor && this.recordUserList.length) {
|
this.form.supervisor = this.recordUserList[0].userName
|
}
|
})
|
},
|
}
|
};
|
</script>
|
|
<style scoped>
|
.tables {
|
table-layout: fixed;
|
width: 100%;
|
margin-top: 10px;
|
}
|
.td-title {
|
height: 40px;
|
text-align: center;
|
font-size: 14px;
|
word-wrap: break-word;
|
white-space: normal;
|
padding: 6px;
|
}
|
.td-info {
|
text-align: center;
|
font-size: 14px;
|
word-wrap: break-word;
|
white-space: normal;
|
}
|
.tables td {
|
height: 40px;
|
font-size: 14px;
|
word-wrap: break-word;
|
white-space: normal;
|
padding: 6px;
|
}
|
</style>
|