[update]新增submittedReward页面
This commit is contained in:
31
web/src/api/backend/user/submittedReward.ts
Normal file
31
web/src/api/backend/user/submittedReward.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import createAxios from '/@/utils/axios'
|
||||||
|
|
||||||
|
export interface SubmittedRewardParams {
|
||||||
|
start: string
|
||||||
|
end: string
|
||||||
|
status: '' | '0' | '1' | '2'
|
||||||
|
username: string
|
||||||
|
game_id: 268 | 269 | 270
|
||||||
|
page: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getSubmittedRewards(params: SubmittedRewardParams) {
|
||||||
|
return createAxios({
|
||||||
|
url: '/admin/user.User/submittedReward',
|
||||||
|
method: 'get',
|
||||||
|
params,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function editReward(data: { id: number | string; status: 1 | 2 }) {
|
||||||
|
return createAxios(
|
||||||
|
{
|
||||||
|
url: '/admin/user.User/editReward',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
showSuccessMessage: true,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@ export default {
|
|||||||
[adminBaseRoutePath + '/moduleStore']: ['./backend/${lang}/module.ts'],
|
[adminBaseRoutePath + '/moduleStore']: ['./backend/${lang}/module.ts'],
|
||||||
[adminBaseRoutePath + '/user/rule']: ['./backend/${lang}/auth/rule.ts'],
|
[adminBaseRoutePath + '/user/rule']: ['./backend/${lang}/auth/rule.ts'],
|
||||||
[adminBaseRoutePath + '/user/moneyLog/annualReport']: ['./backend/${lang}/user/moneyLog.ts'],
|
[adminBaseRoutePath + '/user/moneyLog/annualReport']: ['./backend/${lang}/user/moneyLog.ts'],
|
||||||
|
[adminBaseRoutePath + '/user/submittedReward']: ['./backend/${lang}/user/submittedReward.ts'],
|
||||||
[adminBaseRoutePath + '/user/scoreLog']: ['./backend/${lang}/user/moneyLog.ts'],
|
[adminBaseRoutePath + '/user/scoreLog']: ['./backend/${lang}/user/moneyLog.ts'],
|
||||||
[adminBaseRoutePath + '/crud/crud']: ['./backend/${lang}/crud/log.ts', './backend/${lang}/crud/state.ts'],
|
[adminBaseRoutePath + '/crud/crud']: ['./backend/${lang}/crud/log.ts', './backend/${lang}/crud/state.ts'],
|
||||||
}
|
}
|
||||||
|
|||||||
27
web/src/lang/backend/en/user/submittedReward.ts
Normal file
27
web/src/lang/backend/en/user/submittedReward.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
export default {
|
||||||
|
'Promotion type': 'Promotion type',
|
||||||
|
'Submitted Rewards': 'Submitted Rewards',
|
||||||
|
Running: 'Running',
|
||||||
|
'Start Date': 'Start Date',
|
||||||
|
'End Date': 'End Date',
|
||||||
|
Status: 'Status',
|
||||||
|
Username: 'Username',
|
||||||
|
'All status': '- All status -',
|
||||||
|
'Approve Reward': 'Approve Reward',
|
||||||
|
'Reject Reward': 'Reject Reward',
|
||||||
|
'In process': 'In process',
|
||||||
|
'Search by username': 'Search by username',
|
||||||
|
Clear: 'Clear',
|
||||||
|
'Date of data': 'Date of data',
|
||||||
|
'Submitted Time': 'Submitted Time',
|
||||||
|
'Reward Claim': 'Reward Claim',
|
||||||
|
Action: 'Action',
|
||||||
|
Agree: 'Agree',
|
||||||
|
Reject: 'Reject',
|
||||||
|
'Confirm reward action': 'Are you sure you want to {action} the reward request from {username}?',
|
||||||
|
'No records': 'No records',
|
||||||
|
'Total records': 'Total {total} records',
|
||||||
|
to: 'to',
|
||||||
|
Day: 'Day',
|
||||||
|
Days: 'Days',
|
||||||
|
}
|
||||||
27
web/src/lang/backend/zh-cn/user/submittedReward.ts
Normal file
27
web/src/lang/backend/zh-cn/user/submittedReward.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
export default {
|
||||||
|
'Promotion type': '活动类型',
|
||||||
|
'Submitted Rewards': '已提交奖励',
|
||||||
|
Running: '运行中',
|
||||||
|
'Start Date': '开始日期',
|
||||||
|
'End Date': '结束日期',
|
||||||
|
Status: '状态',
|
||||||
|
Username: '用户名',
|
||||||
|
'All status': '- 全部状态 -',
|
||||||
|
'Approve Reward': '批准奖励',
|
||||||
|
'Reject Reward': '拒绝奖励',
|
||||||
|
'In process': '处理中',
|
||||||
|
'Search by username': '按用户名搜索',
|
||||||
|
Clear: '清除',
|
||||||
|
'Date of data': '数据日期',
|
||||||
|
'Submitted Time': '提交时间',
|
||||||
|
'Reward Claim': '领取奖励',
|
||||||
|
Action: '操作',
|
||||||
|
Agree: '同意',
|
||||||
|
Reject: '拒绝',
|
||||||
|
'Confirm reward action': '确定要{action}用户 {username} 的奖励申请吗?',
|
||||||
|
'No records': '暂无记录',
|
||||||
|
'Total records': '共 {total} 条记录',
|
||||||
|
to: '至',
|
||||||
|
Day: '天',
|
||||||
|
Days: '天',
|
||||||
|
}
|
||||||
@@ -1,156 +1,508 @@
|
|||||||
<!--suppress TypeScriptValidateTypes -->
|
|
||||||
<template>
|
<template>
|
||||||
<div class="default-main ba-table-box">
|
<div class="default-main submitted-rewards">
|
||||||
<el-alert class="ba-table-alert" v-if="baTable.table.remark" :title="baTable.table.remark" type="info" show-icon />
|
<nav class="reward-tabs" :aria-label="t('user.submittedReward.Promotion type')">
|
||||||
|
<button
|
||||||
|
v-for="tab in promotionTabs"
|
||||||
|
:key="tab.value"
|
||||||
|
type="button"
|
||||||
|
:class="{ active: filters.gameId === tab.value }"
|
||||||
|
@click="changePromotion(tab.value)"
|
||||||
|
>
|
||||||
|
{{ tab.label }}
|
||||||
|
</button>
|
||||||
|
</nav>
|
||||||
|
|
||||||
<!-- 表格顶部菜单 -->
|
<section class="reward-panel">
|
||||||
<TableHeader
|
<header class="panel-heading">
|
||||||
:buttons="['refresh', 'add', 'edit', 'delete', 'comSearch', 'quickSearch', 'columnDisplay']"
|
<span>{{ t('user.submittedReward.Submitted Rewards') }} ({{ activePromotionLabel }})</span>
|
||||||
:quick-search-placeholder="t('Quick search placeholder', { fields: t('user.user.User name') + '/' + t('user.user.nickname') })"
|
<strong>{{ t('user.submittedReward.Running') }}</strong>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="filter-panel">
|
||||||
|
<div class="filter-item">
|
||||||
|
<label>{{ t('user.submittedReward.Start Date') }}:</label>
|
||||||
|
<el-date-picker v-model="filters.start" type="date" value-format="YYYY-MM-DD" :clearable="false" />
|
||||||
|
</div>
|
||||||
|
<div class="filter-item">
|
||||||
|
<label>{{ t('user.submittedReward.End Date') }}:</label>
|
||||||
|
<el-date-picker v-model="filters.end" type="date" value-format="YYYY-MM-DD" :clearable="false" />
|
||||||
|
</div>
|
||||||
|
<div class="filter-item">
|
||||||
|
<label>{{ t('user.submittedReward.Status') }}:</label>
|
||||||
|
<el-select v-model="filters.status">
|
||||||
|
<el-option :label="t('user.submittedReward.All status')" value="all" />
|
||||||
|
<el-option :label="t('user.submittedReward.Approve Reward')" value="1" />
|
||||||
|
<el-option :label="t('user.submittedReward.Reject Reward')" value="2" />
|
||||||
|
<el-option :label="t('user.submittedReward.In process')" value="0" />
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<div class="filter-item">
|
||||||
|
<label>{{ t('user.submittedReward.Username') }}:</label>
|
||||||
|
<el-input
|
||||||
|
v-model.trim="filters.username"
|
||||||
|
:placeholder="t('user.submittedReward.Search by username')"
|
||||||
|
clearable
|
||||||
|
@keyup.enter="search"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="filter-actions">
|
||||||
|
<el-button @click="search">{{ t('Search') }}</el-button>
|
||||||
|
<el-button @click="clearFilters">{{ t('user.submittedReward.Clear') }}</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
<!-- 表格 -->
|
<div class="date-summary">
|
||||||
<!-- 要使用`el-table`组件原有的属性,直接加在Table标签上即可 -->
|
<strong>{{ t('user.submittedReward.Date of data') }}:</strong>
|
||||||
<Table />
|
{{ dateRangeText }}
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 表单 -->
|
<div v-loading="loading" class="reward-table-wrap">
|
||||||
<PopupForm />
|
<table class="reward-table">
|
||||||
<MembersPopupForm v-model="customFormVisible" :row="customFormRow" :wallet-data="customFormData" />
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="submitted-time">{{ t('user.submittedReward.Submitted Time') }}</th>
|
||||||
|
<th class="username">{{ t('user.submittedReward.Username') }}</th>
|
||||||
|
<th class="reward-claim">{{ t('user.submittedReward.Reward Claim') }}</th>
|
||||||
|
<th>{{ t('user.submittedReward.Status') }}</th>
|
||||||
|
<th class="action">{{ t('user.submittedReward.Action') }}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="row in rows" :key="row.id">
|
||||||
|
<td>{{ row.submittedTime }}</td>
|
||||||
|
<td>{{ row.username }}</td>
|
||||||
|
<td>{{ row.rewardClaim }}</td>
|
||||||
|
<td>{{ row.status }}</td>
|
||||||
|
<td>
|
||||||
|
<div v-if="row.statusCode === 0" class="action-buttons">
|
||||||
|
<el-button
|
||||||
|
type="success"
|
||||||
|
size="small"
|
||||||
|
:loading="actionLoadingId === row.id"
|
||||||
|
@click="confirmReward(row, 1)"
|
||||||
|
>
|
||||||
|
{{ t('user.submittedReward.Agree') }}
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
type="danger"
|
||||||
|
size="small"
|
||||||
|
:loading="actionLoadingId === row.id"
|
||||||
|
@click="confirmReward(row, 2)"
|
||||||
|
>
|
||||||
|
{{ t('user.submittedReward.Reject') }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-if="!loading && rows.length === 0">
|
||||||
|
<td class="empty-row" colspan="5">{{ t('user.submittedReward.No records') }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="table-footer">
|
||||||
|
<span>{{ t('user.submittedReward.Total records', { total: pagination.total }) }}</span>
|
||||||
|
<el-pagination
|
||||||
|
v-if="pagination.total > 0"
|
||||||
|
v-model:current-page="pagination.currentPage"
|
||||||
|
background
|
||||||
|
layout="prev, pager, next"
|
||||||
|
:page-size="pagination.pageSize"
|
||||||
|
:total="pagination.total"
|
||||||
|
@current-change="changePage"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { provide, ref } from 'vue'
|
import { computed, onMounted, reactive, ref } from 'vue'
|
||||||
import { getWallet } from '/@/api/backend/user/wallet'
|
import { ElMessageBox } from 'element-plus'
|
||||||
import baTableClass from '/@/utils/baTable'
|
|
||||||
import PopupForm from './popupForm.vue'
|
|
||||||
import MembersPopupForm from './membersPopupForm.vue'
|
|
||||||
import Table from '/@/components/table/index.vue'
|
|
||||||
import TableHeader from '/@/components/table/header/index.vue'
|
|
||||||
import { defaultOptButtons } from '/@/components/table'
|
|
||||||
import { baTableApi } from '/@/api/common'
|
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import { editReward, getSubmittedRewards, type SubmittedRewardParams } from '/@/api/backend/user/submittedReward'
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'user/user',
|
name: 'user/submittedReward',
|
||||||
})
|
})
|
||||||
|
|
||||||
const { t } = useI18n()
|
type GameId = 268 | 269 | 270
|
||||||
const customFormVisible = ref(false)
|
|
||||||
const customFormRow = ref<TableRow | null>(null)
|
|
||||||
const customFormData = ref<anyObj | null>(null)
|
|
||||||
const walletLoadingId = ref<number | string | null>(null)
|
|
||||||
let walletRequestSeq = 0
|
|
||||||
|
|
||||||
const optButtons: OptButton[] = [
|
interface RewardRow {
|
||||||
{
|
id: number | string
|
||||||
render: 'tipButton',
|
submittedTime: string
|
||||||
name: 'customAction',
|
username: string
|
||||||
title: 'Members Promotion',
|
rewardClaim: string
|
||||||
text: '',
|
status: string
|
||||||
type: 'primary',
|
statusCode: number
|
||||||
icon: 'el-icon-Wallet',
|
|
||||||
class: 'table-row-custom',
|
|
||||||
disabledTip: false,
|
|
||||||
loading: (row: TableRow) => walletLoadingId.value === row.id,
|
|
||||||
click: async (row: TableRow) => {
|
|
||||||
const requestSeq = ++walletRequestSeq
|
|
||||||
walletLoadingId.value = row.id
|
|
||||||
try {
|
|
||||||
const res = await getWallet(row.id)
|
|
||||||
if (requestSeq !== walletRequestSeq) return
|
|
||||||
customFormRow.value = { ...row }
|
|
||||||
customFormData.value = res.data?.row ?? res.data ?? {}
|
|
||||||
customFormVisible.value = true
|
|
||||||
} finally {
|
|
||||||
if (requestSeq === walletRequestSeq) {
|
|
||||||
walletLoadingId.value = null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
const formatDate = (date: Date) => {
|
||||||
|
const pad = (value: number) => String(value).padStart(2, '0')
|
||||||
|
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`
|
||||||
}
|
}
|
||||||
},
|
|
||||||
},
|
const today = () => formatDate(new Date())
|
||||||
...defaultOptButtons(['edit', 'delete']),
|
|
||||||
|
const promotionTabs: { label: string; value: GameId }[] = [
|
||||||
|
{ label: 'Plinko Ball', value: 268 },
|
||||||
|
{ label: 'Smash Eggs', value: 269 },
|
||||||
|
{ label: 'Spin Wheel', value: 270 },
|
||||||
]
|
]
|
||||||
|
|
||||||
const baTable = new baTableClass(
|
const filters = reactive({
|
||||||
new baTableApi('/admin/user.User/'),
|
gameId: 268 as GameId,
|
||||||
{
|
start: today(),
|
||||||
column: [
|
end: today(),
|
||||||
{ type: 'selection', align: 'center', operator: false },
|
status: 'all' as 'all' | SubmittedRewardParams['status'],
|
||||||
{ label: t('Id'), prop: 'id', align: 'center', operator: '=', operatorPlaceholder: t('Id'), width: 70 },
|
username: '',
|
||||||
{ label: t('user.user.User name'), prop: 'jk_username', align: 'center', operator: 'LIKE', operatorPlaceholder: t('Fuzzy query') },
|
})
|
||||||
{ label: t('user.user.nickname'), prop: 'nickname', align: 'center', operator: 'LIKE', operatorPlaceholder: t('Fuzzy query') },
|
|
||||||
{ label: t('user.user.jk user id'), prop: 'jk_user_id', align: 'center', operator: 'LIKE', operatorPlaceholder: t('Fuzzy query') },
|
const pagination = reactive({
|
||||||
{ label: t('user.user.referrer code'), prop: 'referrer_code', align: 'center', operator: 'LIKE', operatorPlaceholder: t('Fuzzy query'), width: 120,},
|
currentPage: 1,
|
||||||
{
|
pageSize: 20,
|
||||||
label: t('user.user.group'),
|
total: 0,
|
||||||
prop: 'userGroup.name',
|
})
|
||||||
align: 'center',
|
|
||||||
operator: 'LIKE',
|
const rows = ref<RewardRow[]>([])
|
||||||
operatorPlaceholder: t('Fuzzy query'),
|
const loading = ref(false)
|
||||||
render: 'tag',
|
const actionLoadingId = ref<number | string | null>(null)
|
||||||
},
|
|
||||||
{ label: t('user.user.avatar'), prop: 'avatar', align: 'center', render: 'image', operator: false },
|
const activePromotionLabel = computed(() => {
|
||||||
{
|
const labelMap: Record<GameId, string> = {
|
||||||
label: t('user.user.Gender'),
|
268: 'Plinko Ball',
|
||||||
prop: 'gender',
|
269: 'Smash Eggs',
|
||||||
align: 'center',
|
270: 'Spin Wheel',
|
||||||
render: 'tag',
|
|
||||||
custom: { '0': 'info', '1': '', '2': 'success' },
|
|
||||||
replaceValue: { '0': t('Unknown'), '1': t('user.user.male'), '2': t('user.user.female') },
|
|
||||||
},
|
|
||||||
{ label: t('user.user.mobile'), prop: 'mobile', align: 'center', operator: 'LIKE', operatorPlaceholder: t('Fuzzy query') },
|
|
||||||
{
|
|
||||||
label: t('user.user.Last login IP'),
|
|
||||||
prop: 'last_login_ip',
|
|
||||||
align: 'center',
|
|
||||||
operator: 'LIKE',
|
|
||||||
operatorPlaceholder: t('Fuzzy query'),
|
|
||||||
render: 'tag',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: t('user.user.Last login'),
|
|
||||||
prop: 'last_login_time',
|
|
||||||
align: 'center',
|
|
||||||
render: 'datetime',
|
|
||||||
sortable: 'custom',
|
|
||||||
operator: 'RANGE',
|
|
||||||
width: 160,
|
|
||||||
},
|
|
||||||
{ label: t('Create time'), prop: 'create_time', align: 'center', render: 'datetime', sortable: 'custom', operator: 'RANGE', width: 160 },
|
|
||||||
{
|
|
||||||
label: t('State'),
|
|
||||||
prop: 'status',
|
|
||||||
align: 'center',
|
|
||||||
render: 'tag',
|
|
||||||
custom: { disable: 'danger', enable: 'success' },
|
|
||||||
replaceValue: { disable: t('Disable'), enable: t('Enable') },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: t('Operate'),
|
|
||||||
align: 'center',
|
|
||||||
width: '160',
|
|
||||||
render: 'buttons',
|
|
||||||
buttons: optButtons,
|
|
||||||
operator: false,
|
|
||||||
}
|
}
|
||||||
],
|
return labelMap[filters.gameId]
|
||||||
dblClickNotEditColumn: [undefined],
|
})
|
||||||
},
|
|
||||||
|
const dateRangeText = computed(() => {
|
||||||
|
const start = new Date(`${filters.start}T00:00:00`)
|
||||||
|
const end = new Date(`${filters.end}T00:00:00`)
|
||||||
|
const duration = Math.max(1, Math.floor((end.getTime() - start.getTime()) / 86400000) + 1)
|
||||||
|
const range = filters.start === filters.end ? filters.start : `${filters.start} ${t('user.submittedReward.to')} ${filters.end}`
|
||||||
|
return `${range} (${duration} ${duration === 1 ? t('user.submittedReward.Day') : t('user.submittedReward.Days')})`
|
||||||
|
})
|
||||||
|
|
||||||
|
const mapRow = (item: Record<string, any>, index: number): RewardRow => {
|
||||||
|
return {
|
||||||
|
id: item.id ?? `${pagination.currentPage}-${index}`,
|
||||||
|
submittedTime: String(item.submitted_time ?? ''),
|
||||||
|
username: String(item.username ?? ''),
|
||||||
|
rewardClaim: String(item.reward_claim ?? ''),
|
||||||
|
status: String(item.status_text ?? ''),
|
||||||
|
statusCode: Number(item.status),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const normalizeResponse = (responseData: any) => {
|
||||||
|
const source = responseData?.data ?? responseData ?? {}
|
||||||
|
const list = source.list ?? {}
|
||||||
|
const data = Array.isArray(list.data) ? list.data : []
|
||||||
|
const total = Number(list.total ?? list.count ?? data.length)
|
||||||
|
const pageSize = Number(list.per_page ?? list.page_size ?? pagination.pageSize)
|
||||||
|
const currentPage = Number(list.current_page ?? list.page ?? pagination.currentPage)
|
||||||
|
|
||||||
|
return {
|
||||||
|
rows: data.map((item: Record<string, any>, index: number) => mapRow(item, index)),
|
||||||
|
total: Number.isFinite(total) ? total : 0,
|
||||||
|
pageSize: Number.isFinite(pageSize) && pageSize > 0 ? pageSize : 20,
|
||||||
|
currentPage: Number.isFinite(currentPage) && currentPage > 0 ? currentPage : 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadRewards = async (page = pagination.currentPage) => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const response = await getSubmittedRewards({
|
||||||
|
start: filters.start,
|
||||||
|
end: filters.end,
|
||||||
|
status: filters.status === 'all' ? '' : filters.status,
|
||||||
|
username: filters.username,
|
||||||
|
game_id: filters.gameId,
|
||||||
|
page,
|
||||||
|
})
|
||||||
|
const normalized = normalizeResponse(response.data)
|
||||||
|
rows.value = normalized.rows
|
||||||
|
pagination.total = normalized.total
|
||||||
|
pagination.pageSize = normalized.pageSize
|
||||||
|
pagination.currentPage = normalized.currentPage
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const search = () => {
|
||||||
|
pagination.currentPage = 1
|
||||||
|
loadRewards(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
const clearFilters = () => {
|
||||||
|
filters.start = today()
|
||||||
|
filters.end = today()
|
||||||
|
filters.status = 'all'
|
||||||
|
filters.username = ''
|
||||||
|
pagination.currentPage = 1
|
||||||
|
loadRewards(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
const changePromotion = (gameId: GameId) => {
|
||||||
|
filters.gameId = gameId
|
||||||
|
pagination.currentPage = 1
|
||||||
|
loadRewards(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
const changePage = (page: number) => {
|
||||||
|
loadRewards(page)
|
||||||
|
}
|
||||||
|
|
||||||
|
const confirmReward = (row: RewardRow, status: 1 | 2) => {
|
||||||
|
const action = status === 1 ? t('user.submittedReward.Agree') : t('user.submittedReward.Reject')
|
||||||
|
|
||||||
|
ElMessageBox.confirm(
|
||||||
|
t('user.submittedReward.Confirm reward action', {
|
||||||
|
action,
|
||||||
|
username: row.username,
|
||||||
|
}),
|
||||||
|
t('Confirm'),
|
||||||
{
|
{
|
||||||
defaultItems: {
|
confirmButtonText: t('Confirm'),
|
||||||
gender: 0,
|
cancelButtonText: t('Cancel'),
|
||||||
money: '0',
|
type: status === 1 ? 'success' : 'warning',
|
||||||
score: '0',
|
|
||||||
status: 'enable',
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
.then(() => {
|
||||||
|
actionLoadingId.value = row.id
|
||||||
|
return editReward({ id: row.id, status })
|
||||||
|
})
|
||||||
|
.then(() => loadRewards(pagination.currentPage))
|
||||||
|
.finally(() => {
|
||||||
|
actionLoadingId.value = null
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
// Closing the confirmation dialog does not require feedback.
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
baTable.mount()
|
onMounted(() => {
|
||||||
baTable.getData()
|
loadRewards(1)
|
||||||
|
})
|
||||||
provide('baTable', baTable)
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss"></style>
|
<style scoped lang="scss">
|
||||||
|
.submitted-rewards {
|
||||||
|
--reward-dark: #333;
|
||||||
|
--reward-border: #ddd;
|
||||||
|
--reward-approved: #dcfbc9;
|
||||||
|
padding: 20px;
|
||||||
|
color: var(--el-text-color-primary);
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reward-tabs {
|
||||||
|
display: flex;
|
||||||
|
width: fit-content;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
overflow: hidden;
|
||||||
|
border: 1px solid #999;
|
||||||
|
border-radius: 4px;
|
||||||
|
|
||||||
|
button {
|
||||||
|
min-width: 136px;
|
||||||
|
height: 31px;
|
||||||
|
padding: 5px 30px;
|
||||||
|
border: 0;
|
||||||
|
border-right: 1px solid #999;
|
||||||
|
background: var(--el-fill-color-light);
|
||||||
|
color: var(--el-text-color-primary);
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
min-width: 99px;
|
||||||
|
border-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: var(--el-fill-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background: #bbb;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.reward-panel {
|
||||||
|
border: 1px solid var(--reward-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-heading {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
min-height: 40px;
|
||||||
|
padding: 10px;
|
||||||
|
background: var(--reward-dark);
|
||||||
|
color: #fff;
|
||||||
|
font-weight: 700;
|
||||||
|
|
||||||
|
strong {
|
||||||
|
color: #57e31a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-panel {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px 28px;
|
||||||
|
min-height: 88px;
|
||||||
|
padding: 14px 40px;
|
||||||
|
background: var(--el-bg-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
|
||||||
|
label {
|
||||||
|
min-width: 76px;
|
||||||
|
text-align: right;
|
||||||
|
font-weight: 700;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-date-editor),
|
||||||
|
:deep(.el-select),
|
||||||
|
:deep(.el-input) {
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
.el-button {
|
||||||
|
width: 100px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-summary {
|
||||||
|
margin: 20px 0 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reward-table-wrap {
|
||||||
|
min-height: 120px;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reward-table {
|
||||||
|
width: 100%;
|
||||||
|
min-width: 850px;
|
||||||
|
border-collapse: collapse;
|
||||||
|
|
||||||
|
th,
|
||||||
|
td {
|
||||||
|
height: 37px;
|
||||||
|
padding: 8px;
|
||||||
|
border: 1px solid var(--reward-border);
|
||||||
|
text-align: left;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
background: var(--reward-dark);
|
||||||
|
color: #fff;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody tr {
|
||||||
|
background: var(--reward-approved);
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submitted-time {
|
||||||
|
width: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.username {
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reward-claim {
|
||||||
|
width: 180px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action {
|
||||||
|
width: 180px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-row {
|
||||||
|
height: 90px;
|
||||||
|
background: var(--el-bg-color);
|
||||||
|
color: var(--el-text-color-secondary);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
.el-button {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-footer {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 8px;
|
||||||
|
margin-top: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@at-root html.dark {
|
||||||
|
.submitted-rewards {
|
||||||
|
--reward-dark: #2b2b2b;
|
||||||
|
--reward-border: var(--el-border-color);
|
||||||
|
--reward-approved: #29482b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reward-tabs button.active {
|
||||||
|
background: #555;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reward-table tbody tr {
|
||||||
|
color: var(--el-text-color-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 900px) {
|
||||||
|
.submitted-rewards {
|
||||||
|
padding: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reward-tabs {
|
||||||
|
width: 100%;
|
||||||
|
overflow-x: auto;
|
||||||
|
|
||||||
|
button {
|
||||||
|
min-width: 125px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-panel {
|
||||||
|
padding: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user