<!-- 委托书详情 -->
<script lang="ts" setup name="OrderListEdit">
import type { Ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import type { FormInstance, FormRules, UploadUserFile } from 'element-plus'
import type { IOrderDetail, ISampleList, dictType } from './orderList_interface'
import selectSample from './selectSample.vue'
import { UploadFile } from '@/api/measure/file'
import selectCustomer from '@/views/customer/sample/list/selectCustomer.vue'
import type { ICustomer } from '@/views/customer/customerInfo/customer_interface'
import showPhoto from '@/views/system/tool/showPhoto.vue'
import { getDictByCode } from '@/api/system/dict'
import { getUid } from '@/utils/getUid'
import { addOrder, getOrderDetail, updateOrder } from '@/api/business/schedule/order'
const pageType = ref('add') // 页面类型: add, edit, detail
const infoId = ref('') // id
const isReceived = ref(false) // 样品状态是否已接收
const visible = ref(false) // 控制选择委托方对话框显隐
const sampleVisible = ref(false) // 控制选择样品对话框显隐
const ruleFormRef = ref()
// 表单
const dataForm: Ref<IOrderDetail> = ref({
id: '',
orderCode: '', // 委托书编号
deliverer: '', // 送检人
delivererTel: '', // 送样人联系方式
orderTime: '', // 委托日期
planDeliverTime: '', // 预计送达时间
requireOverTime: '', // 要求检完时间
customerNo: '', // 委托方代码
customerId: '', // 委托方id
customerName: '', // 委托方名称
phone: '', // 委托方电话
customerAddress: '', // 委托方地址
remark: '', // 备注
minioFileName: '', // 附件
isUrgent: 0, // 是否加急 0否 1是
certifications: '', // 证书类别
})
const certificationsMap = ref<dictType[]>([]) // 证书类别
const powerVoltageMap = ref<dictType[]>([]) // 电源电压
const isUrgentMap = ref<dictType[]>([]) // 是否加急
const customerInfoMap = ref<dictType[]>([]) // 系统字典--航天计量检测技术(江苏)有限公司基本信息
const list = ref<ISampleList[]>([])// 表格数据
// 选中的内容
const checkoutList = ref([])
// 表头
const columns = ref([
{ text: '样品编号', value: 'sampleNo', align: 'center', width: '170', disabled: true },
{ text: '样品名称', value: 'sampleName', align: 'center', required: true },
{ text: '型号', value: 'sampleModel', align: 'center', required: true },
{ text: '出厂编号', value: 'manufacturingNo', align: 'center', required: true },
{ text: '电源电压', value: 'powerVoltage', align: 'center', required: true },
{ text: '附件说明', value: 'appendixDescn', align: 'center' },
{ text: '备注', value: 'remark', align: 'center' },
{ text: '检定项目', value: 'measureContent', align: 'center' },
])
// 自定义校验规则--要求检完时间不能比预计送达时间大
const requireOverTimeValid = (rule: any, value: any, callback: any) => {
if (!value) {
return callback(new Error('要求检完时间不能为空'))
}
if (new Date(dataForm.value.planDeliverTime).getTime() >= new Date(dataForm.value.requireOverTime).getTime()) {
return callback(new Error('要求检完时间应大于预计送达时间'))
}
callback()
}
// 校验规则
const rules = reactive<FormRules>({
deliverer: [{ required: true, message: '要求送样人不能为空', trigger: 'blur' }],
delivererTel: [{ required: true, message: '要求送样人联系方式不能为空', trigger: 'blur' }],
customerNo: [{ required: true, message: '要求委托方代码不能为空', trigger: 'change' }],
customerName: [{ required: true, message: '要求委托方名称不能为空', trigger: 'change' }],
phone: [{ required: true, message: '要求委托方电话不能为空', trigger: 'change' }],
customerAddress: [{ required: true, message: '要求委托方地址不能为空', trigger: 'change' }],
orderTime: [{ type: 'date', required: true, message: '要求委托日期不能为空', trigger: 'change' }],
planDeliverTime: [{ type: 'date', required: true, message: '要求预计送达时间不能为空', trigger: 'change' }],
requireOverTime: [{ type: 'date', validator: requireOverTimeValid, trigger: 'change' }],
certifications: [{ required: true, message: '要求证书类别不能为空', trigger: 'change' }],
isUrgent: [{ required: true, message: '要求是否加急不能为空', trigger: 'change' }],
}) // 表单验证规则
// 从路由中获取页面类型参数
const $route = useRoute()
if ($route.params && $route.params.type) {
pageType.value = $route.params.type as string
if ($route.params.id) {
infoId.value = $route.params.id as string
}
if ($route.params.status) {
isReceived.value = $route.params.status === '2'
console.log('样品砖淘', isReceived.value)
}
}
// 获取字典值
function getDict() {
// 证书类别
getDictByCode('certificationType').then((response) => {
certificationsMap.value = response.data
})
// 电源电压
getDictByCode('powerVoltage').then((response) => {
powerVoltageMap.value = response.data
})
// 是否加急
getDictByCode('isUrgent').then((response) => {
isUrgentMap.value = response.data.map((item: dictType) => {
return {
...item,
value: parseInt(item.value as string),
}
})
})
// 系统字典
getDictByCode('systemDict').then((response) => {
const tempMap = response.data.map((item: dictType) => {
if (item.value === 'address') {
item.label = '通信地址'
}
else if (item.value === 'postalCode') {
item.label = '邮编'
}
else if (item.value === 'tel') {
item.label = '电话'
}
else if (item.value === 'fax') {
item.label = '传真'
}
return item
})
// 删除除上述四项的其他基本信息
tempMap.forEach((item: dictType, index: number) => {
if (item.value !== 'address' && item.value !== 'postalCode' && item.value !== 'tel' && item.value !== 'fax') {
tempMap.splice(index, 1)
}
})
customerInfoMap.value = tempMap
})
}
getDict()
// 点击选择
const customerNoFocus = () => {
visible.value = true
}
// 点击从样品库添加
const multiAdd = () => {
if (!dataForm.value.customerNo) {
ElMessage.warning('请先选择委托方')
return
}
sampleVisible.value = true
}
// 双击样品表格
const rowDblclick = (row: ISampleList) => {
row.isEdit = true
}
// 单击样品表格某一行
const rowClick = (row: ISampleList) => {
// row.isEdit = false
}
// 点击表头--手填全的行和样品库中选的行退出编辑模式
const headerClick = () => {
list.value.forEach((item) => {
if ((item.isEdit && (!item.sampleName || !item.sampleModel || !item.manufacturingNo || !item.powerVoltage))) {
item.isEdit = true
}
else {
item.isEdit = false
}
})
}
// 选好委托方
const confirmCheckout = (val: Array<ICustomer>) => {
if (val && val.length) {
// 切换委托方时把不是手填的样品删了
list.value.filter(item => !item.sampleNo)
dataForm.value.customerNo = val[0].customerNo // 委托方代码
dataForm.value.customerId = val[0].id // 委托方id
dataForm.value.customerName = val[0].customerName // 委托方名称
dataForm.value.phone = val[0].phone // 委托方电话
dataForm.value.customerAddress = val[0].fullAddress // 委托方地址
}
}
// 选择好样品
const clickConfirmSample = (val: Array<ISampleList>) => {
val.forEach((item: ISampleList) => {
// 只添加列表里不存在的
const index = list.value.findIndex((i: ISampleList) => item.sampleNo === i.sampleNo)
if (index === -1) {
list.value.push({
...item,
isExistSample: '1', // 是否存在样品库中 1存在、0不存在
})
}
})
}
// 控制选择委托方对话框显隐
const changeVisible = (val: boolean) => {
visible.value = val
}
// 控制选择样品对话框显隐
const changeSampleVisible = (val: boolean) => {
sampleVisible.value = val
}
// 多选发生改变时
const handleSelectionChange = (e: any) => {
checkoutList.value = e
}
// 检查表格第几行信息未完善
const checkList = () => {
const index = list.value.findIndex(item => (!item.sampleNo || item.sampleNo === '系统自动生成') && (!item.sampleName || !item.sampleModel || !item.manufacturingNo || !item.powerVoltage))
if (index !== -1) {
return index + 1
}
else {
return 'pass'
}
}
// 增加行
const addRow = () => {
const result = checkList()
if (result !== 'pass') {
ElMessage.warning(`请完善第${result}行样品信息`)
return
}
list.value.push({
sampleNo: '', // 样品编号
sampleName: '', // 样品名称
sampleModel: '', // 样品型号
manufacturingNo: '', // 出厂编号
powerVoltage: '', // 电源电压
appendixDescn: '', // 附件说明
measureContent: '', // 检定项目
remark: '', // 备注
isEdit: true, // 是否可编辑
isExistSample: '0', // 是否存在样品库中 1存在、0不存在
delId: getUid(),
})
}
// 删除行
const delRow = () => {
if (checkoutList.value.length <= 0) {
ElMessage({
message: '请选中要删除的行',
type: 'warning',
})
}
else {
checkoutList.value.forEach((item: ISampleList) => {
list.value.forEach((element, index) => {
if (!item.sampleNo) { // 点击增加行--手动增加的项目需要判断前端添加的delID
if (element.delId === item.delId) {
list.value.splice(index, 1)
}
}
else { // 从样品库中选择的项目
if (element.sampleNo === item.sampleNo) {
list.value.splice(index, 1)
}
}
})
})
}
}
const fileRef = ref() // 文件上传input
const onFileChange = (event: any) => {
// 原生上传
if (event.target.files?.length !== 0) {
// 创建formdata对象
const fd = new FormData()
fd.append('multipartFile', event.target.files[0])
UploadFile(fd).then((res) => {
if (res.code === 200) {
dataForm.value.minioFileName = res.data[0]
// 重置当前验证
ElMessage.success('文件上传成功')
}
else {
ElMessage.error(res.message)
}
})
}
}
const upload = () => {
fileRef.value.click()
}
const $router = useRouter()
// 关闭新增页面的回调
const close = () => {
$router.back()
}
// 点击保存
const saveForm = (formEl: FormInstance | undefined) => {
// 检查表格是否存在增加行信息没有完善的情况
const result = checkList()
if (result !== 'pass') {
ElMessage.warning(`表格第${result}行信息未完善`)
return
}
headerClick() // 所有行退出编辑模式
if (!formEl) { return }
formEl.validate((valid) => {
if (valid) {
ElMessageBox.confirm(
'确认保存吗?',
'提示',
{
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
},
).then(() => {
const params = {
...dataForm.value,
customerPhone: dataForm.value.phone, // 委托方电话
customerSampleInfoList: list.value,
}
if (pageType.value === 'edit') { // 编辑
updateOrder(params).then(() => {
ElMessage.success('已保存')
$router.go(-1)
})
}
if (pageType.value === 'add') { // 新建
addOrder(params).then(() => {
ElMessage.success('已保存')
$router.go(-1)
})
}
})
}
})
}
// 点击打印
const printObj = ref({
id: 'main', // 需要打印元素的id
popTitle: '委托书详情', // 打印配置页上方的标题
extraHead: '<div style="display: flex;flex-direction: column;text-align: center"><h3></h3></div>', // 最上方的头部文字,附加在head标签上的额外标签,使用逗号分割
preview: false, // 是否启动预览模式,默认是false
standard: '',
extarCss: '',
})
// 获取详细信息
const getInfo = () => {
getOrderDetail({ id: infoId.value }).then((res) => {
dataForm.value = res.data
dataForm.value.phone = res.data.customerPhone
list.value = res.data.customerSampleInfoList
})
}
// 非添加页面获取详情
if (pageType.value !== 'add') {
getInfo()
}
</script>
<template>
<app-container>
<div id="main">
<div class="customer-title">
<img src="@/assets/images/logo.png" class="img">
<div class="title">
航天计量检测技术(江苏)有限公司
</div>
</div>
<detail-page title="检测/校准委托单">
<template #btns>
<el-button v-if="pageType === 'detail'" v-print="printObj" type="primary">
打印
</el-button>
<el-button v-if="pageType !== 'detail'" type="primary" @click="saveForm(ruleFormRef)">
保存
</el-button>
<el-button type="info" @click="close">
关闭
</el-button>
</template>
<div id="form">
<el-form
ref="ruleFormRef"
:model="dataForm"
:label-width="120"
label-position="right"
:rules="rules"
>
<el-row :gutter="24">
<el-col :span="8">
<el-form-item label="委托书编号:" prop="orderCode">
<el-input
v-model="dataForm.orderCode"
:placeholder="pageType === 'detail' ? '' : '系统自动生成'"
:class="{ 'detail-input': pageType === 'detail' }"
disabled
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="送样人:" prop="deliverer">
<el-input
v-model="dataForm.deliverer"
:placeholder="pageType === 'detail' ? '' : '请输入送样人'"
:class="{ 'detail-input': pageType === 'detail' }"
:disabled="pageType === 'detail' || isReceived"
/>
</el-form-item>
</el-col><el-col :span="8">
<el-form-item label="联系方式:" prop="delivererTel">
<el-input
v-model="dataForm.delivererTel"
:placeholder="pageType === 'detail' ? '' : '请输入联系方式'"
:class="{ 'detail-input': pageType === 'detail' }"
:disabled="pageType === 'detail' || isReceived"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="委托日期:" prop="orderTime">
<el-date-picker
v-model="dataForm.orderTime"
type="date"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
class="full-width-input"
:placeholder="pageType === 'detail' ? '' : '请输入委托日期'"
:class="{ 'detail-input': pageType === 'detail' }"
:disabled="pageType === 'detail' || isReceived"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="预计送达时间:" prop="planDeliverTime">
<el-date-picker
v-model="dataForm.planDeliverTime"
type="datetime"
class="full-width-input"
:placeholder="pageType === 'detail' ? '' : '请输入预计送达时间'"
:class="{ 'detail-input': pageType === 'detail' }"
:disabled="pageType === 'detail' || isReceived"
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="要求检完时间:" prop="requireOverTime">
<el-date-picker
v-model="dataForm.requireOverTime"
type="datetime"
class="full-width-input"
:placeholder="pageType === 'detail' ? '' : '请输入要求检完时间'"
:class="{ 'detail-input': pageType === 'detail' }"
:disabled="pageType === 'detail' || isReceived"
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="委托方代码" prop="customerNo">
<el-input
v-model="dataForm.customerNo"
:placeholder="pageType === 'detail' ? '' : '请输入委托方代码'"
:class="{ 'detail-input': pageType === 'detail' }"
disabled
>
<template v-if="pageType !== 'detail' && !isReceived" #append>
<el-button size="small" @click="customerNoFocus">
选择
</el-button>
</template>
</el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="委托方名称" prop="customerName">
<el-input
v-model="dataForm.customerName"
:placeholder="pageType === 'detail' ? '' : '请输入委托方名称'"
:class="{ 'detail-input': pageType === 'detail' }"
disabled
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="委托方电话" prop="phone">
<el-input
v-model="dataForm.phone"
:placeholder="pageType === 'detail' ? '' : '请输入委托方电话'"
:class="{ 'detail-input': pageType === 'detail' }"
disabled
/>
</el-form-item>
</el-col>
<el-col :span="16">
<el-form-item label="委托方地址:" prop="customerAddress">
<el-input
v-model="dataForm.customerAddress"
type="textarea"
autosize
:placeholder="pageType === 'detail' ? '' : '请输入委托方地址'"
:class="{ 'detail-input': pageType === 'detail' }"
disabled
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="8">
<el-form-item label="证书类别:" prop="certifications">
<el-select v-model="dataForm.certifications" :placeholder="pageType === 'detail' ? '' : '请选择证书类别'" :disabled="pageType === 'detail' || isReceived" class="full-width-input">
<el-option
v-for="i in certificationsMap"
:key="i.value"
:label="i.name"
:value="i.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="是否加急:" prop="isUrgent">
<el-select v-model="dataForm.isUrgent" :placeholder="pageType === 'detail' ? '' : '请选择是否加急'" :disabled="pageType === 'detail'" class="full-width-input">
<el-option
v-for="i in isUrgentMap"
:key="i.value"
:label="i.name"
:value="i.value"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24" class="marg">
<el-col :span="16">
<el-form-item label="备注:">
<el-input
v-model="dataForm.remark"
type="textarea"
autosize
:placeholder="pageType === 'detail' ? '' : '请输入备注'"
:disabled="pageType === 'detail' || isReceived"
:class="{ 'detail-input': pageType === 'detail' }"
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24" class="marg">
<el-col :span="16">
<el-form-item label="附件:">
<show-photo v-if="dataForm.minioFileName" :minio-file-name="dataForm.minioFileName" />
<span v-else-if="pageType === 'detail'">无</span>
<input v-show="pageType === ''" ref="fileRef" type="file" @change="onFileChange">
<el-button v-if="pageType !== 'detail' && !isReceived" id="file" type="primary" :disabled="pageType === 'detail'" :style="{ 'margin-left': dataForm.minioFileName === '' ? '0px' : '20px' }" @click="upload">
{{ dataForm.minioFileName === '' ? '上传' : '更换附件' }}
</el-button>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
</detail-page>
<!-- 表格 -->
<detail-block title="样品清单">
<template #btns>
<el-button v-if="pageType !== 'detail'" type="primary" @click="multiAdd">
从样品库中添加
</el-button>
<el-button v-if="pageType !== 'detail'" type="primary" @click="addRow">
增加行
</el-button>
<el-button v-if="pageType !== 'detail'" type="info" @click="delRow">
删除行
</el-button>
</template>
<el-table
:data="list"
border
style="width: 100%;"
max-height="600"
@selection-change="handleSelectionChange"
@row-dblclick="rowDblclick"
@row-click="rowClick"
@header-click="headerClick"
>
<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"
:width="item.width"
show-overflow-tooltip
align="center"
>
<template #header>
<span v-show="item.required" style="color: red;">*</span><span>{{ item.text }}</span>
</template>
<template v-if="(pageType === 'add' || pageType === 'edit')" #default="scope">
<!-- 手动增加行-名称、型号、编号可编辑 -->
<el-input
v-if="(!scope.row.sampleNo || scope.row.sampleNo === '系统自动生成') && item.value !== 'powerVoltage' && (item.value === 'sampleNo' || item.value === 'sampleName' || item.value === 'sampleModel' || item.value === 'manufacturingNo') && scope.row.isEdit"
v-model="scope.row[item.value]"
:placeholder="item.value === 'sampleNo' ? '系统自动生成' : `请输入${item.text}`"
:disabled="item.disabled"
class="input"
/>
<!-- 手动增加行可编辑:附件说明、检定项目、备注 -->
<el-input
v-if="(item.value === 'appendixDescn' || item.value === 'measureContent' || item.value === 'remark') && scope.row.isEdit"
v-model="scope.row[item.value]"
:placeholder=" `请输入${item.text}`"
:disabled="item.disabled"
class="input"
/>
<!-- 除电源电压和样品编号另外的行 -->
<span v-if="item.value !== 'powerVoltage' && item.value !== 'sampleNo' && !scope.row.isEdit">{{ scope.row[item.value] }}</span>
<!-- 样品编号不可编辑 -->
<span v-if="item.value === 'sampleNo' && !scope.row.isEdit">{{ scope.row[item.value] || '系统自动生成' }}</span>
<el-select v-if="item.value === 'powerVoltage' && scope.row.isEdit && !scope.row.sampleNo" v-model="scope.row[item.value]" :placeholder="`请选择${item.text}`">
<el-option
v-for="i in powerVoltageMap"
:key="i.value"
:label="i.name"
:value="i.value"
/>
</el-select>
<span v-if="item.value === 'powerVoltage' && !scope.row.isEdit">{{ scope.row[item.value] }}</span>
</template>
</el-table-column>
</el-table>
</detail-block>
<!-- 公司信息 -->
<div class="customer-info">
<div v-for="item in customerInfoMap" :key="item.value" class="content">
<div v-if="item.value === 'address' || item.value === 'postalCode' || item.value === 'tel' || item.value === 'fax'" class="title">
{{ item.label }}:
</div>
<div v-if="item.value === 'address' || item.value === 'postalCode' || item.value === 'tel' || item.value === 'fax'" class="value">
{{ item.name }}
</div>
</div>
</div>
</div>
<!-- 选择委托方组件 -->
<select-customer v-model:visible="visible" @confirmCheckout="confirmCheckout" @changeVisible="changeVisible" />
<!-- 选择样品组件 -->
<select-sample v-model:visible="sampleVisible" :customer-no="dataForm.customerNo" @clickConfirmSample="clickConfirmSample" @changeVisible="changeSampleVisible" />
</app-container>
</template>
<style lang="scss" scoped>
.customer-title {
display: flex;
justify-content: center;
align-items: center;
font-size: 24px;
font-weight: 700;
margin: 24px 0;
.img {
width: 32px;
height: 32px;
margin-right: 14px;
vertical-align: middle;
}
}
.customer-info {
display: flex;
justify-content: space-around;
align-items: center;
flex-wrap: nowrap;
margin: 40px 0;
.content {
display: flex;
font-size: 14px;
.title {
font-weight: 600;
color: #000;
}
.value {
margin-left: 10px;
}
}
}
.selectBtn {
position: absolute;
top: 0;
right: 0;
}
</style>