javascript
rejectQualityInspection: async (data: FormData) => {
return await request.put({
url: `/mission/quality-inspection/reject`,
data,
headers: { 'Content-Type': 'multipart/form-data' }
})
},
上传文件和其他参数接口
下面是表单和多个文件上传页面
javascript
<template>
<ContentWrap>
<el-row :gutter="20">
<el-col class="section-header">
<div class="section-title">基础信息</div>
<el-button @click="goBack" plain>返回</el-button>
</el-col>
</el-row>
<div class="underline"></div>
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="120px" v-loading="formLoading"
:disabled="disabled">
<div>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="客户名称" prop="customerName">
<el-input readonly v-model="formData.customerName" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="产品名称" prop="productName">
<el-input readonly v-model="formData.productName" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="产品图号" prop="productDrawNo">
<el-input readonly v-model="formData.productDrawNo" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="合格数量" prop="passQuantity">
<el-input-number v-model="formData.passQuantity" :min="0" :max="planQty - 1" style="width: 100%"
@change="updateFailQuantity()" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="不合格数量" prop="failQuantity">
<el-input-number v-model="formData.failQuantity" :min="1" :max="planQty" style="width: 100%"
@change="updatePassQuantity()" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="不合格类型" prop="failType">
<el-select multiple v-model="formData.failType" placeholder="请选择不合格类型">
<el-option label="尺寸不合格" :value="1" />
<el-option label="外观不合格" :value="2" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="责任部门" prop="responsibleDeptName">
<el-input readonly v-model="formData.responsibleDeptName" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item v-if="formData.responsibleDeptName === '外协部'" label="责任人" prop="responsiblePerson">
<el-select disabled="true" v-model="formData.responsiblePerson" placeholder="请选择外协单位" filterable
clearable>
<el-option v-for="item in outSourceList" :key="item.id" :label="item.companyName" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item v-else label="责任人" prop="responsiblePerson">
<el-select disabled="true" v-model="formData.responsiblePerson" placeholder="请选择责任人" filterable clearable>
<el-option v-for="person in userList" :key="person.id" :label="person.nickname" :value="person.id" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="任务单编号" prop="mainTaskOrder">
<el-input readonly v-model="formData.mainTaskOrder" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col>
<el-form-item label="不合格内容" prop="failDescription">
<el-input v-model="formData.failDescription" type="textarea" :rows="3" maxlength="1000" show-word-limit />
</el-form-item>
</el-col>
</el-row>
</div>
</el-form>
<div class="file-box">
<div class="file-item" v-for="(item, index) in fileList" :key="index">
<span class="file-name"> {{ item.name }}</span>
<span class="iconfont icon-shanchu" @click="deleteFile(index)"> </span>
</div>
</div>
<input ref="fileInput" type="file" class="file-input" accept=".png,.jpg,.jpeg" @change="handleFileChange"
multiple />
<el-form-item>
<div style="
width: calc(100% - 120px);
margin-left: 120px;
display: flex;
justify-content: center;
align-items: center;
gap: 12px;
">
<el-button @click="triggerFileInput">上传附件</el-button>
<el-button type="primary" @click="submitForm" :loading="formLoading">保存</el-button>
<el-button @click="goBack">取消</el-button>
</div>
</el-form-item>
</ContentWrap>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import type { FormRules } from 'element-plus'
import { FailReviewApi, FailReview } from '@/api/mission/failreview'
import { DeptVO, getSimpleDeptList } from '@/api/system/dept'
import { QualityInspectionApi } from '@/api/mission/qualityinspection'
import { UserVO, getSimpleUserList } from '@/api/system/user'
import { OutsourcedUnitApi, OutsourcedUnit } from '@/api/foundation/outsourcedunit'
import axios from "axios";
defineOptions({ name: 'FailReviewDetail' })
const route = useRoute()
const router = useRouter()
const message = useMessage()
const formLoading = ref(false)
const disabled = ref(false)
const editable = ref(false)
const formData = reactive<Partial<FailReview>>({})
const formRules = reactive<FormRules>({
customerName: [{ required: true, message: '', trigger: 'blur' }],
productName: [{ required: true, message: '', trigger: 'blur' }],
productDrawNo: [{ required: true, message: '', trigger: 'blur' }],
passQuantity: [{ type: 'number' as any, required: true, message: '', trigger: 'blur' }],
failQuantity: [{ type: 'number' as any, required: true, message: '', trigger: 'blur' }],
failType: [{ required: true, message: '', trigger: 'change' }],
responsibleDept: [{ required: true, message: '', trigger: 'blur' }],
responsiblePerson: [{ required: true, message: '', trigger: 'blur' }],
mainTaskOrder: [{ required: true, message: '', trigger: 'blur' }],
failDescription: [{ required: true, min: 0, message: '', trigger: 'blur' }]
})
const deptList = ref<DeptVO[]>([])
const userList = ref<UserVO[]>([])
const outSourceList = ref<OutsourcedUnit[]>([])
const fileInput = ref(null);
const triggerFileInput = (code) => {
fileInput.value?.click();
};
const fileList = ref([]);
const deleteFile = (index) => {
fileList.value.splice(index, 1);
};
// 选择文件
const handleFileChange = async (e) => {
const files = e.target.files;
// 没有选择文件则直接返回
if (!files || files.length === 0) return;
// 追加多个文件
for (let i = 0; i < files.length; i++) {
fileList.value.push(files[i]);
}
e.target.value = "";
};
const planQty = ref(1)
const updatePassQuantity = () => {
formData.passQuantity = planQty.value - (formData.failQuantity || 1)
}
const updateFailQuantity = () => {
formData.failQuantity = planQty.value - formData.passQuantity
}
// 获取 详情
const loadDetail = async (type: number) => {
console.log('type', type)
const id = Number(route.query.id)
planQty.value = Number(route.query.planQty)
if (!id) {
message.error('缺少详情ID')
return
}
formLoading.value = true
try {
let resp = {}
if (type == 1) {
resp = await FailReviewApi.getFillFailReview(id)
} else {
resp = await FailReviewApi.getFailReviewById(id)
}
deptList.value = await getSimpleDeptList()
Object.assign(formData, resp)
formData.responsibleDeptName = deptList.value.find(s => s.id == formData.responsibleDept)?.name
updatePassQuantity()
outSourceList.value = await OutsourcedUnitApi.getAllOutsourcedUnit(0)
userList.value = await getSimpleUserList()
if (formData.failType == undefined) {
return
}
if (formData.failType == 3) {
formData.failType = [1, 2]
} else {
formData.failType = [formData.failType]
}
} catch (e) {
message.error('加载详情失败')
} finally {
formLoading.value = false
}
}
const formRef = ref()
const init = () => {
console.log('init')
var type = String(route.query.type)
if (type == 'detail') {
disabled.value = true
editable.value = false
loadDetail(0)
} else if (type == 'create') {
disabled.value = false
editable.value = true
loadDetail(1)
} else if (type == 'edit') {
disabled.value = false
editable.value = true
loadDetail(0)
}
}
const goBack = () => router.back()
const submitForm = async () => {
formLoading.value = true;
formRef.value.validate(async (valid: boolean) => {
if (valid) {
if (Array.isArray(formData.failType)) {
if (formData.failType.includes(1) && formData.failType.includes(2)) {
formData.failType = 3
} else {
formData.failType = formData.failType[0] || formData.failType
}
}
try {
// 上传文件
const fileFromData = new FormData();
fileList.value.forEach(file => {
fileFromData.append('files', file);
});
// 其他参数追加到fileFromData处理null和undefined
for (let key in formData) {
if (formData[key] !== null && formData[key] !== undefined) {
fileFromData.append(key, formData[key])
}
}
await QualityInspectionApi.rejectQualityInspection(fileFromData)
message.success('保存成功')
goBack()
} catch (e) {
message.error('保存失败')
}
formLoading.value = false;
}
})
}
const handleCheckedCitiesChange = async () => { }
onMounted(() => {
init()
})
</script>
<style scoped lang="scss">
.file-box {
padding: 0 120px;
.file-item {
font-size: 14px;
line-height: 30px;
display: flex;
.file-name {
width: 200px;
// 超出显示省略号
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: #707070;
}
.icon-shanchu {
color: red;
cursor: pointer;
font-size: 12px;
font-weight: 100;
}
}
}
.file-input {
display: none;
}
.el-form .el-form-item {
margin-bottom: 12px;
}
.section-header {
border-radius: 4px;
background: #fff;
display: flex;
justify-content: space-between;
align-items: center;
}
.section-title {
padding: 12px 16px;
font-size: 16px;
font-weight: 600;
color: #333;
}
.underline {
width: 100%;
border-bottom: 1px solid #ccc;
margin-bottom: 12px;
}
.signArea {
width: 100%;
height: 70%;
text-align: center;
display: block;
}
</style>