| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- <template>
- <div class="activity-management">
- <el-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-item>
- <el-form-item label="活动名称">
- <el-input v-model="searchForm.name" clearable placeholder="对内标题/对客名称" style="width: 220px" />
- </el-form-item>
- <el-form-item label="活动类型">
- <el-select v-model="searchForm.category" clearable placeholder="全部" style="width: 150px">
- <el-option label="普通活动" value="普通活动" />
- <el-option label="卓越迎新礼" value="卓越迎新礼" />
- <el-option label="层层礼" value="层层礼" />
- <el-option label="MGM" value="MGM" />
- <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-option label="草稿" value="draft" />
- <el-option label="待审核" value="pending" />
- <el-option label="审核通过" value="approved" />
- <el-option label="已发布" value="published" />
- <el-option label="已下线" value="offline" />
- <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>
- <el-form-item>
- <el-button type="primary" @click="handleSearch">查询</el-button>
- <el-button @click="handleReset">重置</el-button>
- </el-form-item>
- </el-form>
- </div>
- <div class="operation-row">
- <el-button type="primary" @click="handleCreate"><el-icon><Plus /></el-icon>新建活动</el-button>
- </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>
- </template>
- </el-table-column>
- <el-table-column prop="id" label="活动 ID" width="130" />
- <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">
- <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>
- <div class="pagination-section">
- <span>Total {{ tableData.length }}</span>
- <el-pagination
- v-model:current-page="currentPage"
- v-model:page-size="pageSize"
- layout="prev, pager, next, sizes, jumper"
- :page-sizes="[10, 20, 50]"
- :total="tableData.length"
- />
- </div>
- </el-card>
- </div>
- </template>
- <script>
- import { ElMessage, ElMessageBox } from 'element-plus'
- import activityStore from '@/store/activityStore'
- export default {
- name: 'ActivityManagement',
- data() {
- return {
- searchForm: { id: '', name: '', category: '', status: '', creator: '' },
- tableData: [],
- currentPage: 1,
- pageSize: 10
- }
- },
- computed: {
- pagedTableData() {
- const start = (this.currentPage - 1) * this.pageSize
- return this.tableData.slice(start, start + this.pageSize)
- }
- },
- created() { this.handleSearch() },
- activated() { this.handleSearch() },
- methods: {
- handleSearch() {
- this.tableData = activityStore.queryActivities(this.searchForm).filter((item) => {
- if (this.searchForm.creator && !String(item.creator || '').includes(this.searchForm.creator)) return false
- return true
- })
- this.currentPage = 1
- },
- handleReset() {
- this.searchForm = { id: '', name: '', category: '', status: '', creator: '' }
- this.handleSearch()
- },
- handleCreate() { this.$router.push('/customization/hsbc/activities/add') },
- handleEdit(row) { this.$router.push(`/customization/hsbc/activities/edit/${row.id}`) },
- handleView(row) { this.$router.push(`/customization/hsbc/activities/view/${row.id}`) },
- handleAudit(row) { this.$router.push(`/customization/hsbc/activities/audit/${row.id}`) },
- preview(row) { ElMessage.success(`已生成移动端预览:${row.name}`) },
- submitAudit(row) {
- const error = this.validateRequired(row)
- if (error) return ElMessage.warning(error)
- row.status = 'pending'
- row.auditStatus = '待审核'
- ElMessage.success('已提交审核')
- this.handleSearch()
- },
- async publish(row) {
- await ElMessageBox.confirm(`确定发布活动「${row.name}」吗?`, '发布活动', { type: 'warning' })
- activityStore.publishActivity(row.id)
- this.handleSearch()
- },
- async offline(row) {
- await ElMessageBox.confirm(`确定下线活动「${row.name}」吗?`, '下线活动', { type: 'warning' })
- activityStore.offlineActivity(row.id)
- this.handleSearch()
- },
- validateRequired(row) {
- if (!row.name) return '活动名称(对客)必填'
- 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]}` : '-' },
- statusText(status) {
- return { draft: '草稿', pending: '待审核', approved: '审核通过', published: '已发布', offline: '已下线', ended: '已结束', rejected: '已驳回' }[status] || status
- },
- statusType(status) {
- return { draft: 'info', pending: 'warning', approved: 'success', published: 'success', offline: 'danger', ended: 'info', rejected: 'danger' }[status] || ''
- }
- }
- }
- </script>
- <style scoped>
- .activity-management { padding:0; }
- .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; }
- .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; }
- </style>
|