fix(review-meeting): 优化会议附件卡片样式并防止重复提交

- 优化卡片布局为现代风格,支持长文件名完整显示
- 添加 isSubmitting 状态防止快速连续点击导致重复创建会议
- 按钮在提交中禁用并显示"提交中..."文字

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
pull/874/head
Codewoc 2026-04-10 14:14:25 +08:00
parent b3eaefc511
commit 9b94f733ba
1 changed files with 73 additions and 18 deletions

View File

@ -187,10 +187,10 @@
v-if="!isView"
type="button"
class="btn-primary"
:disabled="formLoading"
:disabled="formLoading || isSubmitting"
@click="submitForm"
>
{{ formLoading ? '提交中...' : '提交' }}
{{ formLoading || isSubmitting ? '提交中...' : '提交' }}
</button>
<button type="button" class="btn-default" @click="handleBack"></button>
</div>
@ -239,8 +239,8 @@
</div>
</div>
<template #footer>
<el-button type="primary" :disabled="agendaDialogLoading" @click="handleDialogConfirm">
确定
<el-button type="primary" :disabled="agendaDialogLoading || isSubmitting" @click="handleDialogConfirm">
{{ agendaDialogLoading || isSubmitting ? '提交中...' : '确定' }}
</el-button>
</template>
</el-dialog>
@ -291,6 +291,7 @@ const formLoading = ref(false)
const expertOptions = ref<any[]>([])
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;
}
</style>