feat(admin): 统一用户单元格,展示游客设备号与客户端系统

- 新增 AppUserCell,游客显示标签+deviceId,第二行统一展示系统与机型
- 收藏、点赞、观看记录三页复用,观看记录去掉重复的系统列
This commit is contained in:
Vicky authored and trae-solo-agent committed 2026-10-27 13:53:53 +08:00
1 parent c45820258e
commit f3fbc57c14
5 files changed
+78 -50

No files matched your search

+63
View File
@@ -0,0 +1,63 @@
<!-- Author: fruit.com.cn -->
<script setup>
import { computed } from 'vue'
/**
* 后台各列表共用的「用户」单元格。
*
* 口径:已登录显示昵称 + uid;未登录显示「游客」标签 + deviceId(单行省略,悬浮看全值)。
* 第二行统一展示客户端系统,系统缺失(老客户端没上报)时显示横线。
*/
const props = defineProps({
row: { type: Object, required: true }
})
const PLATFORM_TEXT = { ANDROID: 'Android', IOS: 'iOS', WEB: 'Web' }
const isGuest = computed(() => props.row?.userId == null)
const systemText = computed(() => {
const row = props.row || {}
const name = PLATFORM_TEXT[row.platform] || row.platform || ''
const version = row.osVersion || ''
const text = `${name} ${version}`.trim()
if (!text) return '—'
return row.deviceModel ? `${text} · ${row.deviceModel}` : text
})
</script>
<template>
<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>
</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>
</template>
<span class="app-user-system">{{ systemText }}</span>
</div>
</template>
<style scoped>
.app-user-device {
max-width: 150px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.app-user-system {
color: #b0adbd;
font-size: 12px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
</style>
+3 -20
View File
@@ -4,6 +4,7 @@
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 { pageFavoritesApi } from '@/api/admin/engagement'
const PAGE_SIZES = [10, 20, 50]
@@ -104,20 +105,9 @@ onMounted(load)
class="drama-el-table"
empty-text="暂无收藏"
>
<el-table-column label="用户" min-width="180">
<el-table-column label="用户" min-width="200">
<template #default="{ row }">
<div class="app-user-meta">
<template v-if="row.userId == null">
<el-tag type="info" size="small">游客</el-tag>
<span class="app-user-uid engagement-device-id" :title="row.deviceId || ''">{{
row.deviceId || '—'
}}</span>
</template>
<template v-else>
<span class="app-user-name">{{ row.nickname || '未设置昵称' }}</span>
<span class="app-user-uid">{{ row.uid || `用户 #${row.userId}` }}</span>
</template>
</div>
<AppUserCell :row="row" />
</template>
</el-table-column>
<el-table-column label="短剧" min-width="220">
@@ -156,13 +146,6 @@ onMounted(load)
</template>
<style scoped>
.engagement-device-id {
max-width: 150px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.engagement-range {
width: 360px;
max-width: 100%;
+3 -20
View File
@@ -4,6 +4,7 @@
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'
const PAGE_SIZES = [10, 20, 50]
@@ -127,20 +128,9 @@ onMounted(load)
class="drama-el-table"
empty-text="暂无点赞"
>
<el-table-column label="用户" min-width="180">
<el-table-column label="用户" min-width="200">
<template #default="{ row }">
<div class="app-user-meta">
<template v-if="row.userId == null">
<el-tag type="info" size="small">游客</el-tag>
<span class="app-user-uid engagement-device-id" :title="row.deviceId || ''">{{
row.deviceId || '—'
}}</span>
</template>
<template v-else>
<span class="app-user-name">{{ row.nickname || '未设置昵称' }}</span>
<span class="app-user-uid">{{ row.uid || `用户 #${row.userId}` }}</span>
</template>
</div>
<AppUserCell :row="row" />
</template>
</el-table-column>
<el-table-column label="目标类型" width="110">
@@ -172,13 +162,6 @@ onMounted(load)
</template>
<style scoped>
.engagement-device-id {
max-width: 150px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.engagement-range {
width: 360px;
max-width: 100%;
@@ -3,8 +3,9 @@
<script setup>
import { onMounted, reactive, ref } from 'vue'
import PageHeading from '@/views/components/PageHeading.vue'
import AppUserCell from '@/views/components/AppUserCell.vue'
import { pageWatchHistoryApi } from '@/api/admin/appUser'
import { formatDuration, systemText } from './composables/useAppUsers'
import { formatDuration } from './composables/useAppUsers'
const SOURCE_OPTIONS = [
{ value: '', label: '全部' },
@@ -168,17 +169,11 @@ onMounted(load)
empty-text="暂无符合条件的观看记录"
>
<el-table-column prop="watchedAt" label="观看时间" min-width="170" show-overflow-tooltip />
<el-table-column label="用户" min-width="180">
<el-table-column label="用户" min-width="200">
<template #default="{ row }">
<div class="app-user-meta">
<span class="app-user-name">{{ row.nickname || '未设置昵称' }}</span>
<span class="app-user-uid">{{ row.uid || `用户 #${row.userId || '—'}` }}</span>
</div>
<AppUserCell :row="row" />
</template>
</el-table-column>
<el-table-column label="系统" width="130" show-overflow-tooltip>
<template #default="{ row }">{{ systemText(row) }}</template>
</el-table-column>
<el-table-column label="短剧" min-width="190">
<template #default="{ row }">
<el-tooltip :content="contentTooltip(row)" placement="top">