|
@@ -1,10 +1,11 @@
|
|
|
<template>
|
|
<template>
|
|
|
<el-dialog v-model="dialogVisible" title="资质管理" width="800px" append-to-body @close="handleClose">
|
|
<el-dialog v-model="dialogVisible" title="资质管理" width="800px" append-to-body @close="handleClose">
|
|
|
- <el-form ref="formRef" :model="formData" :rules="rules" label-width="100px">
|
|
|
|
|
|
|
+ <!-- 注意:el-form 的 model 绑定的是本地的 localFormData -->
|
|
|
|
|
+ <el-form ref="formRef" :model="localFormData" :rules="rules" label-width="100px">
|
|
|
<el-row :gutter="20">
|
|
<el-row :gutter="20">
|
|
|
<el-col :span="12">
|
|
<el-col :span="12">
|
|
|
<el-form-item label="资质类型" prop="qualificationType">
|
|
<el-form-item label="资质类型" prop="qualificationType">
|
|
|
- <el-select v-model="formData.qualificationType" placeholder="请选择" style="width: 100%">
|
|
|
|
|
|
|
+ <el-select v-model="localFormData.qualificationType" placeholder="请选择" style="width: 100%">
|
|
|
<el-option label="营业执照" :value="1" />
|
|
<el-option label="营业执照" :value="1" />
|
|
|
<el-option label="资质证书" :value="2" />
|
|
<el-option label="资质证书" :value="2" />
|
|
|
</el-select>
|
|
</el-select>
|
|
@@ -12,29 +13,37 @@
|
|
|
</el-col>
|
|
</el-col>
|
|
|
<el-col :span="12">
|
|
<el-col :span="12">
|
|
|
<el-form-item label="资质编号" prop="qualificationNo">
|
|
<el-form-item label="资质编号" prop="qualificationNo">
|
|
|
- <el-input v-model="formData.qualificationNo" placeholder="请输入" />
|
|
|
|
|
|
|
+ <el-input v-model="localFormData.qualificationNo" placeholder="请输入" />
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
</el-col>
|
|
</el-col>
|
|
|
</el-row>
|
|
</el-row>
|
|
|
<el-row :gutter="20">
|
|
<el-row :gutter="20">
|
|
|
<el-col :span="12">
|
|
<el-col :span="12">
|
|
|
<el-form-item label="签发机构">
|
|
<el-form-item label="签发机构">
|
|
|
- <el-input v-model="formData.authority" placeholder="请输入" />
|
|
|
|
|
|
|
+ <el-input v-model="localFormData.authority" placeholder="请输入" />
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
</el-col>
|
|
</el-col>
|
|
|
<el-col :span="12">
|
|
<el-col :span="12">
|
|
|
<el-form-item label="截止日期">
|
|
<el-form-item label="截止日期">
|
|
|
- <el-date-picker v-model="formData.deadline" type="date" placeholder="请选择日期" value-format="YYYY-MM-DD" style="width: 100%" />
|
|
|
|
|
|
|
+ <el-date-picker v-model="localFormData.deadline" type="date" placeholder="请选择日期" value-format="YYYY-MM-DD" style="width: 100%" />
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
</el-col>
|
|
</el-col>
|
|
|
</el-row>
|
|
</el-row>
|
|
|
<el-row>
|
|
<el-row>
|
|
|
<el-col :span="24">
|
|
<el-col :span="24">
|
|
|
<el-form-item label="附件">
|
|
<el-form-item label="附件">
|
|
|
- <el-upload class="upload-demo" action="#" :auto-upload="false">
|
|
|
|
|
- <el-button size="small">上传</el-button>
|
|
|
|
|
|
|
+ <el-upload
|
|
|
|
|
+ :action="action"
|
|
|
|
|
+ :on-success="handleUploadSuccess"
|
|
|
|
|
+ :before-upload="beforeUpload"
|
|
|
|
|
+ :on-remove="handleRemoveUploadFile"
|
|
|
|
|
+ :on-preview="handlePreviewUploadFile"
|
|
|
|
|
+ :file-list="fileList"
|
|
|
|
|
+ multiple
|
|
|
|
|
+ >
|
|
|
|
|
+ <el-button type="primary" icon="Upload">点击上传</el-button>
|
|
|
<template #tip>
|
|
<template #tip>
|
|
|
- <div class="el-upload__tip">支持jpg/png/xlsx等文件</div>
|
|
|
|
|
|
|
+ <div class="el-upload__tip">支持jpg/png/xlsx等文件,单个文件不超过50MB</div>
|
|
|
</template>
|
|
</template>
|
|
|
</el-upload>
|
|
</el-upload>
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
@@ -49,14 +58,16 @@
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
<script setup lang="ts">
|
|
|
-import { ref, computed } from 'vue';
|
|
|
|
|
|
|
+import { ref, computed, reactive, watch } from 'vue';
|
|
|
import type { PartnerQualificationForm } from '@/api/partner/qualification/types';
|
|
import type { PartnerQualificationForm } from '@/api/partner/qualification/types';
|
|
|
|
|
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
|
|
|
|
+const action = import.meta.env.VITE_APP_BASE_API + '/resource/oss/upload';
|
|
|
|
|
|
|
|
interface Props {
|
|
interface Props {
|
|
|
visible: boolean;
|
|
visible: boolean;
|
|
|
formData: PartnerQualificationForm;
|
|
formData: PartnerQualificationForm;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+const fileList = ref<any[]>([]);
|
|
|
interface Emits {
|
|
interface Emits {
|
|
|
(e: 'update:visible', value: boolean): void;
|
|
(e: 'update:visible', value: boolean): void;
|
|
|
(e: 'update:formData', value: PartnerQualificationForm): void;
|
|
(e: 'update:formData', value: PartnerQualificationForm): void;
|
|
@@ -71,6 +82,24 @@ const dialogVisible = computed({
|
|
|
set: (value) => emit('update:visible', value)
|
|
set: (value) => emit('update:visible', value)
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
|
|
+// 1. 在子组件内部创建一个本地的响应式表单对象
|
|
|
|
|
+const localFormData = reactive<PartnerQualificationForm>({
|
|
|
|
|
+ qualificationType: undefined,
|
|
|
|
|
+ qualificationNo: '',
|
|
|
|
|
+ authority: '',
|
|
|
|
|
+ deadline: '',
|
|
|
|
|
+ annex: ''
|
|
|
|
|
+} as PartnerQualificationForm);
|
|
|
|
|
+
|
|
|
|
|
+// 2. 监听 props.formData 的变化,同步到本地对象(解决弹窗打开时数据不更新的问题)
|
|
|
|
|
+watch(
|
|
|
|
|
+ () => props.formData,
|
|
|
|
|
+ (newVal) => {
|
|
|
|
|
+ Object.assign(localFormData, newVal);
|
|
|
|
|
+ },
|
|
|
|
|
+ { deep: true, immediate: true }
|
|
|
|
|
+);
|
|
|
|
|
+
|
|
|
const rules = {
|
|
const rules = {
|
|
|
qualificationType: [{ required: true, message: '资质类型不能为空', trigger: 'change' }],
|
|
qualificationType: [{ required: true, message: '资质类型不能为空', trigger: 'change' }],
|
|
|
qualificationNo: [{ required: true, message: '资质编号不能为空', trigger: 'blur' }]
|
|
qualificationNo: [{ required: true, message: '资质编号不能为空', trigger: 'blur' }]
|
|
@@ -78,15 +107,66 @@ const rules = {
|
|
|
|
|
|
|
|
const formRef = ref();
|
|
const formRef = ref();
|
|
|
|
|
|
|
|
|
|
+/** 上传前校验 */
|
|
|
|
|
+const beforeUpload = (file: any) => {
|
|
|
|
|
+ const isLt50M = file.size / 1024 / 1024 < 50;
|
|
|
|
|
+ if (!isLt50M) {
|
|
|
|
|
+ proxy?.$modal.msgWarning('上传文件大小不能超过 50MB!');
|
|
|
|
|
+ }
|
|
|
|
|
+ return isLt50M;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+function handleUploadSuccess(response: any, file: any, fileListParam: any[]) {
|
|
|
|
|
+ if (response.code === 200) {
|
|
|
|
|
+ // 为每个上传成功的文件设置 url 属性
|
|
|
|
|
+ fileListParam.forEach((f: any) => {
|
|
|
|
|
+ if (f.response?.code === 200 && f.response?.data?.url) {
|
|
|
|
|
+ f.url = f.response.data.url;
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ // 更新 fileList
|
|
|
|
|
+ fileList.value = fileListParam;
|
|
|
|
|
+ // 收集所有已上传成功的文件URL
|
|
|
|
|
+ const urls = fileListParam
|
|
|
|
|
+ .filter((f: any) => f.response?.code === 200 || f.url)
|
|
|
|
|
+ .map((f: any) => f.response?.data?.url || f.url)
|
|
|
|
|
+ .filter(Boolean);
|
|
|
|
|
+ localFormData.annex = urls.join(',');
|
|
|
|
|
+ proxy?.$modal.msgSuccess('文件上传成功');
|
|
|
|
|
+ } else {
|
|
|
|
|
+ proxy?.$modal.msgError(response.msg || '文件上传失败');
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 删除文件 */
|
|
|
|
|
+const handleRemoveUploadFile = (uploadFile: any) => {
|
|
|
|
|
+ localFormData.annex = fileList.value
|
|
|
|
|
+ .map((f) => f.url)
|
|
|
|
|
+ .filter(Boolean)
|
|
|
|
|
+ .join(',');
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+/** 预览文件 */
|
|
|
|
|
+const handlePreviewUploadFile = (uploadFile: any) => {
|
|
|
|
|
+ if (uploadFile.url) {
|
|
|
|
|
+ window.open(uploadFile.url, '_blank');
|
|
|
|
|
+ } else {
|
|
|
|
|
+ proxy?.$modal.msgWarning('文件地址不存在');
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
const handleClose = () => {
|
|
const handleClose = () => {
|
|
|
emit('update:visible', false);
|
|
emit('update:visible', false);
|
|
|
|
|
+ // 弹窗关闭时,重置表单校验状态
|
|
|
formRef.value?.resetFields();
|
|
formRef.value?.resetFields();
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
const handleSubmit = () => {
|
|
const handleSubmit = () => {
|
|
|
formRef.value?.validate((valid: boolean) => {
|
|
formRef.value?.validate((valid: boolean) => {
|
|
|
if (valid) {
|
|
if (valid) {
|
|
|
- emit('submit', props.formData);
|
|
|
|
|
|
|
+ // 3. 提交时,将本地修改后的数据通过 emit 同步回父组件
|
|
|
|
|
+ emit('update:formData', localFormData);
|
|
|
|
|
+ emit('submit', localFormData);
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
};
|
|
};
|