From e851c6e9d3a644e8236b45c2a3cca70652f84acb Mon Sep 17 00:00:00 2001 From: ZhangTingan Date: Wed, 10 Jun 2026 10:13:38 +0800 Subject: [PATCH] fix: ensure video items always appear at top of search results MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, .videoItems relied on position:absolute + a 50ms setTimeout margin hack to stay at the top of search results. This caused a race condition when multiple Items components loaded asynchronously — the margin could be applied to the wrong element depending on file I/O completion order across different machines. Fix by separating video-guide results in the render method so they always come first in the DOM, and removing position:absolute from .videoItems to let it flow naturally. This eliminates both the timing-dependent hack and the fragile className-based DOM query. Bug: https://pms.uniontech.com/bug-view-363963.html --- src/web/toManual/js/search.jsx | 37 ++++++++++++++++--------------- src/web/toManual/sass/search.scss | 2 -- src/web_dist/toManual/index.css | 4 +--- src/web_dist/toManual/index.js | 30 ++++++++++++------------- 4 files changed, 35 insertions(+), 38 deletions(-) diff --git a/src/web/toManual/js/search.jsx b/src/web/toManual/js/search.jsx index 213230ff3..d3e7526a2 100755 --- a/src/web/toManual/js/search.jsx +++ b/src/web/toManual/js/search.jsx @@ -1,8 +1,8 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2022-2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: GPL-3.0-or-later -import React, { Component, useEffect, useRef } from 'react'; +import React, { Component, useRef } from 'react'; import ReactDOM from 'react-dom'; import PropTypes from 'prop-types'; import Scrollbar from './scrollbar.jsx'; @@ -201,17 +201,6 @@ function VideoItems(props) { } } - useEffect(() => { - const adjustOtherElements = () => { - const componentHeight = videoItemsRef.current.offsetHeight + 20; - setTimeout(function () { - document.getElementsByClassName("items")[0].style.marginTop = `${componentHeight}px`; - }, 50); - }; - - adjustOtherElements(); // 调整其他元素的位置 - }, []); - function handleHover() { console.log("hover....current:", videoItemsRef.current, " ", videoItemsRef.current.offsetHeight); } @@ -250,16 +239,28 @@ export default class SearchPage extends Component { if (this.context.mismatch) { c = ; } else { - c = this.context.searchResult.map(result => ( - result.file === "video-guide" ? { + if (result.file === "video-guide") { + videoResults.push(result); + } else { + otherResults.push(result); + } + }); + + c = videoResults.map(result => ( + - - : + )).concat(otherResults.map(result => ( + - )); + ))); } return ( diff --git a/src/web/toManual/sass/search.scss b/src/web/toManual/sass/search.scss index f8fd2298f..ca3749fd7 100644 --- a/src/web/toManual/sass/search.scss +++ b/src/web/toManual/sass/search.scss @@ -210,8 +210,6 @@ .videoItems { padding: 14px 20px 0px 0px; - position: absolute; - top: 0; #item { height: 34px; diff --git a/src/web_dist/toManual/index.css b/src/web_dist/toManual/index.css index ca4451e76..531c81688 100644 --- a/src/web_dist/toManual/index.css +++ b/src/web_dist/toManual/index.css @@ -742,9 +742,7 @@ body { #search .items .highlight { color: #2bba57; } #search .videoItems { - padding: 14px 20px 0px 0px; - position: absolute; - top: 0; } + padding: 14px 20px 0px 0px; } #search .videoItems #item { height: 34px; display: flex; diff --git a/src/web_dist/toManual/index.js b/src/web_dist/toManual/index.js index 9bee5feff..c5839e511 100644 --- a/src/web_dist/toManual/index.js +++ b/src/web_dist/toManual/index.js @@ -2850,17 +2850,6 @@ function VideoItems(props) { _loop3(i); } - (0, _react.useEffect)(function () { - var adjustOtherElements = function adjustOtherElements() { - var componentHeight = videoItemsRef.current.offsetHeight + 20; - setTimeout(function () { - document.getElementsByClassName("items")[0].style.marginTop = componentHeight + 'px'; - }, 50); - }; - - adjustOtherElements(); // 调整其他元素的位置 - }, []); - function handleHover() { console.log("hover....current:", videoItemsRef.current, " ", videoItemsRef.current.offsetHeight); } @@ -2910,14 +2899,25 @@ var SearchPage = function (_Component3) { if (this.context.mismatch) { c = _react2.default.createElement(Mismatch, { keyword: this.props.match.params.keyword }); } else { - c = this.context.searchResult.map(function (result) { - return result.file === "video-guide" ? _react2.default.createElement(VideoItems, { + var videoResults = []; + var otherResults = []; + this.context.searchResult.forEach(function (result) { + if (result.file === "video-guide") { + videoResults.push(result); + } else { + otherResults.push(result); + } + }); + c = videoResults.map(function (result) { + return _react2.default.createElement(VideoItems, { key: result.file, file: result.file, idList: result.idList, titleList: result.titleList, contentList: result.contentList, - keyword: _this6.props.match.params.keyword }) : _react2.default.createElement(Items, { + keyword: _this6.props.match.params.keyword }); + }).concat(otherResults.map(function (result) { + return _react2.default.createElement(Items, { key: result.file, file: result.file, idList: result.idList, @@ -2925,7 +2925,7 @@ var SearchPage = function (_Component3) { contentList: result.contentList, keyword: _this6.props.match.params.keyword }); - }); + })); } return _react2.default.createElement( _scrollbar2.default,