feat(review-meeting): 会议列表操作下拉化并支持弹窗预览纪要
parent
506c26f7ab
commit
0b140a145e
|
|
@ -91,84 +91,105 @@
|
|||
</el-table-column>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
width="600"
|
||||
width="180"
|
||||
align="center"
|
||||
:fixed="useFixedActionColumn ? 'right' : false"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<template v-if="row.status === 0">
|
||||
<div class="op-group">
|
||||
<a v-hasPermi="['review:meeting:update']" class="op-link" @click="goToEdit(row.id)"
|
||||
>编辑</a
|
||||
>
|
||||
<a
|
||||
v-hasPermi="['review:meeting:send-sms']"
|
||||
class="op-link"
|
||||
@click="handleSendSms(row)"
|
||||
>发送短信邀约</a
|
||||
>
|
||||
<a
|
||||
v-hasPermi="['review:meeting:cancel']"
|
||||
class="op-link op-danger"
|
||||
@click="handleCancel(row)"
|
||||
>取消</a
|
||||
<div class="op-group compact">
|
||||
<el-dropdown
|
||||
trigger="click"
|
||||
@command="(command: string) => handleActionCommand(row, command)"
|
||||
>
|
||||
<span class="op-dropdown-trigger">更多</span>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item v-hasPermi="['review:meeting:update']" command="edit">
|
||||
编辑
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item v-hasPermi="['review:meeting:send-sms']" command="sendSms">
|
||||
发送短信邀约
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
v-hasPermi="['review:meeting:cancel']"
|
||||
command="cancel"
|
||||
class="danger-dropdown-item"
|
||||
>
|
||||
取消
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="row.status === 1">
|
||||
<div class="op-group">
|
||||
<a class="op-link" @click="goToEdit(row.id, 'view')">查看</a>
|
||||
<a
|
||||
v-hasPermi="['review:meeting:send-sms']"
|
||||
class="op-link"
|
||||
@click="openSmsStatus(row)"
|
||||
>短信状态</a
|
||||
>
|
||||
<a
|
||||
v-if="row.mailSent"
|
||||
v-hasPermi="['review:meeting:send-mail']"
|
||||
class="op-link"
|
||||
@click="openMailStatus(row)"
|
||||
>邮件状态</a
|
||||
>
|
||||
<a
|
||||
v-else
|
||||
v-hasPermi="['review:meeting:send-mail']"
|
||||
class="op-link"
|
||||
@click="handleSendMail(row)"
|
||||
>发送议程</a
|
||||
>
|
||||
<a
|
||||
v-hasPermi="['review:meeting:update']"
|
||||
class="op-link"
|
||||
@click="triggerUploadMinutes(row)"
|
||||
>上传纪要</a
|
||||
>
|
||||
<a
|
||||
v-hasPermi="['review:meeting:export']"
|
||||
class="op-link"
|
||||
:class="{ disabled: isExporting(row.id) }"
|
||||
@click="handleExportMaterials(row)"
|
||||
>
|
||||
{{ getExportText(row.id) }}
|
||||
</a>
|
||||
<a v-hasPermi="['review:meeting:finish']" class="op-link" @click="handleFinish(row)"
|
||||
>结束</a
|
||||
>
|
||||
<a
|
||||
v-hasPermi="['review:meeting:cancel']"
|
||||
class="op-link op-danger"
|
||||
@click="handleCancel(row)"
|
||||
>取消</a
|
||||
<div class="op-group compact">
|
||||
<el-dropdown
|
||||
trigger="click"
|
||||
@command="(command: string) => handleActionCommand(row, command)"
|
||||
>
|
||||
<span class="op-dropdown-trigger">更多</span>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item command="view">查看</el-dropdown-item>
|
||||
<el-dropdown-item v-hasPermi="['review:meeting:send-sms']" command="smsStatus">
|
||||
短信状态
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
v-hasPermi="['review:meeting:send-mail']"
|
||||
:command="row.mailSent ? 'mailStatus' : 'sendMail'"
|
||||
>
|
||||
{{ row.mailSent ? '邮件状态' : '发送议程' }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item v-if="hasMinutesAttachment(row)" command="previewMinutes">
|
||||
预览纪要
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item v-hasPermi="['review:meeting:update']" command="uploadMinutes">
|
||||
{{ hasMinutesAttachment(row) ? '重新上传纪要' : '上传纪要' }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
v-hasPermi="['review:meeting:export']"
|
||||
command="export"
|
||||
:disabled="isExporting(row.id)"
|
||||
>
|
||||
{{ getExportText(row.id) }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
v-hasPermi="['review:meeting:finish']"
|
||||
command="finish"
|
||||
class="danger-dropdown-item"
|
||||
>
|
||||
结束
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
v-hasPermi="['review:meeting:cancel']"
|
||||
command="cancel"
|
||||
class="danger-dropdown-item"
|
||||
>
|
||||
取消
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="op-group">
|
||||
<a class="op-link" @click="goToEdit(row.id, 'view')">查看</a>
|
||||
<a v-hasPermi="['review:meeting:create']" class="op-link" @click="handleCopy(row)"
|
||||
>复制新会议</a
|
||||
<div class="op-group compact">
|
||||
<el-dropdown
|
||||
trigger="click"
|
||||
@command="(command: string) => handleActionCommand(row, command)"
|
||||
>
|
||||
<span class="op-dropdown-trigger">更多</span>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item command="view">查看</el-dropdown-item>
|
||||
<el-dropdown-item v-hasPermi="['review:meeting:create']" command="copy">
|
||||
复制新会议
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
|
@ -189,6 +210,13 @@
|
|||
<!-- 邮件状态弹窗 -->
|
||||
<MailStatusDialog ref="mailStatusRef" />
|
||||
|
||||
<FilePreviewDialog
|
||||
v-model="minutesPreviewVisible"
|
||||
:meeting-id="minutesPreviewMeetingId"
|
||||
attachment-type="minutes"
|
||||
:file-name="minutesPreviewFileName"
|
||||
/>
|
||||
|
||||
<input
|
||||
ref="minutesUploadInputRef"
|
||||
type="file"
|
||||
|
|
@ -221,6 +249,7 @@ import {
|
|||
} from '@/api/review/meeting'
|
||||
import SmsStatusDialog from './SmsStatusDialog.vue'
|
||||
import MailStatusDialog from './MailStatusDialog.vue'
|
||||
import FilePreviewDialog from './components/FilePreviewDialog.vue'
|
||||
import { formatDate } from '@/utils/formatTime'
|
||||
import download from '@/utils/download'
|
||||
|
||||
|
|
@ -259,6 +288,9 @@ const smsStatusRef = ref()
|
|||
const mailStatusRef = ref()
|
||||
const minutesUploadInputRef = ref<HTMLInputElement>()
|
||||
const pendingMinutesMeeting = ref<ReviewMeetingRespVO>()
|
||||
const minutesPreviewVisible = ref(false)
|
||||
const minutesPreviewMeetingId = ref(0)
|
||||
const minutesPreviewFileName = ref('')
|
||||
const exportTaskMap = reactive<Record<number, ReviewMeetingMaterialExportTaskRespVO | undefined>>(
|
||||
{}
|
||||
)
|
||||
|
|
@ -356,11 +388,80 @@ const handleCopy = async (row: ReviewMeetingRespVO) => {
|
|||
})
|
||||
}
|
||||
|
||||
type MeetingActionCommand =
|
||||
| 'edit'
|
||||
| 'view'
|
||||
| 'sendSms'
|
||||
| 'smsStatus'
|
||||
| 'mailStatus'
|
||||
| 'sendMail'
|
||||
| 'previewMinutes'
|
||||
| 'uploadMinutes'
|
||||
| 'export'
|
||||
| 'finish'
|
||||
| 'cancel'
|
||||
| 'copy'
|
||||
|
||||
const handleActionCommand = async (row: ReviewMeetingRespVO, command: string) => {
|
||||
const action = command as MeetingActionCommand
|
||||
switch (action) {
|
||||
case 'edit':
|
||||
goToEdit(row.id)
|
||||
break
|
||||
case 'view':
|
||||
goToEdit(row.id, 'view')
|
||||
break
|
||||
case 'sendSms':
|
||||
await handleSendSms(row)
|
||||
break
|
||||
case 'smsStatus':
|
||||
openSmsStatus(row)
|
||||
break
|
||||
case 'mailStatus':
|
||||
openMailStatus(row)
|
||||
break
|
||||
case 'sendMail':
|
||||
await handleSendMail(row)
|
||||
break
|
||||
case 'previewMinutes':
|
||||
handlePreviewMinutes(row)
|
||||
break
|
||||
case 'uploadMinutes':
|
||||
triggerUploadMinutes(row)
|
||||
break
|
||||
case 'export':
|
||||
await handleExportMaterials(row)
|
||||
break
|
||||
case 'finish':
|
||||
await handleFinish(row)
|
||||
break
|
||||
case 'cancel':
|
||||
await handleCancel(row)
|
||||
break
|
||||
case 'copy':
|
||||
await handleCopy(row)
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
const triggerUploadMinutes = (row: ReviewMeetingRespVO) => {
|
||||
pendingMinutesMeeting.value = row
|
||||
minutesUploadInputRef.value?.click()
|
||||
}
|
||||
|
||||
const hasMinutesAttachment = (row: ReviewMeetingRespVO) => !!row.minutesAttachmentUrl
|
||||
|
||||
const handlePreviewMinutes = (row: ReviewMeetingRespVO) => {
|
||||
if (!hasMinutesAttachment(row)) {
|
||||
return
|
||||
}
|
||||
minutesPreviewMeetingId.value = row.id
|
||||
minutesPreviewFileName.value = row.minutesAttachmentName || ''
|
||||
minutesPreviewVisible.value = true
|
||||
}
|
||||
|
||||
const handleMinutesFileChange = async (event: Event) => {
|
||||
const input = event.target as HTMLInputElement
|
||||
const file = input.files?.[0]
|
||||
|
|
@ -377,9 +478,14 @@ const handleMinutesFileChange = async (event: Event) => {
|
|||
return
|
||||
}
|
||||
try {
|
||||
await uploadMinutesAttachment(pendingMinutesMeeting.value.id, file)
|
||||
const meeting = pendingMinutesMeeting.value
|
||||
const attachment = await uploadMinutesAttachment(meeting.id, file)
|
||||
meeting.minutesAttachmentName = attachment.name
|
||||
meeting.minutesAttachmentUrl = attachment.url
|
||||
meeting.minutesAttachmentType = attachment.type
|
||||
meeting.minutesAttachmentSize = attachment.size
|
||||
ElMessage.success('会议纪要上传成功,整改通知后台生成中')
|
||||
getList()
|
||||
await getList()
|
||||
} finally {
|
||||
input.value = ''
|
||||
pendingMinutesMeeting.value = undefined
|
||||
|
|
@ -729,6 +835,40 @@ onBeforeUnmount(() => {
|
|||
.op-link.disabled:hover {
|
||||
color: #8a94a6;
|
||||
}
|
||||
.op-group.compact {
|
||||
gap: 0;
|
||||
}
|
||||
.op-dropdown-trigger {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
color: #295abc;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
.op-dropdown-trigger::after {
|
||||
content: '';
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
margin-top: -3px;
|
||||
border-right: 1.5px solid currentColor;
|
||||
border-bottom: 1.5px solid currentColor;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
.op-dropdown-trigger:hover {
|
||||
color: #1f4ca5;
|
||||
text-decoration: underline;
|
||||
}
|
||||
:deep(.el-dropdown-menu__item.danger-dropdown-item) {
|
||||
color: #d63b42;
|
||||
}
|
||||
:deep(.el-dropdown-menu__item.danger-dropdown-item:not(.is-disabled):focus) {
|
||||
color: #c22e35;
|
||||
background-color: rgba(252, 79, 84, 0.12);
|
||||
}
|
||||
|
||||
/* ── 表格样式 ── */
|
||||
:deep(.review-table .el-table__header-wrapper th) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue