feat(admin): 列表支持按系统筛选,用户列补语义标签

- 收藏/点赞/观看增加「全部系统 / Android / iOS」下拉
- 用户列第二行标注 UID,游客行标注设备,避免一串字母看不出含义
This commit is contained in:
Vicky authored and trae-solo-agent committed 2026-10-27 14:27:16 +08:00
1 parent 5dbc752798
commit e1eb58d4c4
6 files changed
+93 -14

No files matched your search

+2
View File
@@ -21,6 +21,8 @@ export interface WatchHistoryPageParams {
dramaTitle?: string
dramaId?: number
episodeId?: number
/** 客户端平台:ANDROID / IOS / WEB */
platform?: string
source?: string
finished?: boolean
startTime?: string
+2
View File
@@ -10,6 +10,8 @@ export interface EngagementPageParams {
keyword?: string
userId?: string | number
deviceId?: string
/** 客户端平台:ANDROID / IOS / WEB */
platform?: string
dramaId?: string | number
dramaTitle?: string
targetType?: string
+9 -9
View File
@@ -6,8 +6,8 @@ import { computed } from 'vue'
/**
* 后台各列表共用的「用户」单元格。
*
* 口径:已登录显示昵称 + uid;未登录显示「游客」标签 + deviceId(单行省略,悬浮看全值)。
* 客户端平台由独立的「系统」列展示,这里不再重复。
* 口径:已登录显示昵称 + `UID xxx`;未登录显示「游客」标签 + `设备 xxx`。
* 两行都带标签,避免一串随机字母看不出是什么。平台由独立的「系统」列展示。
*/
const props = defineProps({
row: { type: Object, required: true }
@@ -20,15 +20,15 @@ const isGuest = computed(() => props.row?.userId == null)
<div class="app-user-meta">
<template v-if="isGuest">
<el-tag type="info" size="small">游客</el-tag>
<span class="app-user-uid app-user-device" :title="row.deviceId || ''">{{
row.deviceId || '—'
}}</span>
<span class="app-user-uid app-user-device" :title="row.deviceId || ''">
设备 {{ row.deviceId || '—' }}
</span>
</template>
<template v-else>
<span class="app-user-name" :title="row.nickname || ''">{{
row.nickname || '未设置昵称'
}}</span>
<span class="app-user-uid">{{ row.uid || `用户 #${row.userId}` }}</span>
<span class="app-user-name" :title="row.nickname || ''">
{{ row.nickname || '未设置昵称' }}
</span>
<span class="app-user-uid">UID {{ row.uid || `#${row.userId}` }}</span>
</template>
</div>
</template>
+28 -3
View File
@@ -9,8 +9,19 @@ import { pageFavoritesApi } from '@/api/admin/engagement'
import { platformText } from './composables/useAppUsers'
const PAGE_SIZES = [10, 20, 50]
const PLATFORM_OPTIONS = [
{ value: '', label: '全部系统' },
{ value: 'ANDROID', label: 'Android' },
{ value: 'IOS', label: 'iOS' }
]
const filters = reactive({ keyword: '', deviceId: '', dramaTitle: '', range: null })
const filters = reactive({
keyword: '',
deviceId: '',
dramaTitle: '',
platform: '',
range: null
})
const rows = ref([])
const total = ref(0)
const loading = ref(false)
@@ -26,7 +37,7 @@ async function load() {
keyword: filters.keyword.trim() || undefined,
deviceId: filters.deviceId.trim() || undefined,
dramaTitle: filters.dramaTitle.trim() || undefined,
platform: filters.platform || undefined,
startTime: filters.range?.[0] || undefined,
endTime: filters.range?.[1] || undefined
})
@@ -43,7 +54,13 @@ function search() {
}
function resetFilters() {
Object.assign(filters, { keyword: '', deviceId: '', dramaTitle: '', range: null })
Object.assign(filters, {
keyword: '',
deviceId: '',
dramaTitle: '',
platform: '',
range: null
})
search()
}
@@ -84,6 +101,14 @@ onMounted(load)
placeholder="短剧名称"
@keyup.enter="search"
/>
<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"
+30 -2
View File
@@ -15,8 +15,20 @@ const TARGET_OPTIONS = [
{ 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: '' })
const filters = reactive({
keyword: '',
deviceId: '',
dramaTitle: '',
range: null,
targetType: '',
platform: ''
})
const rows = ref([])
const total = ref(0)
const loading = ref(false)
@@ -33,6 +45,7 @@ async function load() {
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
})
@@ -49,7 +62,14 @@ function search() {
}
function resetFilters() {
Object.assign(filters, { keyword: '', deviceId: '', dramaTitle: '', range: null, targetType: '' })
Object.assign(filters, {
keyword: '',
deviceId: '',
dramaTitle: '',
range: null,
targetType: '',
platform: ''
})
search()
}
@@ -108,6 +128,14 @@ onMounted(load)
: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"
@@ -21,11 +21,18 @@ const FINISHED_OPTIONS = [
{ value: false, label: '未看完' }
]
const PLATFORM_OPTIONS = [
{ value: '', label: '全部系统' },
{ value: 'ANDROID', label: 'Android' },
{ value: 'IOS', label: 'iOS' }
]
const filters = reactive({
keyword: '',
dramaTitle: '',
source: '',
finished: '',
platform: '',
range: null
})
const rows = ref([])
@@ -44,6 +51,7 @@ async function load() {
dramaTitle: filters.dramaTitle.trim() || undefined,
source: filters.source || undefined,
finished: filters.finished === '' ? undefined : filters.finished,
platform: filters.platform || undefined,
startTime: filters.range?.[0] || undefined,
endTime: filters.range?.[1] || undefined
})
@@ -64,6 +72,7 @@ function resetFilters() {
filters.dramaTitle = ''
filters.source = ''
filters.finished = ''
filters.platform = ''
filters.range = null
search()
}
@@ -145,6 +154,19 @@ onMounted(load)
:value="item.value"
/>
</el-select>
<el-select
v-model="filters.platform"
class="console-select"
placeholder="全部系统"
@change="search"
>
<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="watch-history-range"