From 5580f9b99bdd0b63fd7fad0388a92c55e019f9be Mon Sep 17 00:00:00 2001 From: Zhou Weidong <502333560@qq.com> Date: Tue, 27 Oct 2026 12:38:31 +0800 Subject: [PATCH 01/12] =?UTF-8?q?feat(admin):=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E6=94=B6=E8=97=8F=E4=B8=8E=E7=82=B9=E8=B5=9E=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E9=A1=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 全量 lint 仍有 5 处既有 vue/no-mutating-props 基线错误, 位于 LocaleTextFields.vue 与 ClassificationDramaDialogs.vue,本次未处理。 --- src/api/admin/engagement.ts | 50 ++++++ src/views/userManagement/FavoritesView.vue | 172 ++++++++++++++++++++ src/views/userManagement/LikesView.vue | 177 +++++++++++++++++++++ 3 files changed, 399 insertions(+) create mode 100644 src/api/admin/engagement.ts create mode 100644 src/views/userManagement/FavoritesView.vue create mode 100644 src/views/userManagement/LikesView.vue diff --git a/src/api/admin/engagement.ts b/src/api/admin/engagement.ts new file mode 100644 index 0000000..c79b63f --- /dev/null +++ b/src/api/admin/engagement.ts @@ -0,0 +1,50 @@ +// Author: fruit.com.cn + +import request from '@/axios' +import type { PageResult } from './types' + +/** 收藏与点赞只读分页筛选条件。 */ +export interface EngagementPageParams { + pageIndex?: number + pageSize?: number + keyword?: string + userId?: string | number + deviceId?: string + dramaId?: string | number + dramaTitle?: string + targetType?: string + targetId?: string | number + episodeId?: string | number + startTime?: string + endTime?: string +} + +/** 后台互动列表行。 */ +export interface EngagementItem { + id: string + userId: string | null + uid: string | null + nickname: string | null + deviceId: string | null + anonymous: boolean + dramaId: string | null + dramaTitle: string | null + dramaCover: string | null + dramaStatus: string | null + dramaPublished: boolean + targetType: string + targetId: string + episodeId: string | null + episodeNo: number | null + episodeTitle: string | null + commentSummary: string | null + createdAt: string +} + +/** 查询收藏分页。 */ +export const pageFavoritesApi = (params: EngagementPageParams) => + request.get>({ url: '/admin/favorites/page', params }) + +/** 查询点赞分页。 */ +export const pageLikesApi = (params: EngagementPageParams) => + request.get>({ url: '/admin/likes/page', params }) diff --git a/src/views/userManagement/FavoritesView.vue b/src/views/userManagement/FavoritesView.vue new file mode 100644 index 0000000..f51460a --- /dev/null +++ b/src/views/userManagement/FavoritesView.vue @@ -0,0 +1,172 @@ + + + + + + + diff --git a/src/views/userManagement/LikesView.vue b/src/views/userManagement/LikesView.vue new file mode 100644 index 0000000..f0cddb5 --- /dev/null +++ b/src/views/userManagement/LikesView.vue @@ -0,0 +1,177 @@ + + + + + + + From 3409a2b4275a3ba4b5396e466e9eed4be3399a90 Mon Sep 17 00:00:00 2001 From: Zhou Weidong <502333560@qq.com> Date: Tue, 27 Oct 2026 12:47:45 +0800 Subject: [PATCH 02/12] =?UTF-8?q?fix(admin):=20=E4=BF=AE=E5=A4=8D=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=20props=20=E5=8F=98=E5=BC=82=E7=9A=84=20lint=20?= =?UTF-8?q?=E5=9F=BA=E7=BA=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/components/LocaleTextFields.vue | 16 ++++++++++++---- .../contentManagement/CategoryDramaView.vue | 1 + .../CategoryManagementView.vue | 1 + .../ClassificationDramaDialogs.vue | 17 +++++++++++++++-- .../contentManagement/DramaManagementView.vue | 2 ++ .../contentManagement/DramaPlaylistView.vue | 2 ++ .../contentManagement/TagManagementView.vue | 1 + 7 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/views/components/LocaleTextFields.vue b/src/views/components/LocaleTextFields.vue index f331fb1..cc52082 100644 --- a/src/views/components/LocaleTextFields.vue +++ b/src/views/components/LocaleTextFields.vue @@ -13,15 +13,21 @@ const props = defineProps({ showLanguages: { type: Boolean, default: true }, required: { type: Boolean, default: true } }) -const emit = defineEmits(['update:languages']) +const emit = defineEmits(['update:languages', 'update:locales']) function changeLanguages(codes) { const next = codes.includes('zh') ? codes : ['zh', ...codes] + const locales = { ...props.locales } next.forEach((code) => { - if (props.locales[code] == null) props.locales[code] = '' + if (locales[code] == null) locales[code] = '' }) + emit('update:locales', locales) emit('update:languages', next) } + +function changeLocale(code, value) { + emit('update:locales', { ...props.locales, [code]: value }) +} diff --git a/src/views/userManagement/FavoritesView.vue b/src/views/userManagement/FavoritesView.vue index 2c63e7a..51f677e 100644 --- a/src/views/userManagement/FavoritesView.vue +++ b/src/views/userManagement/FavoritesView.vue @@ -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="暂无收藏" > - + @@ -156,13 +146,6 @@ onMounted(load) From 5dbc752798757900c31cff7e5371448166fef793 Mon Sep 17 00:00:00 2001 From: Vicky <10212746+haifeng-jiang@user.noreply.gitee.com> Date: Tue, 27 Oct 2026 14:17:37 +0800 Subject: [PATCH 07/12] =?UTF-8?q?feat(admin):=20=E8=A7=82=E7=9C=8B/?= =?UTF-8?q?=E6=94=B6=E8=97=8F/=E7=82=B9=E8=B5=9E=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E5=8D=95=E7=8B=AC=E5=A2=9E=E5=8A=A0=E7=B3=BB=E7=BB=9F=E5=88=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 用户单元格只保留身份信息,Android/iOS 抽成独立「系统」列,三页列结构一致。 --- src/views/components/AppUserCell.vue | 15 +-------------- src/views/userManagement/FavoritesView.vue | 4 ++++ src/views/userManagement/LikesView.vue | 4 ++++ src/views/userManagement/WatchHistoryView.vue | 5 ++++- .../userManagement/composables/useAppUsers.js | 6 ++++++ 5 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/views/components/AppUserCell.vue b/src/views/components/AppUserCell.vue index 5215b94..eb2866d 100644 --- a/src/views/components/AppUserCell.vue +++ b/src/views/components/AppUserCell.vue @@ -7,20 +7,13 @@ import { computed } from 'vue' * 后台各列表共用的「用户」单元格。 * * 口径:已登录显示昵称 + uid;未登录显示「游客」标签 + deviceId(单行省略,悬浮看全值)。 - * 第二行只展示客户端平台(Android / iOS),老客户端没上报时显示横线。 + * 客户端平台由独立的「系统」列展示,这里不再重复。 */ 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 platformText = computed(() => { - const platform = props.row?.platform || '' - return PLATFORM_TEXT[platform] || platform || '—' -}) - {{ platformText }} @@ -48,9 +40,4 @@ const platformText = computed(() => { text-overflow: ellipsis; white-space: nowrap; } - -.app-user-platform { - color: #b0adbd; - font-size: 12px; -} diff --git a/src/views/userManagement/FavoritesView.vue b/src/views/userManagement/FavoritesView.vue index 51f677e..105a85f 100644 --- a/src/views/userManagement/FavoritesView.vue +++ b/src/views/userManagement/FavoritesView.vue @@ -6,6 +6,7 @@ import dayjs from 'dayjs' import PageHeading from '@/views/components/PageHeading.vue' import AppUserCell from '@/views/components/AppUserCell.vue' import { pageFavoritesApi } from '@/api/admin/engagement' +import { platformText } from './composables/useAppUsers' const PAGE_SIZES = [10, 20, 50] @@ -110,6 +111,9 @@ onMounted(load) + + + + + + diff --git a/src/views/userManagement/WatchHistoryView.vue b/src/views/userManagement/WatchHistoryView.vue index 8fd78b4..1feb6db 100644 --- a/src/views/userManagement/WatchHistoryView.vue +++ b/src/views/userManagement/WatchHistoryView.vue @@ -5,7 +5,7 @@ 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 } from './composables/useAppUsers' +import { formatDuration, platformText } from './composables/useAppUsers' const SOURCE_OPTIONS = [ { value: '', label: '全部' }, @@ -174,6 +174,9 @@ onMounted(load) + + + diff --git a/src/views/userManagement/FavoritesView.vue b/src/views/userManagement/FavoritesView.vue index 105a85f..295a13a 100644 --- a/src/views/userManagement/FavoritesView.vue +++ b/src/views/userManagement/FavoritesView.vue @@ -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" /> + + + + + + - + + + diff --git a/src/views/userManagement/WatchHistoryView.vue b/src/views/userManagement/WatchHistoryView.vue index 4ccfc27..e834a6d 100644 --- a/src/views/userManagement/WatchHistoryView.vue +++ b/src/views/userManagement/WatchHistoryView.vue @@ -5,7 +5,7 @@ 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, platformText } from './composables/useAppUsers' +import { formatDateTime, formatDuration, platformText } from './composables/useAppUsers' const SOURCE_OPTIONS = [ { value: '', label: '全部' }, @@ -190,7 +190,9 @@ onMounted(load) class="drama-el-table" empty-text="暂无符合条件的观看记录" > - + + +
- {{ - row.nickname || '未设置昵称' - }} - {{ row.uid }} + + 昵称: {{ row.nickname || '未设置昵称' }} + + UID: {{ row.uid }}
- - + + - - + +