|
|
@@ -0,0 +1,623 @@
|
|
|
+<template>
|
|
|
+ <div class="ship-info-form">
|
|
|
+ <el-collapse v-model="activeNames">
|
|
|
+ <el-collapse-item title="水上交通安全通报信息" name="1" :border="false">
|
|
|
+ <el-form
|
|
|
+ v-for="(item, index) in noticeItems"
|
|
|
+ :key="index"
|
|
|
+ :ref="(el) => noticeFormRefs[index] = el"
|
|
|
+ :model="item"
|
|
|
+ :rules="formRules"
|
|
|
+ label-width="160px"
|
|
|
+ size="default"
|
|
|
+ class="notice-form"
|
|
|
+ >
|
|
|
+ <!-- 通报信息标题 + 删除按钮 -->
|
|
|
+ <div class="notification-header">
|
|
|
+ <div class="notification-matters">{{ '通报信息' + (index + 1) }}</div>
|
|
|
+ <el-button
|
|
|
+ v-if="noticeItems.length > 1 && isEditable"
|
|
|
+ type="danger"
|
|
|
+ text
|
|
|
+ size="small"
|
|
|
+ :icon="Delete"
|
|
|
+ @click="handleDelete(index)"
|
|
|
+ >
|
|
|
+ 删除
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 通报事项 -->
|
|
|
+ <el-row :gutter="24">
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-form-item label="通报事项" prop="noticeItem" required>
|
|
|
+ <el-button
|
|
|
+ v-if="!drawerVisible && !item.noticeItem && isEditable"
|
|
|
+ @click="onClickNotice(index)"
|
|
|
+ type="primary"
|
|
|
+ :disabled="!isEditable"
|
|
|
+ >
|
|
|
+ 请选择通报事项
|
|
|
+ </el-button>
|
|
|
+ <el-input v-else disabled v-model="item.noticeItem" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <!-- 通报标准或具体行为 -->
|
|
|
+ <el-row :gutter="24">
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-form-item label="通报标准或具体行为" prop="noticeStandard" required>
|
|
|
+ <el-input
|
|
|
+ v-model="item.noticeStandard"
|
|
|
+ placeholder="请输入通报依据,内容1000字以内"
|
|
|
+ maxlength="1000"
|
|
|
+ show-word-limit
|
|
|
+ :disabled="!isEditable"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <!-- 通报类别(单选框) -->
|
|
|
+ <el-row :gutter="24">
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-form-item label="通报类别" prop="noticeType" required>
|
|
|
+ <el-radio-group v-model="item.noticeType" :disabled="!isEditable">
|
|
|
+ <el-radio label="info" border>信息告知类</el-radio>
|
|
|
+ <el-radio label="assist" border>协助处置类</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <!-- 水上交通安全信息(多行文本) -->
|
|
|
+ <el-row :gutter="24">
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-form-item label="水上交通安全信息" prop="safetyInfo" required>
|
|
|
+ <el-input
|
|
|
+ v-model="item.safetyInfo"
|
|
|
+ type="textarea"
|
|
|
+ :rows="4"
|
|
|
+ placeholder="违法违规信息(内容3000字以内)"
|
|
|
+ maxlength="3000"
|
|
|
+ show-word-limit
|
|
|
+ :disabled="!isEditable"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <!-- 接收单位名称(下拉选择) -->
|
|
|
+ <el-row :gutter="24">
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-form-item label="接收单位名称" prop="receiveUnit" required>
|
|
|
+ <el-select
|
|
|
+ v-model="item.receiveUnit"
|
|
|
+ placeholder="请选择单位名称"
|
|
|
+ style="width: 100%"
|
|
|
+ :disabled="!isEditable"
|
|
|
+ >
|
|
|
+ <el-option label="单位名称1" value="unit1" />
|
|
|
+ <el-option label="单位名称2" value="unit2" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <!-- 行业外分类和接收单位 -->
|
|
|
+ <el-row :gutter="24" class="industry-row">
|
|
|
+ <el-col :span="6">
|
|
|
+ <el-form-item label="行业外分类" prop="industryType">
|
|
|
+ <el-select
|
|
|
+ v-model="item.industryType"
|
|
|
+ placeholder="请选择行业外分类"
|
|
|
+ :disabled="!isEditable"
|
|
|
+ >
|
|
|
+ <el-option label="海警机构" value="marine" />
|
|
|
+ <el-option label="公安机关" value="public" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="18">
|
|
|
+ <el-form-item label="行业外接收单位名称" prop="otherUnit">
|
|
|
+ <el-input
|
|
|
+ v-model="item.otherUnit"
|
|
|
+ placeholder="请输入行业外接收单位名称 如:XXX1海警机构,XXX2海警机构,XX公安机关"
|
|
|
+ maxlength="200"
|
|
|
+ :disabled="!isEditable"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-row :gutter="24">
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item label="安全管理建议" prop="penaltyFile">
|
|
|
+ <FileUpload v-model="item.penaltyFile"/>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item label="通报事项的相关证据" prop="safetySuggestion">
|
|
|
+ <FileUpload v-model="item.penaltyFile"/>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item label="通报事项的其他材料" prop="safetySuggestion">
|
|
|
+ <FileUpload v-model="item.penaltyFile"/>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+
|
|
|
+ <!-- 上传附件区域(核心改造) -->
|
|
|
+ <el-row :gutter="24" class="upload-area">
|
|
|
+ <el-col :span="24">
|
|
|
+ <div class="upload-cards">
|
|
|
+ <!-- 1. 行政处罚决定 -->
|
|
|
+ <div class="upload-card">
|
|
|
+ <div class="card-title">行政处罚决定</div>
|
|
|
+ <!-- 查看模式:显示下载链接 -->
|
|
|
+ <div v-if="!isEditable && item.attachments?.punishment?.length" class="file-link-list">
|
|
|
+ <div v-for="file in item.attachments.punishment" :key="file.id" class="file-link-item">
|
|
|
+ <el-link :href="file.url" target="_blank" :underline="false">
|
|
|
+ <el-icon><Document /></el-icon>
|
|
|
+ {{ file.name }}
|
|
|
+ </el-link>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- 编辑模式:上传组件(支持覆盖) -->
|
|
|
+ <el-upload
|
|
|
+ v-else-if="isEditable"
|
|
|
+ class="upload-demo"
|
|
|
+ drag
|
|
|
+ action="#"
|
|
|
+ :limit="1"
|
|
|
+ :file-list="item.attachments?.punishment || []"
|
|
|
+ :on-change="(file) => handleFileChange(file, item, 'punishment')"
|
|
|
+ :before-upload="beforeUpload"
|
|
|
+ >
|
|
|
+ <el-icon class="el-icon-upload"><UploadFilled /></el-icon>
|
|
|
+ <div class="el-upload__text">点击上传文件</div>
|
|
|
+ <div class="el-upload__tip" v-if="item.attachments?.punishment?.length">
|
|
|
+ 当前已上传:{{ item.attachments.punishment[0].name }} <span class="text-danger">(再次上传将覆盖)</span>
|
|
|
+ </div>
|
|
|
+ </el-upload>
|
|
|
+ <!-- 无文件时显示空状态 -->
|
|
|
+ <div v-else class="file-empty">暂无附件</div>
|
|
|
+ </div>
|
|
|
+ <!-- 2. 通报事项的相关证据(必填) -->
|
|
|
+ <div class="upload-card">
|
|
|
+ <div class="card-title">通报事项的相关证据 <span class="required-mark">*</span></div>
|
|
|
+ <!-- 查看模式:显示下载链接 -->
|
|
|
+ <div v-if="!isEditable && item.attachments?.evidence?.length" class="file-link-list">
|
|
|
+ <div v-for="file in item.attachments.evidence" :key="file.id" class="file-link-item">
|
|
|
+ <el-link :href="file.url" target="_blank" :underline="false">
|
|
|
+ <el-icon><Document /></el-icon>
|
|
|
+ {{ file.name }}
|
|
|
+ </el-link>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- 编辑模式:上传组件(支持覆盖) -->
|
|
|
+ <el-upload
|
|
|
+ v-else-if="isEditable"
|
|
|
+ class="upload-demo"
|
|
|
+ drag
|
|
|
+ action="#"
|
|
|
+ :limit="1"
|
|
|
+ :file-list="item.attachments?.evidence || []"
|
|
|
+ :on-change="(file) => handleFileChange(file, item, 'evidence')"
|
|
|
+ :before-upload="beforeUpload"
|
|
|
+ >
|
|
|
+ <el-icon class="el-icon-upload"><UploadFilled /></el-icon>
|
|
|
+ <div class="el-upload__text">点击上传文件</div>
|
|
|
+ <div class="el-upload__tip" v-if="item.attachments?.evidence?.length">
|
|
|
+ 当前已上传:{{ item.attachments.evidence[0].name }} <span class="text-danger">(再次上传将覆盖)</span>
|
|
|
+ </div>
|
|
|
+ </el-upload>
|
|
|
+ <!-- 无文件时显示空状态 -->
|
|
|
+ <div v-else class="file-empty">暂无附件</div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 3. 通报事项的其他材料 -->
|
|
|
+ <div class="upload-card">
|
|
|
+ <div class="card-title">通报事项的其他材料</div>
|
|
|
+ <!-- 查看模式:显示下载链接 -->
|
|
|
+ <div v-if="!isEditable && item.attachments?.other?.length" class="file-link-list">
|
|
|
+ <div v-for="file in item.attachments.other" :key="file.id" class="file-link-item">
|
|
|
+ <el-link :href="file.url" target="_blank" :underline="false">
|
|
|
+ <el-icon><Document /></el-icon>
|
|
|
+ {{ file.name }}
|
|
|
+ </el-link>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- 编辑模式:上传组件(支持覆盖) -->
|
|
|
+ <el-upload
|
|
|
+ v-else-if="isEditable"
|
|
|
+ class="upload-demo"
|
|
|
+ drag
|
|
|
+ action="#"
|
|
|
+ :limit="1"
|
|
|
+ :file-list="item.attachments?.other || []"
|
|
|
+ :on-change="(file) => handleFileChange(file, item, 'other')"
|
|
|
+ :before-upload="beforeUpload"
|
|
|
+ >
|
|
|
+ <el-icon class="el-icon-upload"><UploadFilled /></el-icon>
|
|
|
+ <div class="el-upload__text">点击上传文件</div>
|
|
|
+ <div class="el-upload__tip" v-if="item.attachments?.other?.length">
|
|
|
+ 当前已上传:{{ item.attachments.other[0].name }} <span class="text-danger">(再次上传将覆盖)</span>
|
|
|
+ </div>
|
|
|
+ </el-upload>
|
|
|
+ <!-- 无文件时显示空状态 -->
|
|
|
+ <div v-else class="file-empty">暂无附件</div>
|
|
|
+ </div>
|
|
|
+ <!-- <div class="upload-tip text-danger">
|
|
|
+ 提示:目前支持的文件格式:*.gif, *.jpeg, *.jpg, *.png, *.rar, *.zip, *.doc, *.ppt, *.xls, *.pdf, *.docx *.xlsx, *.bmp, *.xml,*.ofd,*.wps。文件大小支持:100M以内。
|
|
|
+ </div> -->
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <!-- 安全管理建议 -->
|
|
|
+ <el-row :gutter="24" class="mt-4">
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-form-item label="安全管理建议" prop="safetySuggestion" required>
|
|
|
+ <el-input
|
|
|
+ v-model="item.safetySuggestion"
|
|
|
+ type="textarea"
|
|
|
+ :rows="2"
|
|
|
+ placeholder="安全管理建议(内容200字以内)"
|
|
|
+ maxlength="200"
|
|
|
+ show-word-limit
|
|
|
+ :disabled="!isEditable"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <!-- 安全管理建议附件(核心改造) -->
|
|
|
+ <el-row :gutter="24">
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-form-item label="安全管理建议附件">
|
|
|
+ <!-- 查看模式:显示下载链接 -->
|
|
|
+ <div v-if="!isEditable && item.attachments?.suggestion?.length" class="file-link-list">
|
|
|
+ <div v-for="file in item.attachments.suggestion" :key="file.id" class="file-link-item">
|
|
|
+ <el-link :href="file.url" target="_blank" :underline="false">
|
|
|
+ <el-icon><Document /></el-icon>
|
|
|
+ {{ file.name }}
|
|
|
+ </el-link>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- 编辑模式:上传组件(支持覆盖) -->
|
|
|
+ <el-upload
|
|
|
+ v-else-if="isEditable"
|
|
|
+ class="upload-demo"
|
|
|
+ action="#"
|
|
|
+ :limit="1"
|
|
|
+ :file-list="item.attachments?.suggestion || []"
|
|
|
+ :on-change="(file) => handleFileChange(file, item, 'suggestion')"
|
|
|
+ :before-upload="beforeUpload"
|
|
|
+ >
|
|
|
+ <el-button size="small" type="primary">上传文件</el-button>
|
|
|
+ <!-- <div class="el-upload__tip" v-if="item.attachments?.suggestion?.length">
|
|
|
+ 当前已上传:{{ item.attachments.suggestion[0].name }} <span class="text-danger">(再次上传将覆盖)</span>
|
|
|
+ </div> -->
|
|
|
+ </el-upload>
|
|
|
+ <!-- 无文件时显示空状态 -->
|
|
|
+ <div v-else class="file-empty mt-2">暂无附件</div>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <!-- 是否需要反馈 -->
|
|
|
+ <el-row :gutter="24">
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-form-item label="是否需要反馈" prop="needFeedback" required>
|
|
|
+ <el-radio-group v-model="item.needFeedback" :disabled="!isEditable">
|
|
|
+ <el-radio label="no" border>否</el-radio>
|
|
|
+ <el-radio label="yes" border>是</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <!-- 分隔线(区分多个通报事项) -->
|
|
|
+ <el-divider v-if="index !== noticeItems.length - 1" />
|
|
|
+ </el-form>
|
|
|
+
|
|
|
+ <!-- 添加通报事项按钮 -->
|
|
|
+ <div class="add-matters" v-if="isEditable">
|
|
|
+ <el-button type="primary" plain :icon="Plus" @click="addNoticeItem">添加通报事项</el-button>
|
|
|
+ </div>
|
|
|
+ </el-collapse-item>
|
|
|
+ </el-collapse>
|
|
|
+ <MattersListDrawer
|
|
|
+ v-model:visible="drawerVisible"
|
|
|
+ @updateSelectedRow="updateSelectedRow"
|
|
|
+ :disabled="!isEditable"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup lang="ts">
|
|
|
+import { ref, reactive, defineEmits, defineExpose, onMounted, watch, computed } from 'vue';
|
|
|
+import { useRoute } from 'vue-router';
|
|
|
+import type { FormInstance, FormRules, UploadFile } from 'element-plus';
|
|
|
+import { UploadFilled, Plus, Delete, Document } from '@element-plus/icons-vue';
|
|
|
+import { ElMessage } from 'element-plus';
|
|
|
+import MattersListDrawer from './mattersListDrawer.vue';
|
|
|
+
|
|
|
+// 路由参数获取
|
|
|
+const route = useRoute();
|
|
|
+const currentType = ref<'add' | 'edit' | 'detail'>('add');
|
|
|
+const isEditable = computed(() => currentType.value === 'add' || currentType.value === 'edit');
|
|
|
+const activeNames = ref(['1']);
|
|
|
+
|
|
|
+// 附件类型定义
|
|
|
+interface AttachmentFile {
|
|
|
+ id: string; // 文件唯一标识
|
|
|
+ name: string; // 文件名
|
|
|
+ url: string; // 下载链接(查看模式)
|
|
|
+ raw?: File; // 原始文件(编辑模式上传用)
|
|
|
+ uid?: string; // element-plus upload 内部标识
|
|
|
+}
|
|
|
+
|
|
|
+// 通报事项类型定义
|
|
|
+interface NoticeItem {
|
|
|
+ noticeItem: string;
|
|
|
+ noticeStandard: string;
|
|
|
+ noticeType: 'info' | 'assist';
|
|
|
+ safetyInfo: string;
|
|
|
+ receiveUnit: string;
|
|
|
+ industryType: string;
|
|
|
+ otherUnit: string;
|
|
|
+ safetySuggestion: string;
|
|
|
+ needFeedback: 'yes' | 'no';
|
|
|
+ attachments?: {
|
|
|
+ punishment?: AttachmentFile[]; // 行政处罚决定
|
|
|
+ evidence?: AttachmentFile[]; // 通报事项的相关证据
|
|
|
+ other?: AttachmentFile[]; // 通报事项的其他材料
|
|
|
+ suggestion?: AttachmentFile[]; // 安全管理建议附件
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
+// 表单数据
|
|
|
+const noticeItems = ref([
|
|
|
+ {
|
|
|
+ noticeItem: '',
|
|
|
+ noticeStandard: '',
|
|
|
+ noticeType: 'info',
|
|
|
+ safetyInfo: '',
|
|
|
+ receiveUnit: '',
|
|
|
+ industryType: '',
|
|
|
+ otherUnit: '',
|
|
|
+ safetySuggestion: '',
|
|
|
+ needFeedback: 'no',
|
|
|
+ penaltyFile: '',
|
|
|
+ attachments: {
|
|
|
+ punishment: [],
|
|
|
+ evidence: [],
|
|
|
+ other: [],
|
|
|
+ suggestion: []
|
|
|
+ }
|
|
|
+ }
|
|
|
+]);
|
|
|
+
|
|
|
+// 表单引用
|
|
|
+const noticeFormRefs = ref<(FormInstance | undefined)[]>([]);
|
|
|
+
|
|
|
+// 表单验证规则
|
|
|
+const formRules = reactive<FormRules>({
|
|
|
+ noticeItem: [
|
|
|
+ { required: true, message: '请填写通报事项', trigger: 'blur' },
|
|
|
+ { max: 500, message: '长度不能超过500个字符', trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ noticeStandard: [
|
|
|
+ { required: true, message: '请输入通报标准或具体行为', trigger: 'blur' },
|
|
|
+ { max: 1000, message: '长度不能超过1000个字符', trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ noticeType: [
|
|
|
+ { required: true, message: '请选择通报类别', trigger: 'change' }
|
|
|
+ ],
|
|
|
+ safetyInfo: [
|
|
|
+ { required: true, message: '请填写水上交通安全信息', trigger: 'blur' },
|
|
|
+ { max: 3000, message: '长度不能超过3000个字符', trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ receiveUnit: [
|
|
|
+ { required: true, message: '请选择接收单位名称', trigger: 'change' }
|
|
|
+ ],
|
|
|
+ safetySuggestion: [
|
|
|
+ { required: true, message: '请填写安全管理建议', trigger: 'blur' },
|
|
|
+ { max: 200, message: '长度不能超过200个字符', trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ needFeedback: [
|
|
|
+ { required: true, message: '请选择是否需要反馈', trigger: 'change' }
|
|
|
+ ]
|
|
|
+});
|
|
|
+
|
|
|
+// 抽屉控制
|
|
|
+const drawerVisible = ref(false);
|
|
|
+const selectNoticeId = ref(0);
|
|
|
+
|
|
|
+// 初始化
|
|
|
+onMounted(() => {
|
|
|
+ // 从路由获取页面类型
|
|
|
+ const type = route.query.type as 'add' | 'edit' | 'detail';
|
|
|
+ if (['add', 'edit', 'detail'].includes(type)) {
|
|
|
+ currentType.value = type;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 编辑/详情模式加载数据
|
|
|
+ if (currentType.value === 'edit' || currentType.value === 'detail') {
|
|
|
+ fetchNoticeData();
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
+// 监听路由变化
|
|
|
+watch(
|
|
|
+ () => route.query.type,
|
|
|
+ (newType) => {
|
|
|
+ if (['add', 'edit', 'detail'].includes(newType as string)) {
|
|
|
+ currentType.value = newType as 'add' | 'edit' | 'detail';
|
|
|
+ currentType.value === 'add' ? resetAllForms() : fetchNoticeData();
|
|
|
+ }
|
|
|
+ }
|
|
|
+);
|
|
|
+
|
|
|
+// 模拟加载数据(edit/detail 场景)
|
|
|
+const fetchNoticeData = () => {
|
|
|
+ setTimeout(() => {
|
|
|
+ noticeItems.value = [
|
|
|
+ {
|
|
|
+ noticeItem: '未按规定配备救生设备',
|
|
|
+ noticeStandard: '根据《内河交通安全管理条例》第23条,船舶应配备符合标准的救生设备',
|
|
|
+ noticeType: 'info',
|
|
|
+ safetyInfo: '2023年10月15日,"扬子10"轮在长江口航行时,未按规定配备救生衣,违反安全管理规定。',
|
|
|
+ receiveUnit: 'unit1',
|
|
|
+ industryType: 'marine',
|
|
|
+ otherUnit: '东海海警机构',
|
|
|
+ safetySuggestion: '立即整改,配备足额救生设备并组织船员培训。',
|
|
|
+ needFeedback: 'yes',
|
|
|
+ attachments: {
|
|
|
+ // 模拟后端返回的附件数据(查看模式显示链接)
|
|
|
+ punishment: [
|
|
|
+ {
|
|
|
+ id: '1',
|
|
|
+ name: '行政处罚决定书.pdf',
|
|
|
+ url: 'https://example.com/files/punishment1.pdf'
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ evidence: [
|
|
|
+ {
|
|
|
+ id: '2',
|
|
|
+ name: '现场检查照片.jpg',
|
|
|
+ url: 'https://example.com/files/evidence1.jpg'
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ suggestion: [
|
|
|
+ {
|
|
|
+ id: '3',
|
|
|
+ name: '整改建议.docx',
|
|
|
+ url: 'https://example.com/files/suggestion1.docx'
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ];
|
|
|
+ }, 500);
|
|
|
+};
|
|
|
+
|
|
|
+// 通报事项选择
|
|
|
+const onClickNotice = (id: number) => {
|
|
|
+ selectNoticeId.value = id;
|
|
|
+ drawerVisible.value = true;
|
|
|
+};
|
|
|
+
|
|
|
+const updateSelectedRow = (row: any) => {
|
|
|
+ noticeItems.value[selectNoticeId.value] = { ...noticeItems.value[selectNoticeId.value], ...row };
|
|
|
+ drawerVisible.value = false;
|
|
|
+};
|
|
|
+
|
|
|
+// 文件上传变化(覆盖逻辑)
|
|
|
+const handleFileChange = (file: UploadFile, item: NoticeItem, type: 'punishment' | 'evidence' | 'other' | 'suggestion') => {
|
|
|
+ // 初始化附件对象
|
|
|
+ if (!item.attachments) {
|
|
|
+ item.attachments = {
|
|
|
+ punishment: [],
|
|
|
+ evidence: [],
|
|
|
+ other: [],
|
|
|
+ suggestion: []
|
|
|
+ };
|
|
|
+ }
|
|
|
+ // 覆盖上传(只保留最新1个文件)
|
|
|
+ item.attachments[type] = [file as AttachmentFile];
|
|
|
+};
|
|
|
+
|
|
|
+// 文件上传前校验
|
|
|
+const beforeUpload = (file: File) => {
|
|
|
+ // 实际项目中替换为真实上传逻辑
|
|
|
+ console.log('文件待上传:', file);
|
|
|
+ return false; // 阻止默认上传
|
|
|
+};
|
|
|
+
|
|
|
+// 删除通报事项
|
|
|
+const handleDelete = (index: number) => {
|
|
|
+ if (noticeItems.value.length <= 1) {
|
|
|
+ ElMessage.warning('至少保留一个通报事项');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ noticeItems.value.splice(index, 1);
|
|
|
+ noticeFormRefs.value.splice(index, 1);
|
|
|
+};
|
|
|
+
|
|
|
+// 添加通报事项
|
|
|
+const addNoticeItem = () => {
|
|
|
+ noticeItems.value.push({
|
|
|
+ noticeItem: '',
|
|
|
+ noticeStandard: '',
|
|
|
+ noticeType: 'info',
|
|
|
+ safetyInfo: '',
|
|
|
+ receiveUnit: '',
|
|
|
+ industryType: '',
|
|
|
+ otherUnit: '',
|
|
|
+ safetySuggestion: '',
|
|
|
+ needFeedback: 'no',
|
|
|
+ attachments: {
|
|
|
+ punishment: [],
|
|
|
+ evidence: [],
|
|
|
+ other: [],
|
|
|
+ suggestion: []
|
|
|
+ }
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+// 表单校验
|
|
|
+const validateForm = async () => {
|
|
|
+ let isAllValid = true;
|
|
|
+ for (let i = 0; i < noticeFormRefs.value.length; i++) {
|
|
|
+ const formRef = noticeFormRefs.value[i];
|
|
|
+ if (!formRef) continue;
|
|
|
+ try {
|
|
|
+ await formRef.validate();
|
|
|
+ } catch (error) {
|
|
|
+ isAllValid = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ emit('validate', isAllValid);
|
|
|
+ return isAllValid;
|
|
|
+};
|
|
|
+
|
|
|
+// 重置表单
|
|
|
+const resetAllForms = () => {
|
|
|
+ noticeItems.value = [{
|
|
|
+ noticeItem: '',
|
|
|
+ noticeStandard: '',
|
|
|
+ noticeType: 'info',
|
|
|
+ safetyInfo: '',
|
|
|
+ receiveUnit: '',
|
|
|
+ industryType: '',
|
|
|
+ otherUnit: '',
|
|
|
+ safetySuggestion: '',
|
|
|
+ needFeedback: 'no',
|
|
|
+ attachments: {
|
|
|
+ punishment: [],
|
|
|
+ evidence: [],
|
|
|
+ other: [],
|
|
|
+ suggestion: []
|
|
|
+ }
|
|
|
+ }];
|
|
|
+ noticeFormRefs.value.forEach(formRef => formRef?.resetFields());
|
|
|
+};
|
|
|
+
|
|
|
+// 暴露方法给父组件
|
|
|
+const emit = defineEmits<{
|
|
|
+ (e: 'validate', isValid: boolean): void;
|
|
|
+}>();
|
|
|
+
|
|
|
+defineExpose({
|
|
|
+ validateForm,
|
|
|
+ resetAllForms
|
|
|
+});
|
|
|
+</script>
|
|
|
+<style scoped lang="scss">
|
|
|
+@import "@/styles/waterSafetyInformation.scss";
|
|
|
+</style>
|