拓冰建站拓冰建站
首页 / 资讯中心 / 正文

IPTVnator 同质门户目录隐藏类型徽章:GridListComponent 冗余 `LIVE`/`VOD`/`SERIES` 徽章移除设计与实现解析

IPTVnator 同质门户目录隐藏类型徽章GridListComponent 冗余LIVE/VOD/SERIES徽章移除设计与实现解析【免费下载链接】iptvnator:tv: Cross-platform IPTV player application with multiple features, such as support of m3u and m3u8 playlists, favorites, TV guide, TV archive/catchup and more.项目地址: https://gitcode.com/GitHub_Trending/ip/iptvnator导读本文围绕 IPTVnator 共享门户组件GridListComponent的“同质目录隐藏类型徽章”设计文档系统讲解为什么在用户已通过门户侧栏选定 Live TV / VOD / Series 之后网格卡片上重复渲染的LIVE、VOD、SERIES徽章属于冗余信息以及如何在不破坏组件type输入其余职责的前提下安全移除徽章标记与专属样式。读完本文你将掌握该改动的完整设计脉络、受影响范围Xtream / Stalker 各类型网格、回归测试策略与验证命令并理解type输入在 IPTVnator 中除徽章之外还驱动的三类“与提供方无关”的行为占位图标选择、直播标题前缀剥离、海报/logo 展示策略。背景信息已被导航语境建立的网格为何还要再贴一次标签设计文档开篇Context 小节点明了问题的根源共享的GridListComponent是在用户已经于门户侧栏完成类型选择Live TV、VOD 或 Series之后才渲染目录条目的。也就是说用户进入某个分类网格时页面周围的导航本身已经明确了当前内容类型——例如侧栏高亮的“VOD”分类、面包屑标题等。此时网格中每一张卡片再叠加一个LIVE/VOD/SERIES徽章只是把导航上下文里已经确立的信息在卡片上重复一遍。与之形成对照的是混合内容mixed-content界面例如门户搜索、收藏、最近添加recently added和仪表盘dashboard等表面同一屏内可能同时出现直播频道、电影和剧集。在这些场景里类型徽章承担了“区分结果类型”的真实职责因此必须保留。从源码结构看两类卡片的职责划分非常清晰组件定位类型徽章GridListComponent同质目录网格分类浏览移除本次改动ContentCardComponent混合内容卡片搜索、收藏、最近添加、仪表盘保留ContentCardComponent的模板中类型徽章由showTypeBadge输入显式控制默认渲染见 content-card.component.htmlif (type() showTypeBadge()) { span classtype-badge [class]type() {{ type() }} /span }因此本次改动只触碰GridListComponent一家ContentCardComponent及其所有混合内容宿主Xtream 搜索结果、Stalker 搜索、收藏布局、最近添加等均保持不变。设计方案只删徽章不动type输入设计文档明确给出了最小侵入式的改动原则从GridListComponent中移除类型徽章的标记markup及其专属样式但保留组件的type输入。这是因为type输入还承担着与徽章展示完全无关、且对提供方中立的若干行为控制职责。待移除的徽章标记实现计划plans/2026-07-20-hide-homogeneous-catalog-type-badges.md给出了精确的删除范围模板中仅需移除下面这一块if (type()) { ... }包裹的徽章divif (type()) { div classtype-badge [class.live]type() live [class.movie]type() vod [class.series]type() series {{ type() }} /div }待移除的徽章专属样式grid-list.component.scss中的.type-badge规则连同其.live、.movie、.series三个变体一并删除。被移除的样式块完整内容如下它定义了徽章的绝对定位、胶囊底色、字号字重以及按类型区分的强调色.type-badge { position: absolute; top: 6px; left: 6px; z-index: 1; padding: 3px 6px; border-radius: 5px; font-size: 0.58rem; font-weight: 700; line-height: 1; text-transform: uppercase; letter-spacing: 0.04em; background: rgba(0, 0, 0, 0.85); color: #fff; .live { color: #ef5350; } .movie { color: #42a5f5; } .series { color: #66bb6a; } }这里有三点值得注意不要动内容卡片的徽章 mixin实现计划明确提示删除范围仅限于grid-list.component.scsscontent-card.component.*及其徽章样式完全隔离避免改动波及其他表面。徽章删除不影响其余徽章体系GridListComponent中仍保留着catchup-badge回看/时移徽章仅直播网格渲染、ratingIMDb 评分徽章和watched-badge观看状态徽章等其他覆盖物它们各自有独立的语义与类型徽章无关。结构语义不变移除的是一个装饰性覆盖层卡片的可访问名称仍由aria-label标题承担键盘交互Enter/Space 激活不受影响。保留type输入的三类真实职责设计文档列举了type输入继续保留的三项职责我们可以在 grid-list.component.ts 的源码中找到一一对应的事实职责一选择占位图标的图标种类getPlaceholderIcon()根据type()决定无封面/封面加载失败时渲染哪个 Material 图标grid-list.component.tsprotected getPlaceholderIcon(): string { switch (this.type()) { case live: return live_tv; case series: return tv; default: return movie; } }职责二将国家前缀剥离限制在直播内容上isLiveGrid计算信号判断当前网格是否为直播类型live | itv | radio而channelTitle只有在isLiveGrid()且用户开启SettingsStore.stripCountryPrefix时才调用applyChannelNameStrip剥离US | CNN这类频道名中的国家前缀grid-list.component.ts/** Prefix stripping applies to channel grids only, never VOD/series. */ private readonly isLiveGrid computed(() [live, itv, radio].includes(this.type()) ); ... protected readonly channelTitle (item: GridListItem): string { const raw item.title ?? item.o_name ?? item.name ?? ; const stripped applyChannelNameStrip( raw, this.isLiveGrid() this.settingsStore.stripCountryPrefix?.() ); return stripped || No name; };从源码注释和测试grid-list.component.spec.ts可以确认前缀剥离只对直播网格生效VOD 标题即使形如US | Some Movie也保持原样。职责三选择海报/logo 展示行为usesArtworkPlaceholder()与postersOnly共同决定了海报区的展示策略private usesArtworkPlaceholder(): boolean { return this.variant() logo || this.type() live; }type live或variant logo时缺失封面渲染带图标占位stream-icon-placeholderpostersOnlySettings.showCoverTitles false的“纯海报墙”只对 VOD/Series 生效直播网格永远保留标题行——因为频道 logo 经常缺失或过于通用无法单凭 logo 识别频道grid-list.component.ts。此外showCatchupBadge()也依赖isLiveGrid()判定回看徽章只在直播网格出现grid-list.component.ts。所有这些行为都与“是否渲染类型徽章”正交因此type输入必须原样保留。受影响范围为什么一次改动同时覆盖 Xtream 与 Stalker设计文档“Affected Portals and Views”小节的结论是一处修改、多处受益。因为 Xtream 和 Stalker 的分类页都通过共享的门户目录视图portal catalog view路由最终汇入同一个GridListComponent。从源码调用链可以印证这一点共享目录视图 category-content-view.component.ts 的imports中直接引入并渲染GridListComponent它通过PORTAL_CATALOG_FACADE注入不同提供方的 facade 实现从而以同一套网格组件承载 Xtream 与 Stalker 的分类内容Xtream 侧live-stream-layout.component.ts 使用GridListComponent渲染直播/点播/剧集内容Stalker 侧stalker-itv-all-items.component.ts 同样消费该共享组件。因此本次改动实际覆盖的视图包括Xtream Live TV、VOD、Series 同质网格Stalker Live TV、VOD、Series 同质网格Xtream Live TV 全部条目网格All Items。而搜索、收藏、最近添加、仪表盘等混合内容表面因使用ContentCardComponent徽章行为完全不受影响。测试策略先写失败用例再删实现最后回归设计文档“Testing”小节要求更新GridListComponent聚焦测试证明live、vod、series三种类型下都不再渲染.type-badge同时type输入仍然驱动原有的标题与占位行为。新增的回归测试实现计划给出了具体的参数化回归测试三个类型共用同一断言见 grid-list.component.spec.tsit.each([live, vod, series] as const)( does not render a redundant %s type badge in homogeneous grids, (type) { fixture.componentRef.setInput(items, [ { name: Catalog item, stream_icon: catalog-item.png }, ]); fixture.componentRef.setInput(type, type); fixture.detectChanges(); expect( fixture.debugElement.query(By.css(.type-badge)) ).toBeNull(); } );同时原本断言徽章的 live-logo 测试被精简为只断言 logo 卡片渲染expect(card.nativeElement.classList).toContain(grid-card--logo)与expect(image.nativeElement.getAttribute(src)).toBe(channel-logo.png)不再查询.type-badge。RED → GREEN 工作流计划建议按 TDD 顺序执行先写入上述失败测试并运行确认 RED此时组件仍渲染.type-badge再删除模板标记与样式最后运行确认 GREEN。聚焦测试命令pnpm nx test portal-shared-ui --testPathPatterngrid-list.component.spec.ts --runInBand预期结果live、vod、series三个回归用例与既有占位/标题行为全部通过。受影响目标与边界验证聚焦用例通过后还需运行相邻的单元与 lint 目标pnpm nx test portal-shared-ui pnpm nx test portal-catalog-feature pnpm nx lint portal-shared-ui由于这是一次可见的门户工作流改动设计文档要求在有可用的 Playwright 覆盖时运行最接近的 Xtream 与 Stalker E2Epnpm nx run web-e2e:e2e-ci--src/xtream.e2e.ts pnpm nx run web-e2e:e2e-ci--src/stalker.e2e.ts若不可用则执行当前条件下最强的定向验证并记录跳过的 UI 自动化项。另外通过比对git diff -- libs/portal/shared/ui/src/lib/components/content-card libs/portal/xtream/feature/src/lib/search-results libs/portal/stalker/feature/src/lib/stalker-search输出为空可以确认混合内容徽章归属未被误伤。文档影响为什么不需要修改规范文档设计文档“Documentation Impact”小节给出的结论是除本设计记录外无需修改任何规范文档。理由有二规范的 UI 指南docs/architecture/iptvnator-ui-guidelines.md中关于“选择语言”Selection Pattern的小节本就明确写着“Do not add extra badges, left rails, or second selection systems unless there is a strong reason.”除非有充分理由不要添加额外徽章、左侧装饰条或第二套选择系统。本次改动恰好是向这条既定规范收敛而非引入新规则。本次改动不涉及任何路由、架构边界、安装配置流程或子系统契约的变化——它是一次纯展示层presentation的收敛所有组件输入/输出接口保持不变。总结GridListComponent类型徽章移除是一次典型的“去冗余、守边界”的 UI 收敛设计上严格区分“同质目录网格”与“混合内容卡片”两类表面前者只删徽章、保留type输入的全部中性职责后者ContentCardComponent连同搜索、收藏、最近添加、仪表盘等宿主一概不动实现上通过共享目录视图一处修改同时覆盖 Xtream 与 Stalker 的直播/点播/剧集网格验证上以参数化回归测试锁定.type-badge不再出现并辅以相邻单元测试、lint 与最近的 Playwright E2E 工作流。整套改动从设计、实现到测试层层闭环可作为理解 IPTVnator 门户共享组件职责划分与 UI 规范落地的典型案例。【免费下载链接】iptvnator:tv: Cross-platform IPTV player application with multiple features, such as support of m3u and m3u8 playlists, favorites, TV guide, TV archive/catchup and more.项目地址: https://gitcode.com/GitHub_Trending/ip/iptvnator创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门