|
@@ -15,9 +15,8 @@
|
|
|
<!-- 通报信息标题 + 删除按钮 -->
|
|
|
<div class="notification-header">
|
|
|
<div class="notification-matters">{{ '通报信息' + (index + 1) }}</div>
|
|
|
- <!-- 删除按钮:仅当表单数量 > 1 时显示 -->
|
|
|
<el-button
|
|
|
- v-if="noticeItems.length > 1"
|
|
|
+ v-if="noticeItems.length > 1 && isEditable"
|
|
|
type="danger"
|
|
|
text
|
|
|
size="small"
|
|
@@ -33,14 +32,14 @@
|
|
|
<el-col :span="24">
|
|
|
<el-form-item label="通报事项" prop="noticeItem" required>
|
|
|
<el-button
|
|
|
- v-if="!drawerVisible && !item.noticeItem"
|
|
|
+ v-if="!drawerVisible && !item.noticeItem && isEditable"
|
|
|
@click="onClickNotice(index)"
|
|
|
- type="primary">
|
|
|
- 请选择通报事项
|
|
|
+ type="primary"
|
|
|
+ :disabled="!isEditable"
|
|
|
+ >
|
|
|
+ 请选择通报事项
|
|
|
</el-button>
|
|
|
- <div v-else>
|
|
|
- {{ item.noticeItem }}
|
|
|
- </div>
|
|
|
+ <el-input v-else disabled v-model="item.noticeItem" />
|
|
|
</el-form-item>
|
|
|
</el-col>
|
|
|
</el-row>
|
|
@@ -54,6 +53,7 @@
|
|
|
placeholder="请输入通报依据,内容1000字以内"
|
|
|
maxlength="1000"
|
|
|
show-word-limit
|
|
|
+ :disabled="!isEditable"
|
|
|
/>
|
|
|
</el-form-item>
|
|
|
</el-col>
|
|
@@ -63,7 +63,7 @@
|
|
|
<el-row :gutter="24">
|
|
|
<el-col :span="24">
|
|
|
<el-form-item label="通报类别" prop="noticeType" required>
|
|
|
- <el-radio-group v-model="item.noticeType">
|
|
|
+ <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>
|
|
@@ -82,6 +82,7 @@
|
|
|
placeholder="违法违规信息(内容3000字以内)"
|
|
|
maxlength="3000"
|
|
|
show-word-limit
|
|
|
+ :disabled="!isEditable"
|
|
|
/>
|
|
|
<div class="example-text mt-1 text-primary">
|
|
|
通报标准1:具体行为列举<br>
|
|
@@ -99,6 +100,7 @@
|
|
|
v-model="item.receiveUnit"
|
|
|
placeholder="请选择单位名称"
|
|
|
style="width: 100%"
|
|
|
+ :disabled="!isEditable"
|
|
|
>
|
|
|
<el-option label="单位名称1" value="unit1" />
|
|
|
<el-option label="单位名称2" value="unit2" />
|
|
@@ -114,6 +116,7 @@
|
|
|
<el-select
|
|
|
v-model="item.industryType"
|
|
|
placeholder="请选择行业外分类"
|
|
|
+ :disabled="!isEditable"
|
|
|
>
|
|
|
<el-option label="海警机构" value="marine" />
|
|
|
<el-option label="公安机关" value="public" />
|
|
@@ -126,53 +129,113 @@
|
|
|
v-model="item.otherUnit"
|
|
|
placeholder="请输入行业外接收单位名称 如:XXX1海警机构,XXX2海警机构,XX公安机关"
|
|
|
maxlength="200"
|
|
|
+ :disabled="!isEditable"
|
|
|
/>
|
|
|
</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="#"
|
|
|
- multiple
|
|
|
+ :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__text">点击上传文件(最多1个)</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="#"
|
|
|
- multiple
|
|
|
+ :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__text">点击上传文件(最多1个)</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="#"
|
|
|
- multiple
|
|
|
+ :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__text">点击上传文件(最多1个)</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以内。
|
|
@@ -192,27 +255,47 @@
|
|
|
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
|
|
|
- class="upload-demo mt-2"
|
|
|
+ v-else-if="isEditable"
|
|
|
+ class="upload-demo"
|
|
|
action="#"
|
|
|
- multiple
|
|
|
+ :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>
|
|
|
+ <el-button size="small" type="primary">上传文件(最多1个)</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>
|
|
|
+
|
|
|
+ <div class="upload-tip text-danger text-sm">
|
|
|
+ 提示:目前支持的文件格式:*.gif, *.jpeg, *.jpg, *.png, *.rar, *.zip, *.doc, *.ppt, *.xls, *.pdf, *.docx *.xlsx, *.bmp, *.xml,*.ofd,*.wps。文件大小支持:100M以内。
|
|
|
+ </div>
|
|
|
</el-form-item>
|
|
|
- <div class="upload-tip text-danger text-sm">
|
|
|
- 提示:目前支持的文件格式:*.gif, *.jpeg, *.jpg, *.png, *.rar, *.zip, *.doc, *.ppt, *.xls, *.pdf, *.docx *.xlsx, *.bmp, *.xml,*.ofd,*.wps。文件大小支持:100M以内。
|
|
|
- </div>
|
|
|
</el-col>
|
|
|
</el-row>
|
|
|
|
|
@@ -220,7 +303,7 @@
|
|
|
<el-row :gutter="24">
|
|
|
<el-col :span="24">
|
|
|
<el-form-item label="是否需要反馈" prop="needFeedback" required>
|
|
|
- <el-radio-group v-model="item.needFeedback" disabled>
|
|
|
+ <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>
|
|
@@ -233,39 +316,63 @@
|
|
|
</el-form>
|
|
|
|
|
|
<!-- 添加通报事项按钮 -->
|
|
|
- <div class="add-matters">
|
|
|
+ <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" />
|
|
|
+ @updateSelectedRow="updateSelectedRow"
|
|
|
+ :disabled="!isEditable"
|
|
|
+ />
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
-import { ref, reactive, defineEmits, defineExpose } from 'vue';
|
|
|
-import type { FormInstance, FormRules } from 'element-plus';
|
|
|
-import { UploadFilled, Plus, Delete } from '@element-plus/icons-vue';
|
|
|
+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']);
|
|
|
-const drawerVisible = ref(false);
|
|
|
|
|
|
-const noticeItems = ref([
|
|
|
- {
|
|
|
- noticeItem: '',
|
|
|
- noticeStandard: '',
|
|
|
- noticeType: 'info',
|
|
|
- safetyInfo: '',
|
|
|
- receiveUnit: '',
|
|
|
- industryType: '',
|
|
|
- otherUnit: '',
|
|
|
- safetySuggestion: '',
|
|
|
- needFeedback: 'no'
|
|
|
- },
|
|
|
+// 附件类型定义
|
|
|
+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[]>([
|
|
|
{
|
|
|
noticeItem: '',
|
|
|
noticeStandard: '',
|
|
@@ -275,12 +382,20 @@ const noticeItems = ref([
|
|
|
industryType: '',
|
|
|
otherUnit: '',
|
|
|
safetySuggestion: '',
|
|
|
- needFeedback: 'no'
|
|
|
+ needFeedback: 'no',
|
|
|
+ attachments: {
|
|
|
+ punishment: [],
|
|
|
+ evidence: [],
|
|
|
+ other: [],
|
|
|
+ suggestion: []
|
|
|
+ }
|
|
|
}
|
|
|
]);
|
|
|
|
|
|
+// 表单引用
|
|
|
const noticeFormRefs = ref<(FormInstance | undefined)[]>([]);
|
|
|
|
|
|
+// 表单验证规则
|
|
|
const formRules = reactive<FormRules>({
|
|
|
noticeItem: [
|
|
|
{ required: true, message: '请填写通报事项', trigger: 'blur' },
|
|
@@ -300,13 +415,6 @@ const formRules = reactive<FormRules>({
|
|
|
receiveUnit: [
|
|
|
{ required: true, message: '请选择接收单位名称', trigger: 'change' }
|
|
|
],
|
|
|
- otherUnit: [
|
|
|
- {
|
|
|
- pattern: /^[\u4e00-\u9fa5a-zA-Z0-9,,\s]{0,200}$/,
|
|
|
- message: '请输入合法的单位名称(支持中文、字母、数字和逗号)',
|
|
|
- trigger: 'blur'
|
|
|
- }
|
|
|
- ],
|
|
|
safetySuggestion: [
|
|
|
{ required: true, message: '请填写安全管理建议', trigger: 'blur' },
|
|
|
{ max: 200, message: '长度不能超过200个字符', trigger: 'blur' }
|
|
@@ -316,19 +424,112 @@ const formRules = reactive<FormRules>({
|
|
|
]
|
|
|
});
|
|
|
|
|
|
+// 抽屉控制
|
|
|
+const drawerVisible = ref(false);
|
|
|
const selectNoticeId = ref(0);
|
|
|
|
|
|
-const onClickNotice = (id) => {
|
|
|
- console.log(id);
|
|
|
+// 初始化
|
|
|
+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) => {
|
|
|
- noticeItems[selectNoticeId.value] = row;
|
|
|
+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('至少保留一个通报事项');
|
|
@@ -336,9 +537,9 @@ const handleDelete = (index: number) => {
|
|
|
}
|
|
|
noticeItems.value.splice(index, 1);
|
|
|
noticeFormRefs.value.splice(index, 1);
|
|
|
- noticeFormRefs.value = [];
|
|
|
};
|
|
|
|
|
|
+// 添加通报事项
|
|
|
const addNoticeItem = () => {
|
|
|
noticeItems.value.push({
|
|
|
noticeItem: '',
|
|
@@ -349,194 +550,64 @@ const addNoticeItem = () => {
|
|
|
industryType: '',
|
|
|
otherUnit: '',
|
|
|
safetySuggestion: '',
|
|
|
- needFeedback: 'no'
|
|
|
+ needFeedback: 'no',
|
|
|
+ attachments: {
|
|
|
+ punishment: [],
|
|
|
+ evidence: [],
|
|
|
+ other: [],
|
|
|
+ suggestion: []
|
|
|
+ }
|
|
|
});
|
|
|
- // 添加后表单实例会通过:ref自动绑定到noticeFormRefs
|
|
|
};
|
|
|
|
|
|
-// 批量校验所有动态表单
|
|
|
+// 表单校验
|
|
|
const validateForm = async () => {
|
|
|
let isAllValid = true;
|
|
|
- const invalidForms: { formIndex: number; fields: any }[] = [];
|
|
|
-
|
|
|
for (let i = 0; i < noticeFormRefs.value.length; i++) {
|
|
|
const formRef = noticeFormRefs.value[i];
|
|
|
if (!formRef) continue;
|
|
|
-
|
|
|
try {
|
|
|
await formRef.validate();
|
|
|
- } catch (error: any) {
|
|
|
+ } catch (error) {
|
|
|
isAllValid = false;
|
|
|
- invalidForms.push({ formIndex: i, fields: error.fields });
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- emit('validate', isAllValid, invalidForms);
|
|
|
+ emit('validate', isAllValid);
|
|
|
return isAllValid;
|
|
|
};
|
|
|
|
|
|
-// 重置所有表单
|
|
|
+// 重置表单
|
|
|
const resetAllForms = () => {
|
|
|
- noticeFormRefs.value.forEach(formRef => {
|
|
|
- formRef?.resetFields();
|
|
|
- });
|
|
|
+ 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, invalidForms?: { formIndex: number; fields: any }[]): void;
|
|
|
+ (e: 'validate', isValid: boolean): void;
|
|
|
}>();
|
|
|
|
|
|
-// 暴露方法给父组件
|
|
|
defineExpose({
|
|
|
validateForm,
|
|
|
resetAllForms
|
|
|
});
|
|
|
-
|
|
|
-// 文件上传前校验(示例)
|
|
|
-const beforeUpload = (file: File) => {
|
|
|
- console.log('文件上传前校验:', file.name);
|
|
|
- return false; // 阻止默认上传,实际项目中替换为真实上传逻辑
|
|
|
-};
|
|
|
</script>
|
|
|
-
|
|
|
<style scoped lang="scss">
|
|
|
-.ship-info-form {
|
|
|
- background: #fff;
|
|
|
- border-radius: 8px;
|
|
|
- padding: 20px;
|
|
|
- box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
|
|
|
-}
|
|
|
-
|
|
|
-// 折叠面板样式
|
|
|
-:deep .el-collapse-item__header {
|
|
|
- color: #5070ae;
|
|
|
- size: 24px;
|
|
|
- background: linear-gradient(135deg, #d2e8ff, #fcfeff);
|
|
|
- box-shadow: 0 8px 20px #fcfeff;
|
|
|
- text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
|
|
- padding-left: 20px;
|
|
|
-}
|
|
|
-
|
|
|
-:deep .el-collapse-item__content {
|
|
|
- padding-top: 25px;
|
|
|
-}
|
|
|
-
|
|
|
-// 表单标题+删除按钮容器
|
|
|
-.notification-header {
|
|
|
- display: flex;
|
|
|
- justify-content: space-between;
|
|
|
- align-items: center;
|
|
|
- margin-bottom: 20px;
|
|
|
-}
|
|
|
-
|
|
|
-// 通报事项标题样式
|
|
|
-.notification-matters {
|
|
|
- font-size: 20px;
|
|
|
- color: #163a8a;
|
|
|
- font-weight: 500;
|
|
|
- margin-bottom: 0;
|
|
|
-}
|
|
|
-
|
|
|
-// 删除按钮样式
|
|
|
-:deep .el-button--text {
|
|
|
- color: #f56c6c;
|
|
|
- &:hover {
|
|
|
- color: #ff4d4f;
|
|
|
- background: rgba(245, 108, 108, 0.1);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// 表单样式
|
|
|
-.notice-form {
|
|
|
- .el-form-item__label {
|
|
|
- color: #333;
|
|
|
- font-weight: 500;
|
|
|
- }
|
|
|
-
|
|
|
- .el-form-item {
|
|
|
- align-items: center;
|
|
|
- margin-bottom: 15px;
|
|
|
- }
|
|
|
-
|
|
|
- .example-text {
|
|
|
- font-size: 14px;
|
|
|
- line-height: 1.5;
|
|
|
- }
|
|
|
-
|
|
|
- .industry-row {
|
|
|
- margin-top: 15px;
|
|
|
- }
|
|
|
-
|
|
|
- .upload-area {
|
|
|
- margin: 20px 0;
|
|
|
-
|
|
|
- .upload-tip {
|
|
|
- font-size: 14px;
|
|
|
- line-height: 1.5;
|
|
|
- margin-bottom: 15px;
|
|
|
- }
|
|
|
-
|
|
|
- .upload-cards {
|
|
|
- display: flex;
|
|
|
- gap: 20px;
|
|
|
- flex-wrap: wrap;
|
|
|
-
|
|
|
- .upload-card {
|
|
|
- flex: 1;
|
|
|
- min-width: 250px;
|
|
|
- border: 1px dashed #e0e0e0;
|
|
|
- border-radius: 4px;
|
|
|
- padding: 15px;
|
|
|
-
|
|
|
- .card-title {
|
|
|
- font-weight: 500;
|
|
|
- margin-bottom: 10px;
|
|
|
- color: #333;
|
|
|
-
|
|
|
- .required-mark {
|
|
|
- color: #f56c6c;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- .upload-tip {
|
|
|
- font-size: 14px;
|
|
|
- line-height: 1.5;
|
|
|
- margin-bottom: 20px;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// 上传组件样式
|
|
|
-:deep .el-upload--text {
|
|
|
- .el-upload-dragger {
|
|
|
- padding: 30px 0;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// 添加按钮样式
|
|
|
-.add-matters {
|
|
|
- display: flex;
|
|
|
- justify-content: center;
|
|
|
- margin-top: 20px;
|
|
|
-}
|
|
|
-
|
|
|
-// 分隔线样式
|
|
|
-:deep .el-divider {
|
|
|
- margin: 25px 0;
|
|
|
- border-color: #f0f0f0;
|
|
|
-}
|
|
|
-
|
|
|
-// 响应式调整
|
|
|
-@media (max-width: 768px) {
|
|
|
- .notice-form .upload-cards {
|
|
|
- flex-direction: column;
|
|
|
- }
|
|
|
-
|
|
|
- .notification-matters {
|
|
|
- font-size: 18px;
|
|
|
- }
|
|
|
-}
|
|
|
+@import "@/styles/waterSafetyInformation.scss";
|
|
|
</style>
|