|
|
@@ -1,18 +1,17 @@
|
|
|
<template>
|
|
|
<div class="activity-management">
|
|
|
- <el-card>
|
|
|
+ <el-card class="activity-list-card">
|
|
|
<template #header>
|
|
|
<div class="search-section">
|
|
|
- <div class="search-row">
|
|
|
- <el-form :model="searchForm" inline label-width="86px">
|
|
|
- <el-form-item label="活动 ID">
|
|
|
- <el-input v-model="searchForm.id" clearable placeholder="精确查询活动编号" style="width: 180px" />
|
|
|
+ <el-form :model="searchForm" class="search-grid" label-width="86px">
|
|
|
+ <el-form-item label="活动 ID" class="search-cell">
|
|
|
+ <el-input v-model="searchForm.id" clearable placeholder="精确查询活动编号" />
|
|
|
</el-form-item>
|
|
|
- <el-form-item label="活动名称">
|
|
|
- <el-input v-model="searchForm.name" clearable placeholder="对内标题/对客名称" style="width: 220px" />
|
|
|
+ <el-form-item label="活动名称" class="search-cell">
|
|
|
+ <el-input v-model="searchForm.name" clearable placeholder="对内标题/对客名称" />
|
|
|
</el-form-item>
|
|
|
- <el-form-item label="活动类型">
|
|
|
- <el-select v-model="searchForm.category" clearable placeholder="全部" style="width: 150px">
|
|
|
+ <el-form-item label="活动类型" class="search-cell">
|
|
|
+ <el-select v-model="searchForm.category" clearable placeholder="全部">
|
|
|
<el-option label="普通活动" value="普通活动" />
|
|
|
<el-option label="卓越迎新礼" value="卓越迎新礼" />
|
|
|
<el-option label="层层礼" value="层层礼" />
|
|
|
@@ -20,8 +19,8 @@
|
|
|
<el-option label="信用卡活动" value="信用卡活动" />
|
|
|
</el-select>
|
|
|
</el-form-item>
|
|
|
- <el-form-item label="活动状态">
|
|
|
- <el-select v-model="searchForm.status" clearable placeholder="全部" style="width: 140px">
|
|
|
+ <el-form-item label="发布状态" class="search-cell">
|
|
|
+ <el-select v-model="searchForm.status" clearable placeholder="全部">
|
|
|
<el-option label="草稿" value="draft" />
|
|
|
<el-option label="待审核" value="pending" />
|
|
|
<el-option label="审核通过" value="approved" />
|
|
|
@@ -30,67 +29,62 @@
|
|
|
<el-option label="已结束" value="ended" />
|
|
|
</el-select>
|
|
|
</el-form-item>
|
|
|
- <el-form-item label="创建人">
|
|
|
- <el-input v-model="searchForm.creator" clearable placeholder="创建人" style="width: 130px" />
|
|
|
+ <el-form-item label="活动状态" class="search-cell">
|
|
|
+ <el-select v-model="searchForm.activityStatus" clearable placeholder="全部">
|
|
|
+ <el-option label="未开始" value="未开始" />
|
|
|
+ <el-option label="进行中" value="进行中" />
|
|
|
+ <el-option label="已结束" value="已结束" />
|
|
|
+ </el-select>
|
|
|
</el-form-item>
|
|
|
- <el-form-item>
|
|
|
- <el-button type="primary" @click="handleSearch">查询</el-button>
|
|
|
- <el-button @click="handleReset">重置</el-button>
|
|
|
+ <el-form-item label="创建人" class="search-cell">
|
|
|
+ <el-input v-model="searchForm.creator" clearable placeholder="创建人" />
|
|
|
</el-form-item>
|
|
|
</el-form>
|
|
|
- </div>
|
|
|
- <div class="operation-row">
|
|
|
+ <div class="action-row">
|
|
|
<el-button type="primary" @click="handleCreate"><el-icon><Plus /></el-icon>新建活动</el-button>
|
|
|
+ <div class="search-actions">
|
|
|
+ <el-button type="primary" @click="handleSearch">查询</el-button>
|
|
|
+ <el-button @click="handleReset">重置</el-button>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
- <el-table :data="pagedTableData" stripe style="width: 100%">
|
|
|
- <el-table-column label="操作" width="240" fixed="left">
|
|
|
- <template #default="{ row, $index }">
|
|
|
- <el-button type="text" size="small" @click="handleView(row)">查看</el-button>
|
|
|
- <el-button v-if="['draft', 'rejected', 'approved'].includes(row.status)" type="text" size="small" @click="handleEdit(row)">编辑</el-button>
|
|
|
- <el-button type="text" size="small" @click="preview(row)">预览</el-button>
|
|
|
- <el-popover placement="bottom" trigger="click" :ref="`morePopover-${$index}`">
|
|
|
- <div class="more-actions-menu">
|
|
|
- <div v-if="row.status === 'draft'" class="more-actions-item" @click="submitAudit(row)">提交审核</div>
|
|
|
- <div v-if="row.status === 'pending'" class="more-actions-item" @click="handleAudit(row)">审核</div>
|
|
|
- <div v-if="row.status === 'approved'" class="more-actions-item" @click="publish(row)">发布</div>
|
|
|
- <div v-if="row.status === 'published'" class="more-actions-item more-actions-item-danger" @click="offline(row)">下线</div>
|
|
|
- </div>
|
|
|
- <template #reference>
|
|
|
- <el-button
|
|
|
- v-if="['draft', 'pending', 'approved', 'published'].includes(row.status)"
|
|
|
- type="text"
|
|
|
- size="small"
|
|
|
- class="more-button"
|
|
|
- >
|
|
|
- <el-icon><More /></el-icon>
|
|
|
- </el-button>
|
|
|
- </template>
|
|
|
- </el-popover>
|
|
|
+ <el-table :data="pagedTableData" stripe border style="width: 100%">
|
|
|
+ <el-table-column label="操作" width="400" fixed="left" align="left">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <div class="list-actions">
|
|
|
+ <el-button v-if="['draft', 'rejected', 'approved'].includes(row.status)" type="text" size="small" @click="handleEdit(row)">编辑</el-button>
|
|
|
+ <el-button type="text" size="small" @click="handleView(row)">查看</el-button>
|
|
|
+ <el-button type="text" size="small" @click="preview(row)">预览</el-button>
|
|
|
+ <el-button v-if="row.status === 'draft'" type="text" size="small" @click="submitAudit(row)">提交审核</el-button>
|
|
|
+ <el-button v-if="row.status === 'pending'" type="text" size="small" @click="handleAudit(row)">{{ row.auditAction === 'offline' ? '审核下线' : '审核' }}</el-button>
|
|
|
+ <el-button v-if="row.status === 'approved'" type="text" size="small" @click="publish(row)">发布</el-button>
|
|
|
+ <el-button v-if="row.status === 'published'" type="text" size="small" class="offline-button" @click="requestOffline(row)">申请下线</el-button>
|
|
|
+ </div>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column prop="id" label="活动 ID" width="130" />
|
|
|
+ <el-table-column prop="id" label="活动 ID" width="130" align="center" />
|
|
|
<el-table-column prop="internalTitle" label="活动标题(对内)" min-width="170" show-overflow-tooltip />
|
|
|
<el-table-column prop="name" label="活动名称(对客)" min-width="170" show-overflow-tooltip />
|
|
|
- <el-table-column prop="category" label="活动类型" width="120" />
|
|
|
- <el-table-column label="活动时间" width="210"><template #default="{ row }">{{ rangeText(row.activityTime) }}</template></el-table-column>
|
|
|
- <el-table-column label="报名时间" width="210"><template #default="{ row }">{{ rangeText(row.signupTime) }}</template></el-table-column>
|
|
|
- <el-table-column label="展示状态" width="110">
|
|
|
+ <el-table-column prop="category" label="活动类型" width="120" align="center" />
|
|
|
+ <el-table-column label="活动时间" width="210" align="center"><template #default="{ row }">{{ rangeText(row.activityTime) }}</template></el-table-column>
|
|
|
+ <el-table-column label="报名时间" width="210" align="center"><template #default="{ row }">{{ rangeText(row.signupTime) }}</template></el-table-column>
|
|
|
+ <el-table-column label="展示状态" width="110" align="center">
|
|
|
<template #default="{ row }">
|
|
|
<el-tag :type="row.showOnHome || row.showOnAll ? 'success' : 'info'">{{ row.showOnHome || row.showOnAll ? '对客展示' : '不展示' }}</el-tag>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column label="活动状态" width="110"><template #default="{ row }"><el-tag :type="statusType(row.status)">{{ statusText(row.status) }}</el-tag></template></el-table-column>
|
|
|
- <el-table-column prop="auditStatus" label="审核状态" width="110" />
|
|
|
- <el-table-column prop="creator" label="创建人" width="110" />
|
|
|
- <el-table-column prop="auditor" label="审核人" width="110" />
|
|
|
- <el-table-column prop="createdAt" label="创建时间" width="170" />
|
|
|
- <el-table-column prop="updatedAt" label="更新时间" width="170" />
|
|
|
+ <el-table-column label="发布状态" width="110" align="center"><template #default="{ row }"><el-tag :type="statusType(row.status)">{{ statusText(row.status) }}</el-tag></template></el-table-column>
|
|
|
+ <el-table-column label="活动状态" width="100" align="center"><template #default="{ row }"><el-tag :type="activityStatusType(row)">{{ activityStatusText(row) }}</el-tag></template></el-table-column>
|
|
|
+ <el-table-column prop="auditStatus" label="审核状态" width="110" align="center" />
|
|
|
+ <el-table-column prop="creator" label="创建人" width="110" align="center" />
|
|
|
+ <el-table-column prop="auditor" label="审核人" width="110" align="center" />
|
|
|
+ <el-table-column prop="createdAt" label="创建时间" width="170" align="center" />
|
|
|
+ <el-table-column prop="updatedAt" label="更新时间" width="170" align="center" />
|
|
|
</el-table>
|
|
|
<div class="pagination-section">
|
|
|
- <span>Total {{ tableData.length }}</span>
|
|
|
+ <span class="total">Total {{ tableData.length }}</span>
|
|
|
<el-pagination
|
|
|
v-model:current-page="currentPage"
|
|
|
v-model:page-size="pageSize"
|
|
|
@@ -111,7 +105,7 @@ export default {
|
|
|
name: 'ActivityManagement',
|
|
|
data() {
|
|
|
return {
|
|
|
- searchForm: { id: '', name: '', category: '', status: '', creator: '' },
|
|
|
+ searchForm: { id: '', name: '', category: '', status: '', activityStatus: '', creator: '' },
|
|
|
tableData: [],
|
|
|
currentPage: 1,
|
|
|
pageSize: 10
|
|
|
@@ -129,12 +123,13 @@ export default {
|
|
|
handleSearch() {
|
|
|
this.tableData = activityStore.queryActivities(this.searchForm).filter((item) => {
|
|
|
if (this.searchForm.creator && !String(item.creator || '').includes(this.searchForm.creator)) return false
|
|
|
+ if (this.searchForm.activityStatus && this.activityStatusText(item) !== this.searchForm.activityStatus) return false
|
|
|
return true
|
|
|
})
|
|
|
this.currentPage = 1
|
|
|
},
|
|
|
handleReset() {
|
|
|
- this.searchForm = { id: '', name: '', category: '', status: '', creator: '' }
|
|
|
+ this.searchForm = { id: '', name: '', category: '', status: '', activityStatus: '', creator: '' }
|
|
|
this.handleSearch()
|
|
|
},
|
|
|
handleCreate() { this.$router.push('/customization/hsbc/activities/add') },
|
|
|
@@ -147,6 +142,7 @@ export default {
|
|
|
if (error) return ElMessage.warning(error)
|
|
|
row.status = 'pending'
|
|
|
row.auditStatus = '待审核'
|
|
|
+ row.auditAction = ''
|
|
|
ElMessage.success('已提交审核')
|
|
|
this.handleSearch()
|
|
|
},
|
|
|
@@ -155,9 +151,11 @@ export default {
|
|
|
activityStore.publishActivity(row.id)
|
|
|
this.handleSearch()
|
|
|
},
|
|
|
- async offline(row) {
|
|
|
- await ElMessageBox.confirm(`确定下线活动「${row.name}」吗?`, '下线活动', { type: 'warning' })
|
|
|
- activityStore.offlineActivity(row.id)
|
|
|
+ async requestOffline(row) {
|
|
|
+ await ElMessageBox.confirm(`提交后将进入下线审核流程,审核通过后活动才会下线。确定申请下线「${row.name}」吗?`, '申请下线', { type: 'warning' })
|
|
|
+ row.status = 'pending'
|
|
|
+ row.auditStatus = '下线待审核'
|
|
|
+ row.auditAction = 'offline'
|
|
|
this.handleSearch()
|
|
|
},
|
|
|
validateRequired(row) {
|
|
|
@@ -165,13 +163,22 @@ export default {
|
|
|
if (!row.internalTitle) return '活动标题(对内)必填'
|
|
|
if (!row.activityTime || row.activityTime.length !== 2) return '活动时间必填'
|
|
|
if (row.needSignup && (!row.signupTime || row.signupTime.length !== 2)) return '报名时间必填'
|
|
|
- if (row.progressEnabled && !row.progressTemplateId) return '开启进度跟踪后必须选择进度模板'
|
|
|
- if (row.progressEnabled && !row.progressRuleId) return '开启进度跟踪后必须选择达标规则'
|
|
|
if (row.rewardEnabled && !row.grantPlanId) return '需要权益发放时必须选择发放计划'
|
|
|
if (row.mutexEnabled && !row.mutexGroup) return '参与互斥时必须选择互斥组'
|
|
|
return ''
|
|
|
},
|
|
|
rangeText(range) { return range && range.length === 2 ? `${range[0]} 至 ${range[1]}` : '-' },
|
|
|
+ activityStatusText(row) {
|
|
|
+ const range = row.activityTime
|
|
|
+ if (!Array.isArray(range) || range.length !== 2 || !range[0] || !range[1]) return '-'
|
|
|
+ const today = new Date().toISOString().slice(0, 10)
|
|
|
+ if (today < range[0]) return '未开始'
|
|
|
+ if (today > range[1]) return '已结束'
|
|
|
+ return '进行中'
|
|
|
+ },
|
|
|
+ activityStatusType(row) {
|
|
|
+ return { '未开始': 'info', '进行中': 'success', '已结束': 'warning' }[this.activityStatusText(row)] || 'info'
|
|
|
+ },
|
|
|
statusText(status) {
|
|
|
return { draft: '草稿', pending: '待审核', approved: '审核通过', published: '已发布', offline: '已下线', ended: '已结束', rejected: '已驳回' }[status] || status
|
|
|
},
|
|
|
@@ -184,18 +191,36 @@ export default {
|
|
|
|
|
|
<style scoped>
|
|
|
.activity-management { padding:0; }
|
|
|
+.activity-list-card { border-radius:4px; }
|
|
|
.search-section { display:flex; flex-direction:column; }
|
|
|
-.search-row { margin-bottom:15px; }
|
|
|
-.search-row .el-form { display:flex; flex-wrap:wrap; }
|
|
|
-.search-row .el-form-item { margin-right:0; margin-bottom:0; }
|
|
|
-.operation-row { display:flex; align-items:center; }
|
|
|
+.search-grid {
|
|
|
+ display:grid;
|
|
|
+ grid-template-columns:repeat(4, minmax(0, 1fr));
|
|
|
+ column-gap:24px;
|
|
|
+ row-gap:20px;
|
|
|
+ margin-bottom:4px;
|
|
|
+}
|
|
|
+.search-grid .search-cell { margin:0; }
|
|
|
+.search-grid .search-cell :deep(.el-form-item__content) { width:100%; }
|
|
|
+.search-grid .search-cell :deep(.el-input),
|
|
|
+.search-grid .search-cell :deep(.el-select) { width:100%; }
|
|
|
+.action-row { display:flex; align-items:center; justify-content:space-between; margin-top:20px; }
|
|
|
+.search-actions { display:flex; align-items:center; gap:12px; }
|
|
|
+.activity-management :deep(.el-input:not(.el-textarea)) { --el-input-height:32px; }
|
|
|
+.activity-management :deep(.el-input:not(.el-textarea) .el-input__wrapper),
|
|
|
+.activity-management :deep(.el-select__wrapper) { min-height:32px; height:32px; }
|
|
|
+.activity-management :deep(.el-input:not(.el-textarea) .el-input__inner) { height:30px; line-height:30px; }
|
|
|
+.activity-management :deep(.el-table th.el-table__cell) { background:#fafafa; }
|
|
|
+.activity-management :deep(.el-table .el-table__cell) { padding:10px 0; }
|
|
|
.pagination-section { display:flex; justify-content:flex-end; align-items:center; gap:20px; margin-top:20px; }
|
|
|
-.more-button { margin-left:8px; }
|
|
|
-</style>
|
|
|
-
|
|
|
-<style>
|
|
|
-.more-actions-menu { display:flex; flex-direction:column; margin:-12px; }
|
|
|
-.more-actions-item { padding:8px 16px; cursor:pointer; color:#606266; font-size:14px; }
|
|
|
-.more-actions-item:hover { background:#f5f7fa; color:#409eff; }
|
|
|
-.more-actions-item-danger:hover { color:#f56c6c; }
|
|
|
+.pagination-section .total { color:#606266; font-size:13px; }
|
|
|
+.list-actions { display:inline-flex; align-items:center; justify-content:flex-start; gap:10px; width:100%; white-space:nowrap; }
|
|
|
+.list-actions :deep(.el-button) { margin-left:0; padding:0; }
|
|
|
+.offline-button { color:#f56c6c; }
|
|
|
+@media (max-width: 1100px) {
|
|
|
+ .search-grid { grid-template-columns:repeat(2, minmax(0, 1fr)); }
|
|
|
+}
|
|
|
+@media (max-width: 600px) {
|
|
|
+ .search-grid { grid-template-columns:1fr; }
|
|
|
+}
|
|
|
</style>
|