<!-- 标准装置状态维护 基本信息 -->
<script name="StandardStateMaintenanceBasic" lang="ts" setup>
import type { Ref } from 'vue'
import { ElLoading, ElMessage, ElMessageBox, formEmits } from 'element-plus'
import type { FormInstance, FormRules } from 'element-plus'
import dayjs from 'dayjs'
import type { IForm } from '../standardStateMaintenance-interface'
import selectStandardDialog from '../dialog/selectStandardDialog.vue'
import selectStandardEquipmentDialog from '../dialog/selectStandardEquipmentDialog.vue'
import SelectEquipmentDialog from '@/views/business/fieldTest/approve/dialog/selectEquipmentDialog.vue'
import type { IAccessory, Itech } from '@/views/equipement/info/book/book-interface'
import showPhoto from '@/components/showPhoto/index.vue'
import { UploadFile } from '@/api/file'
import type { deptType, dictType } from '@/global'
import type { IAddress } from '@/components/AddressSelect/address-interface'
import { getDictByCode } from '@/api/system/dict'
import { SCHEDULE } from '@/utils/scheduleDict'
import ApprovalDialog from '@/components/Approval/ApprovalDialog.vue'
import useUserStore from '@/store/modules/user'
import { getDeptTreeList } from '@/api/system/dept'
import { toTreeList } from '@/utils/structure'
import { getStaffList } from '@/api/resource/register'
import countries from '@/components/AddressSelect/country-code.json'
import { getInfo as getEquipmentDetail } from '@/api/equipment/info/book'
import { useCheckList } from '@/commonMethods/useCheckList'
import { useDoubleClickTableRow, useSetAllRowReadable } from '@/commonMethods/useSetAllRowReadable'
import { addStateMaintenance, failUpdateStateMaintenance, getInfo, submit, updateStateMaintenance } from '@/api/equipment/standardStateMaintenance/stateMaintenance'
const props = defineProps({
pageType: { // 页面类型 add新建 edit编辑 detail详情
type: String,
requre: true,
default: 'detail',
},
id: {
type: String,
requre: true,
},
approvalStatusName: { // 审批状态名称
type: String,
requre: true,
},
title: String, // 标题
approvalType: { // 1启封、2封存、3禁用、4报废
type: String,
default: '1',
},
formId: {
type: String,
default: '',
},
processId: {
type: String,
default: '',
},
})
const emits = defineEmits(['addSuccess', 'submitSuccess'])
const countryList = ref(countries) // 国家列表
const user = useUserStore() // 用户信息
const form = ref<IForm>({
applyNo: '', // 申请单编号
applyName: '', // 申请单名称
createUserId: '', // 申请人id
createUserName: '', // 申请人名称
createTime: '', // 申请时间
standardId: '', // 标准装置id
standardName: '', // 标准装置名称
standardNo: '', // 标准装置代码
deptId: '', // 标准所在部门id
deptName: '', // 标准所在部门名称
directorName: '', // 标准负责人
measureRange: '', // 测量范围
uncertainty: '', // 测量不确定度
applyIllustrate: '', // 申请说明
applyFile: '', // 申请附件
labCode: '', // 实验室代码
groupCode: '', // 组别代码
})
const ruleFormRef = ref() // 表单ref
const loading = ref(false) // loading
const infoId = ref('') // id
const rules = ref<FormRules>({ // 校验规则
standardNo: [{ required: true, message: '标准代码不能为空', trigger: ['blur', 'change'] }],
applyIllustrate: [{ required: true, message: `${props.title}申请说明不能为空`, trigger: ['blur', 'change'] }],
labCode: [{ required: true, message: '实验室代码不能为空', trigger: ['blur', 'change'] }],
groupCode: [{ required: true, message: '组别代码不能为空', trigger: ['blur', 'change'] }],
})
// -----------------------------------------字典--------------------------------------------------------------
const useDeptList = ref<deptType[]>([]) // 所属部门列表
const userList = ref<{ [key: string]: string }[]>([]) // 用户列表
const labCodeList = ref<dictType[]>([]) // 实验室代码
const groupCodeList = ref<dictType[]>([]) // 组别代码
function getDict() {
// 实验室代码
getDictByCode('bizLabCode').then((response) => {
labCodeList.value = response.data
})
// 组别代码
getDictByCode('bizGroupCode').then((response) => {
groupCodeList.value = response.data
})
// 获取部门列表
getDeptTreeList().then((res) => {
// 转成树结构
useDeptList.value = toTreeList(res.data, '0', true)
})
// 获取用户列表
getStaffList({ offset: 1, limit: 999999 }).then((res: any) => {
userList.value = res.data.rows
})
}
// ---------------------------------------选择标准代码-----------------------------------------
const selectStandardDialogRef = ref() // 选择标准代码组件ref
// 点击选择标准代码
const selectStandard = () => {
selectStandardDialogRef.value.initDialog()
}
// 选择好标准代码
const confirmSelectStandard = (val: any) => {
if (val && val.length) {
form.value.standardId = val[0].id // 标准装置id
form.value.standardName = val[0].standardName // 标准装置名称
form.value.standardNo = val[0].standardNo // 标准装置代码
form.value.deptId = val[0].deptId // 标准所在部门id
form.value.deptName = val[0].deptName // 标准所在部门名称
form.value.directorName = val[0].directorName // 标准负责人
form.value.measureRange = val[0].measureRange // 测量范围
form.value.uncertainty = val[0].uncertainty // 测量不确定度
}
}
// --------------------------------------表格-------------------------------------------------
const oldEquipmentList = ref([]) as any // 被更换设备
const checkoutOldEquipmentList = ref([]) as any // 被更换设备选中
const newEquipmentList = ref([]) as any // 更换设备
const checkoutNewEquipmentList = ref([]) as any // 被更换设备选中
const selectIndex = ref(0) // 选择第几行
const columns = [ // 设备表头
{ text: '统一编号', value: 'equipmentNo', align: 'center', width: '240', required: true },
{ text: '设备名称', value: 'equipmentName', align: 'center' },
{ text: '型号规格', value: 'model', align: 'center' },
{ text: '检定有效期', value: 'measureValidDate', align: 'center', width: '120' },
]
const equipmentObj = { // 新增行增加的obj
id: '',
equipmentNo: '',
equipmentName: '',
model: '',
measureValidDate: '',
}
const selectEquipmentDialogRef = ref() // 选择设备编号组件ref
const selectStandardEquipmentDialogRef = ref() // 选择标准装置配套设备组件ref
// 被更换设备选中
const handleOldSelectionChange = (e: any) => {
checkoutOldEquipmentList.value = e
}
// 更换设备选中
const handleNewSelectionChange = (e: any) => {
checkoutNewEquipmentList.value = e
}
// 点击增加行
const addRow = (type: string) => {
if (!form.value.standardId) {
ElMessage.warning('请先选择标准代码')
return false
}
if (type === 'old') {
if (!useCheckList(oldEquipmentList.value, columns, '被更换设备')) {
return false
}
}
else {
if (!useCheckList(newEquipmentList.value, columns, '更换设备')) {
return false
}
}
if (type === 'old') { // 被更换设备
if (useCheckList(oldEquipmentList.value, columns, '被更换设备')) {
useSetAllRowReadable(oldEquipmentList.value)
oldEquipmentList.value.push({ ...equipmentObj })
}
}
else { // 更换设备
if (useCheckList(newEquipmentList.value, columns, '更换设备')) {
useSetAllRowReadable(newEquipmentList.value)
newEquipmentList.value.push({ ...equipmentObj })
}
}
}
/**
* 点击删除行
* @param val 操作的表格类型 old被更换设备、new更换设备
*/
const removeRow = (val: string) => {
if ((val === 'old' && oldEquipmentList.value.length <= 0) || (val === 'new' && newEquipmentList.value.length <= 0)) {
ElMessage({
message: '请选中要删除的行',
type: 'warning',
})
return false
}
if (val === 'old') { // 被更换设备
oldEquipmentList.value = oldEquipmentList.value.filter((item: Itech) => {
return !checkoutOldEquipmentList.value.includes(item)
})
}
if (val === 'new') { // 更换设备
newEquipmentList.value = newEquipmentList.value.filter((item: IAccessory) => {
return !checkoutNewEquipmentList.value.includes(item)
})
}
}
// 点击选择设备
const chooseList = (row: any, index: number, type: string) => {
selectIndex.value = index
if (type === 'old') { // 被更换设备
selectStandardEquipmentDialogRef.value.initDialog(form.value.standardId) // 选择设备台账
}
else {
selectEquipmentDialogRef.value.initDialog() // 选择设备台账
}
}
// 确定选择设备
const confirmSelectEquipment = (val: any, type: string) => {
if (val && val.length) {
if (type === 'old') {
if (oldEquipmentList.value.findIndex((item: { equipmentNo: string }) => item.equipmentNo === val[0].equipmentNo) === -1) {
oldEquipmentList.value.splice(selectIndex.value, 1, val[0])
return false
}
}
else {
if (newEquipmentList.value.findIndex((item: { equipmentNo: string }) => item.equipmentNo === val[0].equipmentNo) === -1) {
newEquipmentList.value.splice(selectIndex.value, 1, val[0])
return false
}
}
ElMessage.warning('此设备添加过')
}
}
// 双击被更换设备
const rowDblclickOld = (row: any) => {
if (props.pageType !== 'detail') {
useDoubleClickTableRow(row, oldEquipmentList.value)
}
}
// 双击更换设备
const rowDblclickNew = (row: any) => {
if (props.pageType !== 'detail') {
useDoubleClickTableRow(row, newEquipmentList.value)
}
}
// -------------------------------------------文件上传--------------------------------------
const fileRef = ref() // 文件上传input
const onFileChange = (event: any) => {
// 原生上传
const files = event.target.files // 上传的文件列表
if (files.length !== 0) {
// 创建formdata对象
const fd = new FormData()
for (var i = 0; i < files.length; i++) {
fd.append('multipartFile', files[i])
}
const loading = ElLoading.service({
lock: true,
background: 'rgba(255, 255, 255, 0.8)',
})
UploadFile(fd).then((res) => {
if (res.code === 200) {
form.value.applyFile = res.data[0]
ElMessage.success('文件上传成功')
loading.close()
}
else {
loading.close()
ElMessage.error(res.message)
}
})
}
}
const upload = () => {
fileRef.value.click()
}
// -----------------------------------------------保存-------------------------------------------
/**
* 点击保存
* @param formEl 基本信息表单ref
*/
const saveForm = async () => {
if (props.title === '更换') {
if (!useCheckList(oldEquipmentList.value, columns, '被更换设备')) {
return false
}
if (!oldEquipmentList.value.length) {
ElMessage.warning('被更换设备表格不能为空')
return false
}
if (!useCheckList(newEquipmentList.value, columns, '被更换设备')) {
return false
}
if (!newEquipmentList.value.length) {
ElMessage.warning('更换设备表格不能为空')
return false
}
if (oldEquipmentList.value.length !== newEquipmentList.value.length) {
ElMessage.warning('被更换的设备和更换的设备数量应该相同')
return false
}
}
await ruleFormRef.value.validate((valid: boolean) => {
if (valid) { // 基本信息表单通过校验
ElMessageBox.confirm(
'确认保存吗?',
'提示',
{
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
},
).then(() => {
const loading = ElLoading.service({
lock: true,
text: '加载中...',
background: 'rgba(255, 255, 255, 0.8)',
})
const param = {
...form.value,
changedIdList: oldEquipmentList.value.map((item: { id: string }) => item.id),
changeIdList: newEquipmentList.value.map((item: { id: string }) => item.id),
}
if (props.pageType === 'add') { // 新建
addStateMaintenance({ ...param, approvalType: props.approvalType }).then((res) => {
loading.close()
form.value.applyNo = res.data.applyNo // 申请编号
infoId.value = res.data.id // id
emits('addSuccess', infoId.value)
ElMessage.success('已保存')
}).catch(() => {
loading.close()
})
}
else if (props.pageType === 'edit') { // 编辑
console.log(props.approvalStatusName)
if (props.approvalStatusName === '草稿箱' || props.approvalStatusName === '全部') {
updateStateMaintenance({ ...param, approvalType: props.approvalType, id: infoId.value, processId: props.processId }).then((res) => {
loading.close()
emits('addSuccess', infoId.value)
ElMessage.success('已保存')
}).catch(() => {
loading.close()
})
}
else { // '未通过' || '已取消'
console.log(props.processId, 'lll')
failUpdateStateMaintenance({ ...param, approvalType: props.approvalType, id: infoId.value, processId: props.processId }).then((res) => {
loading.close()
emits('submitSuccess')
ElMessage.success('已保存')
}).catch(() => {
loading.close()
})
}
}
})
}
})
}
// ----------------------------------------------提交--------------------------------------------
// 提交
/**
*
* @param processId 流程实例id
* @param id
*/
const submitForm = (processId: string, id: string) => {
const loading = ElLoading.service({
lock: true,
text: '加载中...',
background: 'rgba(255, 255, 255, 0.6)',
})
submit({ id, formId: props.formId, processId }).then((res) => {
ElMessage.success('已提交')
emits('submitSuccess')
loading.close()
})
}
// -----------------------------------------获取详情------------------------------------------
// 获取详情
const fetchInfo = () => {
loading.value = true
getInfo({ id: infoId.value }).then((res) => {
loading.value = false
form.value = res.data
oldEquipmentList.value = res.data.changedList.map((item: { measureValidDate: string }) => {
return {
...item,
measureValidDate: item.measureValidDate ? dayjs(item.measureValidDate).format('YYYY-MM-DD') : item.measureValidDate,
}
})
newEquipmentList.value = res.data.changeList.map((item: { measureValidDate: string }) => {
return {
...item,
measureValidDate: item.measureValidDate ? dayjs(item.measureValidDate).format('YYYY-MM-DD') : item.measureValidDate,
}
})
})
}
// ---------------------------------------------钩子----------------------------------------------
watch(() => props.id, (newValue) => {
infoId.value = newValue!
if (infoId.value) {
fetchInfo() // 获取详情信息
}
}, { immediate: true })
onMounted(async () => {
await getDict()
form.value.applyName = `标准装置${props.title}申请表` // 申请表名称
form.value.createUserId = user.id// 申请人id
form.value.createUserName = user.name // 申请人名字
form.value.createTime = dayjs().format('YYYY-MM-DD HH-mm:ss')// 申请时间
if (props.pageType !== 'add' && infoId.value) {
fetchInfo() // 获取详情信息
}
})
defineExpose({ saveForm, submitForm })
</script>
<template>
<detail-block v-loading="loading" title="">
<el-form
ref="ruleFormRef"
:model="form"
:label-width="120"
label-position="right"
:rules="rules"
>
<el-row :gutter="24">
<el-col :span="6">
<el-form-item label="实验室代码" prop="labCode">
<el-select v-model="form.labCode" :placeholder="pageType === 'detail' ? ' ' : '请选择实验室代码'" :disabled="pageType === 'detail'" class="full-width-input">
<el-option v-for="item in labCodeList" :key="item.id" :label="item.name" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="组别代码" prop="groupCode">
<el-select v-model="form.groupCode" :placeholder="pageType === 'detail' ? ' ' : '请选择组别代码'" :disabled="pageType === 'detail'" class="full-width-input">
<el-option v-for="item in groupCodeList" :key="item.id" :label="item.name" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="申请单编号">
<el-input v-model="form.applyNo" disabled placeholder="系统自动生成" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="申请单名称">
<el-input
v-model="form.applyName"
:placeholder="pageType === 'detail' ? '' : '请输入申请单名称'"
disabled
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="申请人:">
<el-input
v-model="form.createUserName" disabled
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="申请时间:" prop="applyTime">
<el-date-picker
v-model="form.createTime"
type="datetime"
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
disabled
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="标准代码:" prop="standardNo">
<el-input
v-model="form.standardNo"
:placeholder="pageType === 'detail' ? '' : '请选择标准代码'"
:class="{ 'detail-input': pageType === 'detail' }"
disabled
>
<template v-if="pageType !== 'detail'" #append>
<el-button size="small" @click="selectStandard">
选择
</el-button>
</template>
</el-input>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="标准装置名称:" prop="standardName">
<el-input
v-model.trim="form.standardName"
:placeholder="pageType === 'detail' ? '' : '标准装置名称'"
disabled
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="标准所在部门" prop="deptId">
<dept-select v-model="form.deptId" :data="useDeptList" disabled :placeholder="pageType === 'detail' ? ' ' : '标准所在部门'" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="标准负责人:" prop="directorName">
<el-input
v-model.trim="form.directorName"
:placeholder="pageType === 'detail' ? '' : '标准负责人'"
disabled
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24" class="marg">
<el-col :span="12">
<el-form-item label="测量范围:">
<el-input
v-model="form.measureRange"
type="textarea"
autosize
:placeholder="pageType === 'detail' ? '' : '测量范围'"
disabled
:class="{ 'detail-input': pageType === 'detail' }"
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24" class="marg">
<el-col :span="12">
<el-form-item label="测量不确定度:">
<el-input
v-model="form.uncertainty"
type="textarea"
autosize
:placeholder="pageType === 'detail' ? '' : '测量不确定度'"
disabled
:class="{ 'detail-input': pageType === 'detail' }"
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24" class="marg">
<el-col :span="12">
<el-form-item :label="`${props.title}申请说明:`" prop="applyIllustrate">
<el-input
v-model="form.applyIllustrate"
type="textarea"
autosize
:placeholder="pageType === 'detail' ? '' : `请输入${props.title}申请说明`"
:disabled="pageType === 'detail'"
:class="{ 'detail-input': pageType === 'detail' }"
/>
</el-form-item>
</el-col>
</el-row>
<el-row v-if="props.title !== '更换'" :gutter="24" class="marg">
<el-col :span="24">
<el-form-item label="附件:">
<show-photo v-if="form.applyFile" :minio-file-name="form.applyFile" />
<el-button v-if="pageType !== 'detail'" type="primary" :disabled="pageType === 'detail'" :style="{ 'margin-left': form.applyFile === '' ? '0px' : '20px' }" @click="upload">
{{ form.applyFile === '' ? '上传' : '更换附件' }}
</el-button>
<input v-show="pageType === ''" ref="fileRef" type="file" name="upload" multiple @change="onFileChange">
</el-form-item>
</el-col>
</el-row>
</el-form>
</detail-block>
<detail-block v-if="props.title === '更换'" title="被更换设备">
<template v-if="pageType !== 'detail'" #btns>
<el-button v-if="pageType !== 'detail'" type="primary" @click="addRow('old')">
增加行
</el-button>
<el-button v-if="pageType !== 'detail'" type="info" @click="removeRow('old')">
删除行
</el-button>
</template>
<el-table
:data="oldEquipmentList"
border
style="width: 100%;"
@selection-change="handleOldSelectionChange"
@row-dblclick="rowDblclickOld"
>
<el-table-column
v-if="pageType !== 'detail'"
type="selection"
width="38"
/>
<el-table-column align="center" label="序号" width="80" type="index" />
<el-table-column
v-for="item in columns"
:key="item.value"
:prop="item.value"
:label="item.text"
align="center"
:width="item.width"
>
<template #header>
<span v-show="item.required" style="color: red;">*</span><span>{{ item.text }}</span>
</template>
<template
v-if="item.value === 'equipmentNo' && pageType !== 'detail'"
#default="scope"
>
<el-input
v-model="scope.row[item.value]"
:placeholder="`${item.text}`"
class="input"
disabled
>
<template v-if="pageType !== 'detail'" #append>
<el-button
size="small"
@click="chooseList(scope.row, scope.$index, 'old')"
>
选择
</el-button>
</template>
</el-input>
</template>
</el-table-column>
</el-table>
</detail-block>
<detail-block v-if="props.title === '更换'" title="更换设备">
<template v-if="pageType !== 'detail'" #btns>
<el-button v-if="pageType !== 'detail'" type="primary" @click="addRow('new')">
增加行
</el-button>
<el-button v-if="pageType !== 'detail'" type="info" @click="removeRow('new')">
删除行
</el-button>
</template>
<el-table
:data="newEquipmentList
"
border
style="width: 100%;"
@selection-change="handleNewSelectionChange"
@row-dblclick="rowDblclickNew"
>
<el-table-column
v-if="pageType !== 'detail'"
type="selection"
width="38"
/>
<el-table-column align="center" label="序号" width="80" type="index" />
<el-table-column
v-for="item in columns"
:key="item.value"
:prop="item.value"
:label="item.text"
align="center"
:width="item.width"
>
<template #header>
<span v-show="item.required" style="color: red;">*</span><span>{{ item.text }}</span>
</template>
<template
v-if="item.value === 'equipmentNo' && pageType !== 'detail'"
#default="scope"
>
<el-input
v-model="scope.row[item.value]"
:placeholder="`${item.text}`"
class="input"
disabled
>
<template v-if="pageType !== 'detail'" #append>
<el-button
v-if="pageType !== 'detail'"
size="small"
@click="chooseList(scope.row, scope.$index, 'new')"
>
选择
</el-button>
</template>
</el-input>
</template>
</el-table-column>
</el-table>
</detail-block>
<!-- 选择标准代码 -->
<select-standard-dialog ref="selectStandardDialogRef" @confirm="confirmSelectStandard" />
<!-- 选择标准装置配套设备 -->
<select-standard-equipment-dialog ref="selectStandardEquipmentDialogRef" @confirm="(val: any) => confirmSelectEquipment(val, 'old')" />
<!-- 选择设备台账 -->
<select-equipment-dialog ref="selectEquipmentDialogRef" @confirm="(val: any) => confirmSelectEquipment(val, 'new')" />
</template>
<style lang="scss" scoped>
.link {
text-decoration: underline;
color: #3d7eff;
cursor: pointer;
}
.file-area {
display: flex;
align-items: center;
font-size: 14px;
color: #60627f;
margin-bottom: 10px;
margin-left: 40px;
white-space: nowrap;
.tech-file {
display: flex;
align-items: center;
margin-left: 20px;
.file-text {
margin-right: 10px;
}
}
}
</style>