From e53af934093e770f63398a80fcb72453450a0606 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 6 Sep 2026 13:38:25 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=94=B6=E8=97=8F=E9=A1=B5?= =?UTF-8?q?=E5=A4=9A=E9=80=89=E6=A8=A1=E5=BC=8F=E4=B8=8B=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E4=B8=A2=E5=A4=B1=E3=80=81=E8=B7=A8tab?= =?UTF-8?q?=E9=80=89=E6=8B=A9=E9=9D=99=E9=BB=98=E7=B4=AF=E5=8A=A0=E4=B8=A4?= =?UTF-8?q?=E4=B8=AA=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因1:'favorites-select' 是全部类型 tab 共用的同一个路由,本身不带类型信息,Favorites 组件原来进入多选模式时把 type 硬编码回退成 'file',不管进入前实际停在哪个 tab。实测在 "文本"tab 点"多选",列表和头部计数会静默换成"文件"tab 的数据,用户看不出发生了什么, 勾选/删除会作用在自己根本没看到的文件项上——测试过程中因此真的误删了一条文件收藏。 修复:进入多选前把当前 type 作为 hash 参数带上,多选页/分享页的返回箭头、"取消"、发送后 跳转都改用该参数换算的 tab,不再硬编码 'favorites-files'。 根因2:切换类型 tab 只更新 type,没有清空 selected——在"文件"tab 选中项目后切到"图片"tab, 头部仍显示旧的"已选择 N 项",实际操作的是已经不在当前列表里的旧类型收藏,删除/转发没有任何 可见提示。修复:切 tab 时一并清空 selected。 验证:真实浏览器逐步复现两个问题后确认修复生效——在"文本"tab进入多选保留文本列表、 切"图片"tab选择清零、"取消"正确回到多选前所在的图片tab;多选删除功能本身回归正常。 --- css/base.css | 11 +++++++++ src/views/content-library-view.jsx | 36 +++++++++++++++++++++++------- 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/css/base.css b/css/base.css index 3c188cad..2e58493f 100644 --- a/css/base.css +++ b/css/base.css @@ -4647,6 +4647,17 @@ video { user-select: none; } +/* 群系统事件(成员加入/角色变更/公告发布等),docs/images/内容沟通对话3-开启进群验证与拉人状态.png + 显示为不带背景的纯居中灰字,跟需要背景色块区分"这是一条独立提示"的 date/deleted 两种 .meta + 变体不一样——公告/进群这类事件本身已经在句子里说明了是系统提示,不需要额外的气泡背景。 */ +.meta .bubble.system { + max-width: 90%; + padding: 0.3rem 0.5rem; + background-color: transparent; + font-size: 0.8rem; + text-align: center; +} + /* Left triangle placed bottom left flush. */ .left .bubble.tip::before { content: ''; diff --git a/src/views/content-library-view.jsx b/src/views/content-library-view.jsx index 835ca80f..a020c34a 100644 --- a/src/views/content-library-view.jsx +++ b/src/views/content-library-view.jsx @@ -266,10 +266,17 @@ function FavoriteItem({item, onOpen, selecting, selected, onSelect, query, onToa const TYPE_ROUTE = {all: 'favorites-mixed', file: 'favorites-files', text: 'favorites-text', voice: 'favorites-voice', link: 'favorites-links', image: 'favorites-image', video: 'favorites-video'}; const TYPE_LABELS = [['all', '全部'], ['image', '图片'], ['video', '视频'], ['file', '文件'], ['voice', '语音'], ['text', '文本'], ['link', '链接']]; -function Favorites({view, tinode, onToast}) { +function Favorites({view, hashParams, tinode, onToast}) { const initialType = view === 'favorites-files' ? 'file' : view === 'favorites-text' ? 'text' : view === 'favorites-voice' ? 'voice' : view === 'favorites-links' ? 'link' : view === 'favorites-image' ? 'image' : view === 'favorites-video' ? 'video' : 'all'; const selecting = view === 'favorites-select'; - const [type, setType] = React.useState(selecting ? 'file' : initialType); + // 'favorites-select' 是所有类型 tab 共用的同一个路由,本身不带任何类型信息——原来不管进入 + // 多选前停在哪个 tab,一律硬编码回退成 'file'。实测复现:在"文本"tab 点"多选",列表和头部 + // 的"已选择 N 项"计数都静默换成了"文件"tab 的数据(tab 高亮也跟着跳到"文件"),用户在视觉上 + // 完全看不出发生了什么,勾选/删除会作用在自己压根没看到、以为还是文本收藏的文件项上——测试 + // 过程中真的因为这个把一条本不该删的文件收藏删掉了。现在"多选"按钮把当前 type 作为 hash 参数 + // 带过去,这里读回来,保留进入多选前用户实际所在的 tab;只有直接深链到 'favorites-select' + // 且没带 type 参数时才落回原来的 'file' 默认值。 + const [type, setType] = React.useState(selecting ? ((hashParams && hashParams.type) || 'file') : initialType); // 输入值与实际发请求用的值分开:原来 query 直接进 load 的依赖数组,输入 6 个字的关键词就打 // 6 次接口,而且返回顺序没有保证——后发的短前缀请求可能后到、把正确结果覆盖掉。 const [queryInput, setQueryInput] = React.useState(''); @@ -359,11 +366,19 @@ function Favorites({view, tinode, onToast}) { }; const list = items || []; return
-
navigate(selecting ? 'favorites-files' : 'favorites-select')} /> + {/* "返回"/"取消"都要回到多选前那个类型 tab,而不是硬编码的"文件"——TYPE_ROUTE 查不到时 + (比如 type 还是初始的 'all') 才退回 'favorites-files',跟原来的兜底保持一致。 */} +
navigate(selecting ? (TYPE_ROUTE[type] || 'favorites-files') : 'favorites-select', selecting ? undefined : {type})} /> + // 多选模式下切 tab 之前,selected 存的是"收藏 id 的集合",不带类型信息——原来只切 type、 + // 不清 selected,导致在"文件"tab 选中 2 项后切到"图片"tab,头部仍显示"已选择 2 项"、点 + // 删除/转发会真的作用在两个已经从当前列表消失、用户此刻根本看不到也无法勾选/取消的文件上, + // 且没有任何提示告诉用户这两项还算在内。多选场景下天然只该管"当前这个列表里勾了什么", + // 跨 tab 静默累加选择集不是这里的预期行为(对照参考图"收藏—文件(多选)"也只画了单一 + // 类型列表内的勾选,没有跨 tab 累加的设计)。 + onClick={() => { setType(id); setSelected([]); if (TYPE_ROUTE[id] && !selecting) navigateReplace(TYPE_ROUTE[id]); }}>{label})}
{items === null ?

加载中…

: list.length ? <>{list.map(item => 0 && forTarget.every(r => r.status === 'sent'); }).length; onToast(successTargets === selected.length ? `已分享给 ${selected.length} 个会话` : `${successTargets}/${selected.length} 个会话分享成功`); - window.setTimeout(() => navigate('favorites-files'), 700); + // 发完之后回到分享前那个类型 tab,而不是硬编码的"文件"——preview 是这批收藏里第一条的详情, + // 拿它的 type 就够找回对应 tab;preview 还没加载完时退回原来的 'favorites-files' 兜底。 + window.setTimeout(() => navigate(TYPE_ROUTE[preview && preview.type] || 'favorites-files'), 700); }).catch(err => onToast(err.message || '分享失败')).finally(() => setSending(false)); }; const previewAtt = preview && firstAttachment(preview.snapshot && preview.snapshot.content); @@ -418,7 +435,10 @@ function FavoriteShare({hashParams, myUserId, chatList, onToast}) { (!query || topicDisplayName(c.name, c.public, c.name || '').toLowerCase().includes(query.toLowerCase()))); const nameOf = uid => { const t = contacts.find(c => c.name === uid); return (t && topicDisplayName(t.name, t.public, uid)) || uid; }; return
-
+ {/* 同上一条注释——"favorites-select" 不带类型信息,点这里的返回箭头原来会静默把多选列表 + 换成硬编码的"文件"tab。preview.type 是这批收藏第一条的真实类型,带回去能让返回箭头落回 + 分享前实际所在的 tab。 */} +
{!confirming ? <>

最近聊天

@@ -718,7 +738,7 @@ function History({view, hashParams, myUserId, onToast}) { export default function ContentLibraryView({view, hashParams, tinode, myUserId, onTopicSelected, chatList}) { const [toast, setToast] = React.useState(''); let content; - if (view.startsWith('favorites')) content = ; + if (view.startsWith('favorites')) content = ; else if (view === 'favorite-share') content = ; else if (view.startsWith('file-download')) content = ; else content = ;