202 lines
5.6 KiB
Vue
202 lines
5.6 KiB
Vue
<!-- Author: fruit.com.cn -->
|
|
|
|
<script setup>
|
|
import { onMounted, reactive, ref } from 'vue'
|
|
import dayjs from 'dayjs'
|
|
import PageHeading from '@/views/components/PageHeading.vue'
|
|
import AppUserCell from '@/views/components/AppUserCell.vue'
|
|
import { pageLikesApi } from '@/api/admin/engagement'
|
|
import { platformText } from './composables/useAppUsers'
|
|
|
|
const PAGE_SIZES = [10, 20, 50]
|
|
const TARGET_OPTIONS = [
|
|
{ value: '', label: '全部' },
|
|
{ value: 'DRAMA', label: '短剧' },
|
|
{ value: 'EPISODE', label: '剧集' },
|
|
{ value: 'COMMENT', label: '评论' }
|
|
]
|
|
const PLATFORM_OPTIONS = [
|
|
{ value: '', label: '全部系统' },
|
|
{ value: 'ANDROID', label: 'Android' },
|
|
{ value: 'IOS', label: 'iOS' }
|
|
]
|
|
|
|
const filters = reactive({
|
|
keyword: '',
|
|
deviceId: '',
|
|
dramaTitle: '',
|
|
range: null,
|
|
targetType: '',
|
|
platform: ''
|
|
})
|
|
const rows = ref([])
|
|
const total = ref(0)
|
|
const loading = ref(false)
|
|
const pageIndex = ref(1)
|
|
const pageSize = ref(10)
|
|
|
|
async function load() {
|
|
loading.value = true
|
|
try {
|
|
const res = await pageLikesApi({
|
|
pageIndex: pageIndex.value,
|
|
pageSize: pageSize.value,
|
|
keyword: filters.keyword.trim() || undefined,
|
|
deviceId: filters.deviceId.trim() || undefined,
|
|
dramaTitle: filters.dramaTitle.trim() || undefined,
|
|
targetType: filters.targetType || undefined,
|
|
platform: filters.platform || undefined,
|
|
startTime: filters.range?.[0] || undefined,
|
|
endTime: filters.range?.[1] || undefined
|
|
})
|
|
rows.value = res.data?.list || []
|
|
total.value = res.data?.total || 0
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
function search() {
|
|
pageIndex.value = 1
|
|
load()
|
|
}
|
|
|
|
function resetFilters() {
|
|
Object.assign(filters, {
|
|
keyword: '',
|
|
deviceId: '',
|
|
dramaTitle: '',
|
|
range: null,
|
|
targetType: '',
|
|
platform: ''
|
|
})
|
|
search()
|
|
}
|
|
|
|
function handleSizeChange() {
|
|
pageIndex.value = 1
|
|
load()
|
|
}
|
|
|
|
function formatTime(value) {
|
|
return value && dayjs(value).isValid() ? dayjs(value).format('YYYY-MM-DD HH:mm:ss') : '—'
|
|
}
|
|
|
|
function targetText(row) {
|
|
if (row.targetType === 'COMMENT') return row.commentSummary || '—'
|
|
if (row.targetType === 'EPISODE') return `${row.dramaTitle || '—'} 第 ${row.episodeNo ?? '—'} 集`
|
|
return row.dramaTitle || '—'
|
|
}
|
|
|
|
function typeText(type) {
|
|
return TARGET_OPTIONS.find((item) => item.value === type)?.label || type || '—'
|
|
}
|
|
|
|
onMounted(load)
|
|
</script>
|
|
|
|
<template>
|
|
<PageHeading eyebrow="用户管理" title="点赞列表" />
|
|
<section class="panel">
|
|
<div class="console-toolbar">
|
|
<el-input
|
|
v-model="filters.keyword"
|
|
class="console-keyword"
|
|
clearable
|
|
placeholder="uid / 昵称"
|
|
@keyup.enter="search"
|
|
/>
|
|
<el-input
|
|
v-model="filters.deviceId"
|
|
class="console-keyword"
|
|
clearable
|
|
placeholder="设备 ID"
|
|
@keyup.enter="search"
|
|
/>
|
|
<el-input
|
|
v-model="filters.dramaTitle"
|
|
class="console-keyword"
|
|
clearable
|
|
placeholder="短剧名称"
|
|
@keyup.enter="search"
|
|
/>
|
|
<el-select v-model="filters.targetType" class="console-select" placeholder="全部目标类型">
|
|
<el-option
|
|
v-for="item in TARGET_OPTIONS"
|
|
:key="item.value"
|
|
:label="item.label"
|
|
:value="item.value"
|
|
/>
|
|
</el-select>
|
|
<el-select v-model="filters.platform" class="console-select" placeholder="全部系统">
|
|
<el-option
|
|
v-for="item in PLATFORM_OPTIONS"
|
|
:key="item.value"
|
|
:label="item.label"
|
|
:value="item.value"
|
|
/>
|
|
</el-select>
|
|
<el-date-picker
|
|
v-model="filters.range"
|
|
class="engagement-range"
|
|
type="datetimerange"
|
|
value-format="YYYY-MM-DD HH:mm:ss"
|
|
range-separator="至"
|
|
start-placeholder="开始时间"
|
|
end-placeholder="结束时间"
|
|
/>
|
|
<el-button type="primary" @click="search">查询</el-button>
|
|
<el-button @click="resetFilters">重置</el-button>
|
|
<span class="console-count">共 {{ total }} 条</span>
|
|
</div>
|
|
<el-table
|
|
v-loading="loading"
|
|
:data="rows"
|
|
row-key="id"
|
|
border
|
|
class="drama-el-table"
|
|
empty-text="暂无点赞"
|
|
>
|
|
<el-table-column label="用户" min-width="200">
|
|
<template #default="{ row }">
|
|
<AppUserCell :row="row" />
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column label="系统" width="100">
|
|
<template #default="{ row }">{{ platformText(row) }}</template>
|
|
</el-table-column>
|
|
<el-table-column label="目标类型" width="110">
|
|
<template #default="{ row }">{{ typeText(row.targetType) }}</template>
|
|
</el-table-column>
|
|
<el-table-column label="目标" min-width="200" show-overflow-tooltip>
|
|
<template #default="{ row }"
|
|
><span :title="targetText(row)">{{ targetText(row) }}</span></template
|
|
>
|
|
</el-table-column>
|
|
<el-table-column prop="dramaTitle" label="所属短剧" min-width="180" show-overflow-tooltip />
|
|
<el-table-column label="点赞时间" min-width="170">
|
|
<template #default="{ row }">{{ formatTime(row.createdAt) }}</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
<div class="pagination">
|
|
<el-pagination
|
|
v-model:current-page="pageIndex"
|
|
v-model:page-size="pageSize"
|
|
:page-sizes="PAGE_SIZES"
|
|
:total="total"
|
|
layout="total, sizes, prev, pager, next, jumper"
|
|
background
|
|
@current-change="load"
|
|
@size-change="handleSizeChange"
|
|
/>
|
|
</div>
|
|
</section>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.engagement-range {
|
|
width: 360px;
|
|
max-width: 100%;
|
|
}
|
|
</style>
|