Fix tag management view entering search flow

This commit is contained in:
kuekhaoyang
2026-07-09 16:59:39 +08:00
parent 5a76958816
commit 2bb70ca648
9 changed files with 84 additions and 28 deletions
+7
View File
@@ -1,5 +1,12 @@
# Changelog
## 4.9.9 - 2026-07-09
- 修复首页管理标签入口混入快捷搜索流程的问题,打开管理模式后不再显示“内容分类”“电影类型”“年份”等搜索快捷项。
- 管理标签时隐藏电影/电视剧切换和推荐内容网格,让“完成 / 恢复默认 / 添加标签 / 标签列表”成为当前视图主体。
- 标签管理列表改为可换行 chip 布局,并在管理模式下使用矩形拖拽排序策略,避免标签区域被横向滚动行挤压。
- 新增标签管理视图回归测试,防止管理入口再次退化为搜索筛选界面。
## 4.9.8 - 2026-07-09
- 修复登录完成跳转后 Network 面板出现 `/api/user/config``/api/user/sync` 两个 400 请求的问题。
+12 -1
View File
@@ -4,8 +4,19 @@
"name": "KVideo",
"branch": "main"
},
"currentVersion": "4.9.8",
"currentVersion": "4.9.9",
"releases": [
{
"version": "4.9.9",
"publishedAt": "2026-07-09",
"title": "修复管理标签入口误入搜索流程",
"notes": [
"首页管理标签模式现在会隐藏内容分类、电影类型、年份等快捷搜索项,避免用户打开标签管理时触发视频源搜索。",
"管理标签时不再显示电影/电视剧切换和推荐内容网格,完成、恢复默认、添加标签和标签列表成为当前视图主体。",
"标签 chip 在管理模式下改为可换行布局,并使用矩形拖拽排序策略,减少上方筛选内容对标签操作区的挤压。",
"新增标签管理视图回归测试,锁定管理入口不应退化为搜索结果筛选界面。"
]
},
{
"version": "4.9.8",
"publishedAt": "2026-07-09",
+23 -20
View File
@@ -58,6 +58,7 @@ export function PopularFeatures({ onSearch }: PopularFeaturesProps) {
const [isRecommendSelected, setIsRecommendSelected] = useState(false);
const effectiveRecommendSelected = hasHistory && isRecommendSelected;
const isTagManagementMode = showTagManager;
const {
movies,
@@ -92,10 +93,10 @@ export function PopularFeatures({ onSearch }: PopularFeaturesProps) {
return (
<div className="animate-fade-in">
<CategoryQuickSearch onSearch={onSearch} />
{!isTagManagementMode && <CategoryQuickSearch onSearch={onSearch} />}
{/* Content Type Toggle (Capsule Liquid Glass - Fixed & Centered) */}
{!effectiveRecommendSelected && (
{!isTagManagementMode && !effectiveRecommendSelected && (
<div className="mb-10 flex justify-center">
<div className="relative w-80 p-1 bg-[var(--glass-bg)] border border-[var(--glass-border)] rounded-full grid grid-cols-2 backdrop-blur-2xl shadow-lg ring-1 ring-white/10 overflow-hidden">
{/* Sliding Indicator */}
@@ -146,24 +147,26 @@ export function PopularFeatures({ onSearch }: PopularFeaturesProps) {
} : undefined}
/>
{effectiveRecommendSelected ? (
<MovieGrid
movies={recommendMovies}
loading={recommendLoading}
hasMore={recommendHasMore}
onMovieClick={handleMovieClick}
prefetchRef={recommendPrefetchRef}
loadMoreRef={recommendLoadMoreRef}
/>
) : (
<MovieGrid
movies={movies}
loading={loading}
hasMore={hasMore}
onMovieClick={handleMovieClick}
prefetchRef={prefetchRef}
loadMoreRef={loadMoreRef}
/>
{!isTagManagementMode && (
effectiveRecommendSelected ? (
<MovieGrid
movies={recommendMovies}
loading={recommendLoading}
hasMore={recommendHasMore}
onMovieClick={handleMovieClick}
prefetchRef={recommendPrefetchRef}
loadMoreRef={recommendLoadMoreRef}
/>
) : (
<MovieGrid
movies={movies}
loading={loading}
hasMore={hasMore}
onMovieClick={handleMovieClick}
prefetchRef={prefetchRef}
loadMoreRef={loadMoreRef}
/>
)
)}
</div>
);
+2
View File
@@ -51,6 +51,7 @@ export function SortableTag({
>
<div className={`${showTagManager && !isDragging ? 'animate-jiggle' : ''}`}>
<button
type="button"
onClick={() => onTagSelect(tag.id)}
className={`
px-6 py-2.5 text-sm font-semibold transition-all whitespace-nowrap rounded-[var(--radius-full)] cursor-pointer select-none
@@ -64,6 +65,7 @@ export function SortableTag({
</button>
{showTagManager && (
<button
type="button"
onClick={(e) => {
e.stopPropagation();
onTagDelete(tag.id);
-2
View File
@@ -1,7 +1,5 @@
'use client';
import { Icons } from '@/components/ui/Icon';
interface TagInputProps {
newTagInput: string;
onNewTagInputChange: (value: string) => void;
+8 -2
View File
@@ -15,6 +15,7 @@ import {
SortableContext,
sortableKeyboardCoordinates,
horizontalListSortingStrategy,
rectSortingStrategy,
} from '@dnd-kit/sortable';
import { SortableTag, Tag } from './SortableTag';
import { useState, useRef, useEffect } from 'react';
@@ -115,12 +116,17 @@ export function TagList({
>
<div
ref={scrollContainerRef}
className="mb-8 flex items-center gap-3 overflow-x-auto pb-3 pt-2 px-1 scrollbar-hide"
className={`mb-8 flex items-center gap-3 pb-3 pt-2 px-1 scrollbar-hide ${
showTagManager
? 'flex-wrap overflow-visible'
: 'overflow-x-auto'
}`}
>
{/* Recommendation Tag — non-draggable, rendered before sortable tags */}
{recommendTag && (
<div className="relative flex-shrink-0">
<button
type="button"
onClick={recommendTag.onSelect}
className={`
px-6 py-2.5 text-sm font-semibold transition-all whitespace-nowrap rounded-[var(--radius-full)] cursor-pointer select-none flex items-center gap-1.5
@@ -137,7 +143,7 @@ export function TagList({
)}
<SortableContext
items={tags.map((t) => t.id)}
strategy={horizontalListSortingStrategy}
strategy={showTagManager ? rectSortingStrategy : horizontalListSortingStrategy}
>
{tags.map((tag) => (
<SortableTag
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "kvideo",
"version": "4.9.8",
"version": "4.9.9",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "kvideo",
"version": "4.9.8",
"version": "4.9.9",
"dependencies": {
"@dnd-kit/core": "^6.3.1",
"@dnd-kit/sortable": "^10.0.0",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "kvideo",
"version": "4.9.8",
"version": "4.9.9",
"private": true,
"scripts": {
"dev": "node scripts/next-with-lan-access.mjs dev",
+29
View File
@@ -0,0 +1,29 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
import { join } from 'node:path';
const projectRoot = process.cwd();
test('popular tag management mode stays out of quick search and discovery grids', () => {
const source = readFileSync(
join(projectRoot, 'components/home/PopularFeatures.tsx'),
'utf8',
);
assert.match(source, /const isTagManagementMode = showTagManager;/);
assert.match(source, /!\s*isTagManagementMode && <CategoryQuickSearch/);
assert.match(source, /!\s*isTagManagementMode && !effectiveRecommendSelected/);
assert.match(source, /!\s*isTagManagementMode && \(/);
});
test('tag management list uses wrapping chip layout instead of a horizontal search filter row', () => {
const source = readFileSync(
join(projectRoot, 'components/home/TagList.tsx'),
'utf8',
);
assert.match(source, /rectSortingStrategy/);
assert.match(source, /showTagManager\s*\?\s*'flex-wrap overflow-visible'/);
assert.match(source, /showTagManager \? rectSortingStrategy : horizontalListSortingStrategy/);
});