Files
RuoYi-Vue/ruoyi-ui/src/views/app/pointTaskReview/index.vue

98 lines
8.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="app-container">
<el-form v-show="showSearch" ref="queryForm" :model="queryParams" size="small" :inline="true">
<el-form-item label="任务名称" prop="taskName"><el-input v-model="queryParams.taskName" clearable placeholder="任务名称" @keyup.enter.native="handleQuery" /></el-form-item>
<el-form-item label="用户" prop="userName"><el-input v-model="queryParams.userName" clearable placeholder="账号或昵称" @keyup.enter.native="handleQuery" /></el-form-item>
<el-form-item label="状态" prop="status"><el-select v-model="queryParams.status" clearable placeholder="全部"><el-option v-for="item in statusOptions" :key="item.value" :label="item.label" :value="item.value" /></el-select></el-form-item>
<el-form-item label="周期" prop="cycleKey"><el-input v-model="queryParams.cycleKey" clearable placeholder="ONCE或2026-09-16" /></el-form-item>
<el-form-item><el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button><el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button></el-form-item>
</el-form>
<right-toolbar :show-search.sync="showSearch" @queryTable="getList" />
<el-table v-loading="loading" :data="submissionList">
<el-table-column label="提交单号" prop="submissionNo" min-width="185" />
<el-table-column label="任务" prop="taskName" min-width="160" show-overflow-tooltip />
<el-table-column label="用户" min-width="130"><template slot-scope="scope"><div>{{ scope.row.nickName || scope.row.userName }}</div><small class="muted">ID: {{ scope.row.userId }}</small></template></el-table-column>
<el-table-column label="周期" prop="cycleKey" align="center" width="110" />
<el-table-column label="积分" prop="rewardPoints" align="center" width="75" />
<el-table-column label="提交次数" prop="attemptCount" align="center" width="85" />
<el-table-column label="状态" align="center" width="100"><template slot-scope="scope"><el-tag :type="statusType(scope.row.status)" size="small">{{ statusLabel(scope.row.status) }}</el-tag></template></el-table-column>
<el-table-column label="提交时间" prop="lastSubmitTime" width="165" />
<el-table-column label="操作" align="center" width="225" fixed="right">
<template slot-scope="scope">
<el-button v-hasPermi="['app:pointTaskReview:query']" type="text" icon="el-icon-view" size="mini" @click="handleView(scope.row)">详情</el-button>
<el-button v-if="scope.row.status === 0" v-hasPermi="['app:pointTaskReview:edit']" type="text" icon="el-icon-check" size="mini" @click="handleApprove(scope.row)">通过</el-button>
<el-button v-if="scope.row.status === 0" v-hasPermi="['app:pointTaskReview:edit']" type="text" icon="el-icon-close" size="mini" @click="openReason(scope.row, 'reject')">驳回</el-button>
<el-button v-if="scope.row.status === 1" v-hasPermi="['app:pointTaskReview:revoke']" type="text" icon="el-icon-refresh-left" size="mini" @click="openReason(scope.row, 'revoke')">撤销</el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
<el-dialog title="任务提交详情" :visible.sync="detailOpen" width="820px" append-to-body>
<el-descriptions v-if="detail.id" :column="2" border>
<el-descriptions-item label="提交单号" :span="2">{{ detail.submissionNo }}</el-descriptions-item>
<el-descriptions-item label="任务名称">{{ detail.taskName }}</el-descriptions-item>
<el-descriptions-item label="奖励积分">{{ detail.rewardPoints }}</el-descriptions-item>
<el-descriptions-item label="用户">{{ detail.nickName || detail.userName }}({{ detail.userId }})</el-descriptions-item>
<el-descriptions-item label="任务周期">{{ detail.cycleKey }}</el-descriptions-item>
<el-descriptions-item label="状态"><el-tag :type="statusType(detail.status)" size="small">{{ statusLabel(detail.status) }}</el-tag></el-descriptions-item>
<el-descriptions-item label="提交次数">{{ detail.attemptCount }}</el-descriptions-item>
<el-descriptions-item label="用户说明" :span="2"><div class="pre-wrap">{{ detail.remark || '-' }}</div></el-descriptions-item>
<el-descriptions-item v-if="detail.rejectReason" label="驳回/撤销原因" :span="2">{{ detail.rejectReason }}</el-descriptions-item>
</el-descriptions>
<h4>任务截图</h4>
<div class="image-list">
<div v-for="item in detail.attachments || []" :key="item.id" class="image-card" :class="{ history: item.isCurrent !== 1 }">
<el-image :src="item.previewUrl" :preview-src-list="previewUrls" fit="cover" />
<div>{{ item.isCurrent === 1 ? '当前截图' : '历史第' + item.submitBatch + '次' }}</div>
</div>
</div>
<div slot="footer"><el-button @click="detailOpen=false">关闭</el-button></div>
</el-dialog>
<el-dialog :title="reasonMode === 'reject' ? '驳回任务' : '撤销积分奖励'" :visible.sync="reasonOpen" width="520px" append-to-body>
<el-input v-model="reason" type="textarea" :rows="4" maxlength="300" show-word-limit :placeholder="reasonMode === 'reject' ? '请填写审核未通过原因' : '请填写撤销原因'" />
<el-alert v-if="reasonMode === 'revoke'" title="撤销将扣回已发放积分;用户积分不足时操作会失败。" type="warning" :closable="false" show-icon style="margin-top:15px" />
<div slot="footer"><el-button @click="reasonOpen=false">取消</el-button><el-button type="primary" :loading="submitting" @click="submitReason">确定</el-button></div>
</el-dialog>
</div>
</template>
<script>
import { listPointTaskSubmission, getPointTaskSubmission, approvePointTaskSubmission, rejectPointTaskSubmission, revokePointTaskSubmission } from '@/api/app/pointTask'
export default {
name: 'PointTaskReview',
data() {
return {
loading: false, submitting: false, showSearch: true, total: 0, submissionList: [], detailOpen: false, detail: {}, reasonOpen: false, reason: '', reasonMode: 'reject', currentRow: {},
statusOptions: [{ value: 0, label: '待审核' }, { value: 1, label: '已通过' }, { value: 2, label: '已驳回' }, { value: 3, label: '已撤销' }],
queryParams: { pageNum: 1, pageSize: 10, taskName: undefined, userName: undefined, status: undefined, cycleKey: undefined }
}
},
computed: { previewUrls() { return (this.detail.attachments || []).map(item => item.previewUrl).filter(Boolean) } },
created() { this.getList() },
methods: {
getList() { this.loading = true; listPointTaskSubmission(this.queryParams).then(res => { this.submissionList = res.rows || []; this.total = res.total || 0 }).finally(() => { this.loading = false }) },
handleQuery() { this.queryParams.pageNum = 1; this.getList() },
resetQuery() { this.resetForm('queryForm'); this.handleQuery() },
handleView(row) { getPointTaskSubmission(row.id).then(res => { this.detail = res.data; this.detailOpen = true }) },
handleApprove(row) { this.$modal.confirm('确认通过该任务并发放 ' + row.rewardPoints + ' 积分吗?').then(() => approvePointTaskSubmission(row.id)).then(() => { this.$modal.msgSuccess('审核通过,积分已发放'); this.getList() }).catch(() => {}) },
openReason(row, mode) { this.currentRow = row; this.reasonMode = mode; this.reason = ''; this.reasonOpen = true },
submitReason() { const reason = String(this.reason || '').trim(); if (!reason) { this.$modal.msgError('请填写原因'); return } this.submitting = true; const action = this.reasonMode === 'reject' ? rejectPointTaskSubmission : revokePointTaskSubmission; action(this.currentRow.id, reason).then(() => { this.$modal.msgSuccess(this.reasonMode === 'reject' ? '已驳回' : '奖励已撤销'); this.reasonOpen = false; this.getList() }).finally(() => { this.submitting = false }) },
statusLabel(status) { const item = this.statusOptions.find(v => v.value === status); return item ? item.label : '未知' },
statusType(status) { return { 0: 'warning', 1: 'success', 2: 'danger', 3: 'info' }[status] || 'info' }
}
}
</script>
<style scoped>
.muted { color: #909399; }
.pre-wrap { white-space: pre-wrap; }
.image-list { display: flex; flex-wrap: wrap; gap: 14px; }
.image-card { width: 150px; text-align: center; color: #606266; }
.image-card .el-image { width: 150px; height: 150px; border-radius: 6px; }
.image-card.history { opacity: .58; }
</style>