|
@@ -40,7 +40,11 @@
|
|
|
<template slot-scope="{ row }">{{ row.price ? (row.price / 100).toFixed(2) : '免费' }}</template>
|
|
<template slot-scope="{ row }">{{ row.price ? (row.price / 100).toFixed(2) : '免费' }}</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
<el-table-column label="人数" width="90">
|
|
<el-table-column label="人数" width="90">
|
|
|
- <template slot-scope="{ row }">{{ row.currentParticipants || 0 }}/{{ row.maxParticipants || '不限' }}</template>
|
|
|
|
|
|
|
+ <template slot-scope="{ row }">
|
|
|
|
|
+ <el-button type="text" size="mini" @click="showRegistrations(row)" style="padding:0;">
|
|
|
|
|
+ {{ row.currentParticipants || 0 }}/{{ row.maxParticipants || '不限' }}
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ </template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
<el-table-column label="状态" width="100">
|
|
<el-table-column label="状态" width="100">
|
|
|
<template slot-scope="{ row }">
|
|
<template slot-scope="{ row }">
|
|
@@ -51,9 +55,10 @@
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
<el-table-column prop="startTime" label="开始时间" width="170" />
|
|
<el-table-column prop="startTime" label="开始时间" width="170" />
|
|
|
<el-table-column prop="endTime" label="结束时间" width="170" />
|
|
<el-table-column prop="endTime" label="结束时间" width="170" />
|
|
|
- <el-table-column label="操作" width="240">
|
|
|
|
|
|
|
+ <el-table-column label="操作" width="280">
|
|
|
<template slot-scope="{ row }">
|
|
<template slot-scope="{ row }">
|
|
|
- <el-button size="mini" @click="editActivity(row)" :disabled="row.status === 'ended'">编辑</el-button>
|
|
|
|
|
|
|
+ <el-button size="mini" @click="viewActivity(row)" v-if="row.status !== 'draft'">查看</el-button>
|
|
|
|
|
+ <el-button size="mini" @click="editActivity(row)" :disabled="row.status !== 'draft'" v-else>编辑</el-button>
|
|
|
<el-button
|
|
<el-button
|
|
|
size="mini"
|
|
size="mini"
|
|
|
type="success"
|
|
type="success"
|
|
@@ -83,12 +88,12 @@
|
|
|
</el-card>
|
|
</el-card>
|
|
|
|
|
|
|
|
<el-dialog
|
|
<el-dialog
|
|
|
- :title="editId ? '编辑活动' : '创建活动'"
|
|
|
|
|
|
|
+ :title="viewMode ? '查看活动' : (editId ? '编辑活动' : '创建活动')"
|
|
|
:visible.sync="dialogVisible"
|
|
:visible.sync="dialogVisible"
|
|
|
width="700px"
|
|
width="700px"
|
|
|
@closed="resetForm"
|
|
@closed="resetForm"
|
|
|
>
|
|
>
|
|
|
- <el-form label-width="120px">
|
|
|
|
|
|
|
+ <el-form label-width="120px" ref="activityForm">
|
|
|
<el-form-item label="活动标题">
|
|
<el-form-item label="活动标题">
|
|
|
<el-input v-model="form.title" placeholder="请输入活动标题" />
|
|
<el-input v-model="form.title" placeholder="请输入活动标题" />
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
@@ -188,16 +193,50 @@
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
</el-form>
|
|
</el-form>
|
|
|
<div slot="footer">
|
|
<div slot="footer">
|
|
|
- <el-button @click="dialogVisible = false">取消</el-button>
|
|
|
|
|
- <el-button type="primary" @click="saveActivity" :loading="saving">保存</el-button>
|
|
|
|
|
|
|
+ <el-button @click="dialogVisible = false">{{ viewMode ? '关闭' : '取消' }}</el-button>
|
|
|
|
|
+ <el-button v-if="!viewMode" type="primary" @click="saveActivity" :loading="saving">保存</el-button>
|
|
|
</div>
|
|
</div>
|
|
|
</el-dialog>
|
|
</el-dialog>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 报名列表对话框 -->
|
|
|
|
|
+ <el-dialog
|
|
|
|
|
+ :title="'报名列表 - ' + (currentActivity ? currentActivity.title : '')"
|
|
|
|
|
+ :visible.sync="regDialogVisible"
|
|
|
|
|
+ width="800px"
|
|
|
|
|
+ @closed="regDialogVisible = false"
|
|
|
|
|
+ >
|
|
|
|
|
+ <el-table :data="registrations" v-loading="regLoading" border stripe>
|
|
|
|
|
+ <el-table-column prop="id" label="ID" width="60" />
|
|
|
|
|
+ <el-table-column prop="userId" label="用户ID" width="70" />
|
|
|
|
|
+ <el-table-column prop="childId" label="孩子ID" width="70" />
|
|
|
|
|
+ <el-table-column label="状态" width="90">
|
|
|
|
|
+ <template slot-scope="{ row }">
|
|
|
|
|
+ <el-tag :type="row.status === 'approved' ? 'success' : row.status === 'rejected' ? 'danger' : 'warning'">
|
|
|
|
|
+ {{ row.status === 'approved' ? '已通过' : row.status === 'rejected' ? '已拒绝' : '待审核' }}
|
|
|
|
|
+ </el-tag>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column prop="registeredAt" label="报名时间" width="160">
|
|
|
|
|
+ <template slot-scope="{ row }">
|
|
|
|
|
+ {{ formatTime(row.registeredAt || row.createdAt) }}
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="操作" width="200" fixed="right">
|
|
|
|
|
+ <template slot-scope="{ row }">
|
|
|
|
|
+ <el-button v-if="row.status === 'pending'" type="success" size="small" @click="handleRegApprove(row)">通过</el-button>
|
|
|
|
|
+ <el-button v-if="row.status === 'pending'" type="danger" size="small" @click="handleRegReject(row)">拒绝</el-button>
|
|
|
|
|
+ <span v-else style="color: #999;">已处理</span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ </el-table>
|
|
|
|
|
+ <p v-if="!registrations.length && !regLoading" style="text-align:center;color:#999;">暂无报名记录</p>
|
|
|
|
|
+ </el-dialog>
|
|
|
</div>
|
|
</div>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
<script>
|
|
|
import DimensionWeightPicker from '@/components/DimensionWeightPicker.vue'
|
|
import DimensionWeightPicker from '@/components/DimensionWeightPicker.vue'
|
|
|
-import { getActivityList, createActivity, updateActivity, publishActivity, endActivity } from '@/api/activity'
|
|
|
|
|
|
|
+import { getActivityList, createActivity, updateActivity, publishActivity, endActivity, getRegistrationList, approveRegistration, rejectRegistration } from '@/api/activity'
|
|
|
import { saveDimensionWeights, getDimensionWeights } from '@/api/dimension-weight.js'
|
|
import { saveDimensionWeights, getDimensionWeights } from '@/api/dimension-weight.js'
|
|
|
|
|
|
|
|
const STATUS_MAP = {
|
|
const STATUS_MAP = {
|
|
@@ -228,6 +267,7 @@ export default {
|
|
|
activities: [],
|
|
activities: [],
|
|
|
total: 0,
|
|
total: 0,
|
|
|
editId: null,
|
|
editId: null,
|
|
|
|
|
+ viewMode: false,
|
|
|
dialogVisible: false,
|
|
dialogVisible: false,
|
|
|
filter: {
|
|
filter: {
|
|
|
status: '',
|
|
status: '',
|
|
@@ -250,7 +290,12 @@ export default {
|
|
|
visibleScope: '',
|
|
visibleScope: '',
|
|
|
visibleTo: '',
|
|
visibleTo: '',
|
|
|
checkinPoints: 0
|
|
checkinPoints: 0
|
|
|
- }
|
|
|
|
|
|
|
+ },
|
|
|
|
|
+ // 报名列表对话框
|
|
|
|
|
+ regDialogVisible: false,
|
|
|
|
|
+ regLoading: false,
|
|
|
|
|
+ currentActivity: null,
|
|
|
|
|
+ registrations: []
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
computed: {
|
|
computed: {
|
|
@@ -334,10 +379,12 @@ export default {
|
|
|
},
|
|
},
|
|
|
openCreate() {
|
|
openCreate() {
|
|
|
this.editId = null
|
|
this.editId = null
|
|
|
|
|
+ this.viewMode = false
|
|
|
this.resetForm()
|
|
this.resetForm()
|
|
|
this.dialogVisible = true
|
|
this.dialogVisible = true
|
|
|
},
|
|
},
|
|
|
resetForm() {
|
|
resetForm() {
|
|
|
|
|
+ this.viewMode = false
|
|
|
this.form = {
|
|
this.form = {
|
|
|
title: '',
|
|
title: '',
|
|
|
coverImage: '',
|
|
coverImage: '',
|
|
@@ -358,6 +405,7 @@ export default {
|
|
|
},
|
|
},
|
|
|
editActivity(row) {
|
|
editActivity(row) {
|
|
|
this.editId = row.id
|
|
this.editId = row.id
|
|
|
|
|
+ this.viewMode = false
|
|
|
this.form = {
|
|
this.form = {
|
|
|
title: row.title || '',
|
|
title: row.title || '',
|
|
|
coverImage: row.coverImage || '',
|
|
coverImage: row.coverImage || '',
|
|
@@ -458,6 +506,89 @@ export default {
|
|
|
} catch (e) {
|
|
} catch (e) {
|
|
|
this.$message.error('操作失败')
|
|
this.$message.error('操作失败')
|
|
|
}
|
|
}
|
|
|
|
|
+ },
|
|
|
|
|
+ // ===== 查看活动(只读,使用同一对话框) =====
|
|
|
|
|
+ viewActivity(row) {
|
|
|
|
|
+ this.viewMode = true
|
|
|
|
|
+ this.editId = row.id
|
|
|
|
|
+ this.form = {
|
|
|
|
|
+ title: row.title || '',
|
|
|
|
|
+ coverImage: row.coverImage || '',
|
|
|
|
|
+ activityType: row.activityType || '',
|
|
|
|
|
+ description: row.description || '',
|
|
|
|
|
+ dimensionCode: row.dimensionCode || '',
|
|
|
|
|
+ dimensionWeights: [],
|
|
|
|
|
+ location: row.location || '',
|
|
|
|
|
+ maxParticipants: row.maxParticipants || null,
|
|
|
|
|
+ priceYuan: row.price ? row.price / 100 : null,
|
|
|
|
|
+ startTime: row.startTime || null,
|
|
|
|
|
+ endTime: row.endTime || null,
|
|
|
|
|
+ visibility: row.visibility || 'public',
|
|
|
|
|
+ visibleScope: row.visibleScope || '',
|
|
|
|
|
+ visibleTo: row.visibleTo || '',
|
|
|
|
|
+ checkinPoints: row.checkinPoints || 0
|
|
|
|
|
+ }
|
|
|
|
|
+ this.dialogVisible = true
|
|
|
|
|
+ this.loadDimensionWeights(row.id)
|
|
|
|
|
+ this.$nextTick(() => {
|
|
|
|
|
+ if (this.$refs.activityForm) {
|
|
|
|
|
+ // 禁用所有 el-form-item 内的输入控件
|
|
|
|
|
+ this.$refs.activityForm.$el.querySelectorAll('input, textarea, .el-select, .el-input-number, .el-switch, .el-date-editor, .el-upload').forEach(el => {
|
|
|
|
|
+ el.classList.add('is-disabled')
|
|
|
|
|
+ const inp = el.querySelector('input') || el.querySelector('textarea')
|
|
|
|
|
+ if (inp) inp.disabled = true
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ // ===== 报名列表 =====
|
|
|
|
|
+ showRegistrations(row) {
|
|
|
|
|
+ this.currentActivity = row
|
|
|
|
|
+ this.regDialogVisible = true
|
|
|
|
|
+ this.loadRegistrations(row.id)
|
|
|
|
|
+ },
|
|
|
|
|
+ async loadRegistrations(activityId) {
|
|
|
|
|
+ this.regLoading = true
|
|
|
|
|
+ try {
|
|
|
|
|
+ const res = await getRegistrationList({ activityId })
|
|
|
|
|
+ if (res.code === 200) {
|
|
|
|
|
+ this.registrations = res.data || []
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ this.$message.error('加载报名列表失败')
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ this.regLoading = false
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ formatTime(t) {
|
|
|
|
|
+ if (!t) return '-'
|
|
|
|
|
+ return t.replace ? t.replace('T', ' ').substring(0, 19) : t
|
|
|
|
|
+ },
|
|
|
|
|
+ async handleRegApprove(row) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const res = await approveRegistration({ registrationId: row.id })
|
|
|
|
|
+ if (res.code === 200) {
|
|
|
|
|
+ this.$message.success('已通过')
|
|
|
|
|
+ this.loadRegistrations(this.currentActivity.id)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.$message.error(res.message || '操作失败')
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ this.$message.error('操作失败')
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ async handleRegReject(row) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const res = await rejectRegistration({ registrationId: row.id })
|
|
|
|
|
+ if (res.code === 200) {
|
|
|
|
|
+ this.$message.success('已拒绝')
|
|
|
|
|
+ this.loadRegistrations(this.currentActivity.id)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.$message.error(res.message || '操作失败')
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ this.$message.error('操作失败')
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|