diff --git a/src/views/review/meeting/MeetingEdit.vue b/src/views/review/meeting/MeetingEdit.vue
index 9329c9f0a..239c28865 100644
--- a/src/views/review/meeting/MeetingEdit.vue
+++ b/src/views/review/meeting/MeetingEdit.vue
@@ -187,10 +187,10 @@
v-if="!isView"
type="button"
class="btn-primary"
- :disabled="formLoading"
+ :disabled="formLoading || isSubmitting"
@click="submitForm"
>
- {{ formLoading ? '提交中...' : '提交' }}
+ {{ formLoading || isSubmitting ? '提交中...' : '提交' }}
@@ -239,8 +239,8 @@
-
- 确定
+
+ {{ agendaDialogLoading || isSubmitting ? '提交中...' : '确定' }}
@@ -291,6 +291,7 @@ const formLoading = ref(false)
const expertOptions = ref([])
const isProjectsModified = ref(false)
const meetingLocationOptions = ['东5楼326', '南6楼203', '南6楼207']
+const isSubmitting = ref(false) // 防止重复提交
// 上传会议附件弹窗
const agendaDialogVisible = ref(false)
@@ -619,7 +620,7 @@ const buildAgendaGenerateData = (): ReviewMeetingAgendaGenerateReqVO | undefined
}
const submitForm = async () => {
- if (formLoading.value) return
+ if (formLoading.value || isSubmitting.value) return
const valid = await formRef.value?.validate().catch(() => false)
if (!valid) return
if (formData.meetingTimeRange?.length === 2) {
@@ -628,6 +629,7 @@ const submitForm = async () => {
}
// 编辑模式且有议程附件:直接保存
if (isEdit.value && formData.agendaAttachmentUrl) {
+ isSubmitting.value = true
formLoading.value = true
try {
const projects = buildScheduledProjects()
@@ -658,6 +660,7 @@ const submitForm = async () => {
router.push({ name: 'ReviewMeeting' })
} finally {
formLoading.value = false
+ isSubmitting.value = false
}
} else {
// 新建模式或编辑模式下议程附件为空:弹出上传议程附件弹窗
@@ -711,10 +714,12 @@ const handleDialogGenerateAgenda = async () => {
// 弹窗确定按钮 - 真正保存草稿
const handleDialogConfirm = async () => {
+ if (agendaDialogLoading.value || isSubmitting.value) return
if (!formData.agendaAttachmentUrl) {
ElMessage.warning('请上传或生成议程附件')
return
}
+ isSubmitting.value = true
agendaDialogLoading.value = true
try {
const projects = buildScheduledProjects()
@@ -736,6 +741,7 @@ const handleDialogConfirm = async () => {
router.push({ name: 'ReviewMeeting' })
} finally {
agendaDialogLoading.value = false
+ isSubmitting.value = false
}
}
@@ -1031,38 +1037,87 @@ const handleBack = () => {
.attachment-cards {
display: flex;
gap: 12px;
+ flex-wrap: wrap;
}
.attachment-card {
- flex: 1;
- background-color: #fff;
- border: 1px solid #e1e7f0;
- border-radius: 4px;
- overflow: hidden;
+ background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
+ border: 1px solid #e8eaef;
+ border-radius: 8px;
+ padding: 12px 14px;
+ min-width: 320px;
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
+ transition: all 0.2s ease;
+}
+.attachment-card:hover {
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
+ border-color: #d0d4dc;
}
.attachment-card-header {
- padding: 1px 6px;
- background-color: #f5f7fa;
- border-bottom: 1px solid #e1e7f0;
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ margin-bottom: 8px;
}
.attachment-card-title {
font-size: 12px;
font-weight: 600;
- color: #333;
+ color: #6b7280;
+ text-transform: uppercase;
+ letter-spacing: 0.3px;
}
.attachment-card-body {
- padding: 2px 6px;
+ display: flex;
+ flex-direction: column;
+ gap: 6px;
}
.attachment-file-info {
display: flex;
align-items: center;
- gap: 4px;
+ gap: 8px;
flex-wrap: wrap;
+ min-width: 0;
+}
+.attachment-file-info .el-link {
+ font-size: 13px;
+ color: #3b82f6;
+ font-weight: 500;
+ word-break: break-all;
+ flex: 1;
+ min-width: 100px;
+}
+.attachment-file-info .el-link:hover {
+ text-decoration: underline;
+}
+.attachment-file-info .el-tag {
+ background-color: #eef2ff;
+ color: #6366f1;
+ border-color: #e0e7ff;
+ font-weight: 500;
+}
+.attachment-file-info .el-text {
+ color: #9ca3af;
+ font-size: 12px;
+}
+.attachment-file-info .el-button {
+ color: #ef4444;
+ font-size: 12px;
+}
+.attachment-file-info .el-button:hover {
+ color: #dc2626;
}
.minutes-ai-line {
- margin-top: 2px;
display: flex;
align-items: center;
- gap: 4px;
+ gap: 6px;
flex-wrap: wrap;
+ padding-top: 4px;
+ border-top: 1px solid #f0f0f0;
+}
+.minutes-ai-line .el-tag {
+ font-weight: 500;
+}
+.minutes-ai-line .el-text {
+ color: #9ca3af;
+ font-size: 11px;
}