feat(review-meeting): 增加评审结果筛选并优化列表布局

pull/874/head
Codewoc 2026-03-27 09:44:52 +08:00
parent 00f3b0f7ec
commit 91b550fb1e
4 changed files with 102 additions and 38 deletions

View File

@ -38,6 +38,7 @@ export interface ReviewMeetingProjectPageReqVO {
projectTitle?: string projectTitle?: string
agendaCategory?: string agendaCategory?: string
reporter?: string reporter?: string
reviewResult?: 'PASS' | 'REJECT'
reviewDate?: string reviewDate?: string
} }
@ -50,6 +51,7 @@ export interface ReviewProjectPageReqVO {
agendaCategory?: string agendaCategory?: string
reporter?: string reporter?: string
reporterUnit?: string reporterUnit?: string
reviewResult?: 'PASS' | 'REJECT'
reviewDate?: string reviewDate?: string
} }

View File

@ -2,29 +2,29 @@
<div class="app-container"> <div class="app-container">
<!-- 搜索工作栏 --> <!-- 搜索工作栏 -->
<el-card shadow="never" class="search-wrapper"> <el-card shadow="never" class="search-wrapper">
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px"> <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px" class="search-form">
<el-form-item label="项目名称" prop="projectName"> <el-form-item label="项目名称" prop="projectName">
<el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable class="!w-240px" @keyup.enter="handleQuery" /> <el-input v-model="queryParams.projectName" size="large" placeholder="请输入项目名称" clearable class="!w-240px" @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item label="项目编号" prop="projectCode"> <el-form-item label="项目编号" prop="projectCode">
<el-input v-model="queryParams.projectCode" placeholder="请输入项目编号" clearable class="!w-240px" @keyup.enter="handleQuery" /> <el-input v-model="queryParams.projectCode" size="large" placeholder="请输入项目编号" clearable class="!w-240px" @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item label="申报单位" prop="applyUnit"> <el-form-item label="申报单位" prop="applyUnit">
<el-input v-model="queryParams.applyUnit" placeholder="请输入申报单位" clearable class="!w-240px" @keyup.enter="handleQuery" /> <el-input v-model="queryParams.applyUnit" size="large" placeholder="请输入申报单位" clearable class="!w-240px" @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item label="项目状态" prop="status"> <el-form-item label="项目状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择项目状态" clearable class="!w-240px"> <el-select v-model="queryParams.status" size="large" placeholder="请选择项目状态" clearable class="!w-240px">
<el-option label="待验收" value="0" /> <el-option label="待验收" value="0" />
<el-option label="验收中" value="1" /> <el-option label="验收中" value="1" />
<el-option label="已完成" value="2" /> <el-option label="已完成" value="2" />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="创建时间" prop="createTime"> <el-form-item label="创建时间" prop="createTime">
<el-date-picker v-model="queryParams.createTime" value-format="YYYY-MM-DD HH:mm:ss" type="daterange" start-placeholder="" end-placeholder="" class="!w-240px" /> <el-date-picker v-model="queryParams.createTime" size="large" value-format="YYYY-MM-DD HH:mm:ss" type="daterange" start-placeholder="" end-placeholder="" class="!w-240px" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> <el-button size="large" @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button> <el-button size="large" @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -481,4 +481,13 @@ onMounted(() => {
:deep(.el-form-item) { :deep(.el-form-item) {
margin-bottom: 12px; margin-bottom: 12px;
} }
:deep(.search-form .el-input__wrapper),
:deep(.search-form .el-select__wrapper) {
min-height: 40px;
}
:deep(.search-form .el-input__inner) {
line-height: 40px;
}
</style> </style>

View File

@ -8,6 +8,7 @@
<el-select <el-select
v-model="queryParams.reviewMeetingId" v-model="queryParams.reviewMeetingId"
placeholder="所属会议" placeholder="所属会议"
size="large"
clearable clearable
filterable filterable
class="search-meeting-select" class="search-meeting-select"
@ -22,6 +23,7 @@
<el-input <el-input
v-model="queryParams.projectTitle" v-model="queryParams.projectTitle"
placeholder="项目标题" placeholder="项目标题"
size="large"
clearable clearable
class="search-input" class="search-input"
@keyup.enter="handleQuery" @keyup.enter="handleQuery"
@ -29,6 +31,7 @@
<el-input <el-input
v-model="queryParams.reporter" v-model="queryParams.reporter"
placeholder="报告人" placeholder="报告人"
size="large"
clearable clearable
class="search-input-sm" class="search-input-sm"
@keyup.enter="handleQuery" @keyup.enter="handleQuery"
@ -36,16 +39,22 @@
<el-input <el-input
v-model="queryParams.reporterUnit" v-model="queryParams.reporterUnit"
placeholder="报告单位" placeholder="报告单位"
size="large"
clearable clearable
class="search-input" class="search-input"
@keyup.enter="handleQuery" @keyup.enter="handleQuery"
/> />
<el-select v-model="queryParams.agendaCategory" placeholder="议程分类" clearable class="search-input"> <el-select v-model="queryParams.agendaCategory" placeholder="议程分类" size="large" clearable class="search-input">
<el-option v-for="item in REVIEW_AGENDA_CATEGORY_OPTIONS" :key="item" :label="item" :value="item" /> <el-option v-for="item in REVIEW_AGENDA_CATEGORY_OPTIONS" :key="item" :label="item" :value="item" />
</el-select> </el-select>
<el-select v-model="queryParams.reviewResult" placeholder="评审结果" size="large" clearable class="search-input">
<el-option label="通过" value="PASS" />
<el-option label="不通过" value="REJECT" />
</el-select>
<el-date-picker <el-date-picker
v-model="queryParams.reviewDate" v-model="queryParams.reviewDate"
type="date" type="date"
size="large"
value-format="YYYY-MM-DD" value-format="YYYY-MM-DD"
placeholder="评审日期" placeholder="评审日期"
clearable clearable
@ -209,6 +218,7 @@ const queryParams = reactive<ReviewProjectPageReqVO & { pageNo: number; pageSize
agendaCategory: undefined, agendaCategory: undefined,
reporter: undefined, reporter: undefined,
reporterUnit: undefined, reporterUnit: undefined,
reviewResult: undefined,
reviewDate: undefined reviewDate: undefined
}) })
@ -235,6 +245,7 @@ const resetQuery = () => {
queryParams.agendaCategory = undefined queryParams.agendaCategory = undefined
queryParams.reporter = undefined queryParams.reporter = undefined
queryParams.reporterUnit = undefined queryParams.reporterUnit = undefined
queryParams.reviewResult = undefined
queryParams.reviewDate = undefined queryParams.reviewDate = undefined
handleQuery() handleQuery()
} }
@ -353,16 +364,34 @@ onMounted(async () => {
.search-input-sm { .search-input-sm {
width: 120px; width: 120px;
} }
:deep(.search-meeting-select),
:deep(.search-input),
:deep(.search-input-sm) {
height: 40px;
}
:deep(.search-meeting-select .el-input__wrapper), :deep(.search-meeting-select .el-input__wrapper),
:deep(.search-input .el-input__wrapper), :deep(.search-input .el-input__wrapper),
:deep(.search-input-sm .el-input__wrapper) { :deep(.search-input-sm .el-input__wrapper) {
height: 40px; min-height: 40px;
border-radius: 6px; border-radius: 6px;
border-color: #dcdedf; border-color: #dcdedf;
} }
:deep(.search-meeting-select .el-select__wrapper),
:deep(.search-input .el-select__wrapper),
:deep(.search-input-sm .el-select__wrapper) {
min-height: 40px;
border-radius: 6px;
border-color: #dcdedf;
}
:deep(.search-meeting-select.el-date-editor),
:deep(.search-input.el-date-editor),
:deep(.search-input-sm.el-date-editor) {
min-height: 40px;
}
:deep(.search-meeting-select .el-input__inner), :deep(.search-meeting-select .el-input__inner),
:deep(.search-input .el-input__inner), :deep(.search-input .el-input__inner),
:deep(.search-input-sm .el-input__inner) { :deep(.search-input-sm .el-input__inner) {
line-height: 40px;
font-size: 15px; font-size: 15px;
color: #333; color: #333;
} }

View File

@ -7,6 +7,7 @@
<div class="search-bar"> <div class="search-bar">
<el-input <el-input
v-model="queryParams.name" v-model="queryParams.name"
size="large"
placeholder="搜索会议名称" placeholder="搜索会议名称"
clearable clearable
class="search-input" class="search-input"
@ -14,6 +15,7 @@
/> />
<el-date-picker <el-date-picker
v-model="queryParams.startTime" v-model="queryParams.startTime"
size="large"
type="datetimerange" type="datetimerange"
range-separator="至" range-separator="至"
start-placeholder="会议开始时间" start-placeholder="会议开始时间"
@ -21,7 +23,7 @@
value-format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss"
class="search-datepicker" class="search-datepicker"
/> />
<el-select v-model="queryParams.status" placeholder="会议状态" clearable class="search-select"> <el-select v-model="queryParams.status" size="large" placeholder="会议状态" clearable class="search-select">
<el-option v-for="item in MEETING_STATUS_OPTIONS" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in MEETING_STATUS_OPTIONS" :key="item.value" :label="item.label" :value="item.value" />
</el-select> </el-select>
<button class="btn-reset" @click="resetQuery"></button> <button class="btn-reset" @click="resetQuery"></button>
@ -38,18 +40,18 @@
<!-- 列表 --> <!-- 列表 -->
<el-table v-loading="loading" :data="list" class="review-table" border> <el-table v-loading="loading" :data="list" class="review-table" border>
<el-table-column label="编号" prop="id" width="70" align="center" /> <el-table-column label="编号" prop="id" width="70" align="center" />
<el-table-column label="会议名称" min-width="200"> <el-table-column label="会议名称" min-width="170">
<template #default="{ row }"> <template #default="{ row }">
<span class="meeting-name-link" @click="goToProjectList(row)">{{ row.name }}</span> <span class="meeting-name-link" @click="goToProjectList(row)">{{ row.name }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="会议开始时间" width="150"> <el-table-column label="会议开始时间" width="180">
<template #default="{ row }">{{ formatDate(row.startTime, 'YYYY-MM-DD HH:mm') }}</template> <template #default="{ row }">{{ formatDate(row.startTime, 'YYYY-MM-DD HH:mm') }}</template>
</el-table-column> </el-table-column>
<el-table-column label="会议结束时间" width="150"> <el-table-column label="会议结束时间" width="180">
<template #default="{ row }">{{ formatDate(row.endTime, 'YYYY-MM-DD HH:mm') }}</template> <template #default="{ row }">{{ formatDate(row.endTime, 'YYYY-MM-DD HH:mm') }}</template>
</el-table-column> </el-table-column>
<el-table-column label="会议地点" prop="location" show-overflow-tooltip /> <el-table-column label="会议地点" prop="location" width="130" show-overflow-tooltip />
<el-table-column label="参会专家数" prop="expertCount" width="100" align="center" /> <el-table-column label="参会专家数" prop="expertCount" width="100" align="center" />
<el-table-column label="项目数" prop="projectCount" width="80" align="center" /> <el-table-column label="项目数" prop="projectCount" width="80" align="center" />
<el-table-column label="状态" width="90" align="center"> <el-table-column label="状态" width="90" align="center">
@ -57,28 +59,31 @@
<span :class="`status-text status-${row.status}`">{{ STATUS_LABEL[row.status] }}</span> <span :class="`status-text status-${row.status}`">{{ STATUS_LABEL[row.status] }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="操作" width="300" align="center" fixed="right"> <el-table-column label="操作" width="360" align="center" fixed="right">
<template #default="{ row }"> <template #default="{ row }">
<template v-if="row.status === 0"> <template v-if="row.status === 0">
<a v-hasPermi="['review:meeting:update']" class="op-link" @click="goToEdit(row.id)"></a> <div class="op-group">
<a class="op-link" @click="goToProjectList(row)"></a> <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:send-sms']" class="op-link" @click="handleSendSms(row)"></a>
<a v-hasPermi="['review:meeting:cancel']" class="op-link op-danger" @click="handleCancel(row)"></a> <a v-hasPermi="['review:meeting:cancel']" class="op-link op-danger" @click="handleCancel(row)"></a>
</div>
</template> </template>
<template v-else-if="row.status === 1"> <template v-else-if="row.status === 1">
<a class="op-link" @click="goToEdit(row.id, 'view')">查看</a> <div class="op-group">
<a class="op-link" @click="goToProjectList(row)"></a> <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-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-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-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:update']" class="op-link" @click="triggerUploadMinutes(row)"></a>
<a v-hasPermi="['review:meeting:finish']" class="op-link" @click="handleFinish(row)"></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> <a v-hasPermi="['review:meeting:cancel']" class="op-link op-danger" @click="handleCancel(row)"></a>
</div>
</template> </template>
<template v-else> <template v-else>
<a class="op-link" @click="goToEdit(row.id, 'view')">查看</a> <div class="op-group">
<a class="op-link" @click="goToProjectList(row)"></a> <a class="op-link" @click="goToEdit(row.id, 'view')">查看</a>
<a v-hasPermi="['review:meeting:create']" class="op-link" @click="handleCopy(row)"></a> <a v-hasPermi="['review:meeting:create']" class="op-link" @click="handleCopy(row)"></a>
</div>
</template> </template>
</template> </template>
</el-table-column> </el-table-column>
@ -285,25 +290,37 @@ onMounted(() => getList())
width: 220px; width: 220px;
} }
.search-datepicker { .search-datepicker {
width: 340px; width: 240px;
} }
.search-select { .search-select {
width: 140px; width: 140px;
} }
:deep(.search-input .el-input__wrapper), :deep(.search-input .el-input__wrapper),
:deep(.search-select .el-input__wrapper) { :deep(.search-select .el-input__wrapper),
height: 40px; :deep(.search-datepicker .el-input__wrapper) {
min-height: 40px;
border-radius: 6px;
border-color: #dcdedf;
font-size: 15px;
}
:deep(.search-select .el-select__wrapper) {
min-height: 40px;
border-radius: 6px; border-radius: 6px;
border-color: #dcdedf; border-color: #dcdedf;
font-size: 15px; font-size: 15px;
} }
:deep(.search-datepicker.el-date-editor) { :deep(.search-datepicker.el-date-editor) {
height: 40px; width: 240px !important;
min-width: 240px !important;
max-width: 240px !important;
min-height: 40px;
border-radius: 6px; border-radius: 6px;
border-color: #dcdedf; border-color: #dcdedf;
} }
:deep(.search-input .el-input__inner), :deep(.search-input .el-input__inner),
:deep(.search-select .el-input__inner) { :deep(.search-select .el-input__inner),
:deep(.search-datepicker .el-input__inner) {
line-height: 40px;
font-size: 15px; font-size: 15px;
color: #333; color: #333;
} }
@ -387,17 +404,24 @@ onMounted(() => getList())
/* ── 操作链接 ── */ /* ── 操作链接 ── */
.op-link { .op-link {
display: inline-block; display: inline-flex;
color: #295abc; color: #295abc;
font-size: 13px; font-size: 13px;
cursor: pointer; cursor: pointer;
margin: 0 4px;
transition: opacity 0.2s; transition: opacity 0.2s;
} }
.op-link:hover { .op-link:hover {
opacity: 0.8; opacity: 0.8;
text-decoration: underline; text-decoration: underline;
} }
.op-group {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
gap: 8px;
line-height: 1.4;
}
.op-danger { .op-danger {
color: #fc4f54; color: #fc4f54;
} }