Your Name and Claude Opus 5
02b98cceae
修复全页面走查发现的问题(第二批:登录、通讯录、群聊)
...
第1章
- tinode-web: 手输密码登录失败会 navigateTo('') 把用户弹回企业码页,刚输的账号丢了,而
TenantEntry 不渲染 FormAlert,那句错误提示根本看不到。改成只有存储的 token 失效才回登录入口。
- auth-onboarding IdentityCheck: 限流 429 时服务端会连同未过期的 challenge_id 一起返回,
原来只显示错误文案、challengeId 留空,于是 submit 开头的守卫静默吞掉点击——输完验证码点
"确定"毫无反应也无提示。同文件 VerificationButton 早就处理对了,这里是漏抄。
- auth-onboarding Register: 手机号注册路径硬传 invite_code:'',把用户填的邀请码丢了。后端
user.go:175-181 对邀请码的校验和 RecordUse 不区分注册路径,UI 上也摆着这个输入框。
第5章
- 好友列表主副行显示同一串字:后端在有备注时把 display_name 也设成备注(im_http.go:8500-8507),
两个字段同值。加"不同才显示"的守卫。
- 拉黑确认弹窗把设置页当背景渲染并摆出"操作之后"的样子,但背景组件自己的 getUserProfile
回来后又把开关改回未拉黑、"删除好友"红条重新冒出来。加 pinBlocked 挡住这次覆盖。
第6章
- 群列表把群名显示成 topic id、成员数恒为 0。根因在后端:handler 用 store.Users.GetSubs,而
store 自己的注释就写着它 "Does not load Public/Trusted or Private"(store.go:834-835),
groupListItemPayload 却去读 sub.GetPublic()/GetSubCnt()(应该用 GetTopics)。已记为后端问题;
前端先用本地 Tinode 会话缓存兜底(消息首页一直这么取,是准的)。
- 禁言页每行头像画成群组图标(Avatar 兜底图标默认 'group',没传 icon="person"),
且顺带从成员表带上真实头像。
- 禁言页"以上成员不允许发言"被当成空状态用,语义正好反了——有禁言成员时这句消失、
一个都没有时反而显示。改为列表下方常驻注脚,空态另给文案,并补 .group-inline-note 样式。
- bytesToGB 只输出到 MB,1.4GB 的文件显示成 "1433.6 MB"。
- 群文件"来自"直接显示裸 uploader_id(groupFilePayload 不给昵称),拉成员表交叉引用。
- 群公告从聊天页横幅进入后返回,会把会话一起关掉:navigate 只写 query 参数,path[1] 仍为空,
handleHashRoute 就把 topicSelected 清成 null。Header 支持 onBack,显式把 topic 写回 path[1]。
- 群成员点头像打不开非好友资料页:目标页先读 'profile-seed:' 缓存,因为 getUserProfile 对
非好友直接 403。第5章入口一直有 seed,这里漏了。
- 群简介上限 225 超过后端硬限 200(im_http.go:4667),写满必被打回。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-09-03 18:40:53 +08:00
Your Name and Claude Opus 5
5a07bb4e3b
修复全页面走查发现的 P0 前端问题(第一批)
...
八个 agent 对 11 章逐页对照设计稿+后端源码后,先修其中"功能不可用/崩溃/谎报成功"级别的:
崩溃与数据错误
- content-library-view: Highlight 按 [start,len] 数组解构后端返回的 {start,end} 对象,
对象不可迭代会直接抛 TypeError,任何文本搜索命中都让整个结果区渲染崩掉。服务端偏移还叠加
两个问题(Go 字节下标 vs JS UTF-16;偏移基准是全文但 snippet 会被开窗截断),改为在展示
文本上本地匹配关键词。
- content-library-view: firstAttachment 用 Drafty.attachments,SDK 里硬过滤 tp=='EX'
只认文件附件,图片(IM)/视频(VD)/语音(AU) 一个都取不到——收藏缩略图、语音播放源、聊天记录
图片视频宫格全部拿不到资源。改用 Drafty.entities 按类型分派(chat-message.jsx 已有先例)。
- message-center-view: 系统通知的机器码兜底会把真实数据吞掉(日报提醒的 summary 就是日期
字符串 "2026-08-20",会议通知的 summary 是标题),改为查表命中才替换。
- message-center-view: 会话列表漏了 avatar 字段,每行都只能落到兜底图标;同文件
frequentContacts() 本来就是对的,照它补上。
功能不可用
- auth-onboarding-view: 首次开启青少年模式是死路——设完密码丢弃了服务端返回的
enable_action_token,从不调 enableYouthMode,用户走完短信验证+设密码后模式仍是关的。
现在拿着这个 token 把最后一步做完。
- group-management-view: "投诉/举报"是个 onToast('暂未开放') 死桩,而 target_type='group'
这条链路早就通了。接上真实举报页。
- tinode-web: 刷新/深链会被弹回首页。两个原因叠加:初始化白名单还是上游 Tinode 的
['cred','reset','register'];handleLoginSuccessful 无条件把 hash 改写成 workbench,
刷新触发的自动登录也走这条。抽出 SIDE_PANEL_VIEWS 常量复用,并区分登录流程与自动登录。
- widgets/meta-message: deleted 分支从未实现,撤回一条消息后时间线上什么都不剩。
谎报成功 / 判定错误
- tinode-web + personal-settings-view: 改密码不返回 Promise,服务端拒绝时照样弹"密码已更新"。
- group-management-view: 禁言批量读 result.succeeded,但该接口返回的是 {topic, items},
succeeded 恒为 undefined,不管成没成都弹"设置成功"。两个接口结构不同,分开判定。
- workplace-collaboration-view: 会议取消状态写成 'cancelled',后端是 'canceled' 单 l,
会议取消后"取消会议"按钮还挂着。
样式与显示
- base.css: 删掉旧版 .organization-department 的 padding-left !important,它压过按层级算出的
内联缩进,导致部门行全平、只有人员行缩进。
- base.css: 补 .youth-password-gate(原来 0 条规则),PIN 框缺 position:relative 和居中。
- security-support-view: shield_lock 不在经典 Material Icons 里(只有 Symbols),会显示成
字面文本;.risk-info-page 也是 0 条规则,整页渲染成裸项目符号列表。改用 verified_user 并
补上 .risk-dialog。
- contact-management-view: 好友资料页性别直接输出后端枚举,显示成 "male"。
- workplace-collaboration-view: 层级标注两条路径两种格式(树形深三层变"3级"、搜索硬传"三"),
统一成一个 helper。
已记录不在前端修的后端缺口:recallMessage 的 version 只能传 1,因为所有消息读取接口
(messagePayload/messageSearchPayload/mediaMessagePayload/favoriteSnapshot)都不下发 version,
冲突错误里也不回传真实值,被编辑过的消息撤回必然失败。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-09-03 18:31:26 +08:00
Your Name and Claude Opus 5
c4189646f4
消息首页:群聊头像图标、昨天的时间格式、常联系的人名字截断
...
对照 docs/images/消息.png 逐项核对消息首页,实测 DOM 后确认三处:
1. 群聊会话的兜底头像画成了单人像:normalizeConversations 没给任何会话设 icon,全部落到
Avatar 的默认值 person,列表里分不出哪条是群。按 topic 的 grp 前缀区分,群用 group 图标。
顺带把群的 online 传 undefined——群不存在"在线"概念,之前会给群也渲染一个状态点。
2. 昨天的会话只显示"昨天",参考图是"昨天21:03"带具体时间。实测修复后显示"昨天17:40"。
3. "常联系的人"的名字被截断:格子 3.75rem(50px),而 "kcg051307" 这类用户名需要 52px,
显示成 "kcg0513...";参考图里这一栏名字是完整显示的。加宽到 4.4rem,实测 59px 可见宽、
59px 实际宽,不再截断。
另外记录一个未改的观感偏差供决策:这一栏的头像实测占视口宽 10.1%(42.7px / 424px),参考图
里约占 17%,明显小一号。放大属于观感调整不是缺陷修复,没有自行改动。
本轮还做了一次全局层叠扫描(遍历 19 个页面,自动检测图标在容器内不居中、文字被压成 0 高度、
元素溢出视口、意外截断四类问题):除上面这处截断外没有新命中,说明之前群设置页那组 CSS 层叠
冲突是孤立的,没有蔓延到其他页面。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-09-03 18:09:00 +08:00
Your Name and Claude Opus 5
0ba3577c96
群头像图标贴顶不居中;成员格子文字区过窄
...
用户实机反馈的三点,逐项查证后:
1. 图标垂直不居中(真bug,已修):.group-settings-header span 这条规则把 .group-avatar 一起
命中了——它本身就是个 span,被改成 flex-direction:column 之后,自己的 place-items:center
只剩交叉轴(水平)生效,主轴(垂直)退回 flex-start,图标贴着方块顶部。实测头部群头像上边距
0px、下边距 28.7px,左右各 14.3px,正好对应这个成因。选择器改为
> span:not(.group-avatar) 精确排除;同时给 .group-avatar 补 align-content/justify-content,
以后再被外部规则改成 flex 也不会散架。修完三处(头部群头像、成员头像、添加格)实测上下左右
边距全部对称。
2. 文字区过窄只显示两个字(真问题,已修):上一版把成员格子宽度收到与头像等宽(3rem),昵称
被截成"测试..."。按参考图比例重算——那张图里头像约占格子宽七成、相邻头像间隙约头像宽四成,
且五字昵称完整显示——格子改 4.4rem、头像改 3.6rem、间距 0.5rem。实测"测试昵称A"完整显示
不再截断。
3. 头像配色:上一版我把兜底头像从饱和蓝底白图标改成了浅蓝底蓝图标,这是自作主张、用户没要求,
已还原成原来的 #4389df 底 + 白色图标。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-09-03 17:54:22 +08:00
Your Name and Claude Opus 5
f7bc98811e
群聊设置:重做成员预览区,修掉错位间距、多余横线和被压扁的名字
...
用户实机截图反馈这块"图标和间距有问题"。对照 docs/images/群聊设置.png 逐项查证,实际有四个独立
缺陷叠在一起:
1. 多余横线:成员容器 div 和邀请按钮都是 section 的直接子元素,命中了通用列表项样式
(.group-settings section > button/div 带 border-bottom + min-height + padding),
于是这一块被当成两个普通设置行渲染,凭空多出两截下划线。
2. 间距错位:原来是 flex 布局,成员列表 flex:1 占满剩余宽度,把邀请按钮一路挤到最右,两者之间
出现一大片空白;参考图是等宽网格。
3. 名字看不见:全局 button 规则(base.css:1999)写死 height/line-height 2.2rem,成员格子没有
覆盖它,整个格子被压到 29px 高——48px 的头像直接溢出,名字被压成 0 高度,实测
getBoundingClientRect().height 为 0。
4. 图标撞车:成员头像的兜底图标沿用了 Avatar 的默认值 group(双人图标),跟上方群头像长得一模
一样,分不清哪个是群哪个是人;改传 icon="person"。
改成参考图的结构:一行"群成员"标题(右侧显示人数)+ 5 列等宽网格,最后一格是与头像同尺寸、
同圆角的浅色"添加"块。新样式用 .group-settings section > .group-member-* 提高特异性,明确压过
那套列表项规则,并显式写 height:auto 覆盖全局 button 高度。
刻意没做的两点,都是因为本分支没有对应页面,不想做点了没反应或跳错地方的入口:参考图里"查看
15465群成员"那个可点链接(没有通用群成员列表页,这里只展示人数文字),以及"删除"格(没有移除
成员的页面)。这两个缺口需要单独补页面,不在这次范围内。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-09-03 17:43:22 +08:00
Your Name and Claude Opus 5
8225848493
系统消息:按通知自身内容决定入口和文案,不再一律显示"前往安全设置"
...
用户实机测试反馈:系统消息列表里每条通知底部都是同一个"前往安全设置"按钮,点进去跟通知内容毫不
相关;正文还直接显示 "group.settings.updated" 这种原始事件码。查证后两个问题性质不同:
入口按钮(前端问题,已修):原来无条件对所有通知渲染同一个按钮、固定跳 security 页。改为按通知
自己的 action 字段决定——action.topic 是 grp 开头的进对应群聊设置页,好友申请类(action.type
为 friend_request)进"新朋友"页,带 device/ip 的安全类才进安全设置页,都不匹配就不显示按钮。
注意 action.topic 不能直接当群用:好友申请通知的 action 里带的是 p2p 会话 topic
(db/mysql/tenant_adapter.go:8643),所以判断加了 grp 前缀检查。跳转目标都核对过在
tinode-web.jsx 的路由白名单里(friend-requests / group-settings),没有凭空造路由名。
正文文案(后端问题,前端只做兜底):后端多处把机器码直接当 summary 写进通知——群事件统一写
summary=event.EventType(im_group_events.go:42-44,7 种群事件还共用同一个 title"群聊动态"),
好友申请处理结果写 summary=status(im_http.go:5956 等,值就是 "accepted"/"rejected")。前端加
了一层兜底:summary 命中"纯小写字母数字点下划线"这种机器码特征时,按已知码翻译成中文,翻译不了
就退回通用文案;后端以后补上真正的文案会自动优先使用,不会被兜底覆盖。这条已记入后端问题清单。
实机验证:两条群通知正文由 "group.settings.updated" 变为"群设置有更新"、按钮变为"查看群聊"且
点击后正确进入 grpXDkK5cbXoK0 的群聊设置页;两条好友通知正文由 "accepted" 变为"对方已通过你的
好友申请",不再显示无关的安全设置按钮。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-09-03 17:32:36 +08:00
Your Name and Claude Opus 5
3bdb0bf40f
群昵称改用专门的接口读取,修好读不回已保存值的问题
...
上一个commit修好了"群资料"页把群名称当成个人群昵称显示的问题,但实机验证发现改完仍然显示"未设置"。
抓包确认根因:GET /groups/{topic}/members 列表接口的每一项里压根没有 group_nickname 字段(只有
acs/display_name/mentionable/role/user_id),所以任何从成员列表里读昵称的写法,不管代码逻辑对不对,
都永远拿不到值——这个文件里原有的 MyNicknameEditor 也是同样的写法,同样存在这个问题(打开编辑器时
不会回填已保存的昵称)。
真正能读到昵称的是保存用的那个路径上对应的 GET:GET /groups/{topic}/members/me/profile,返回
{nickname, version, updated_at}(server/im_http.go:4776-4782)。im-api.js 里之前只封装了 PUT,
补上了对应的 getMyGroupProfile,两处读取(群资料页预览行、昵称编辑器回填)都改成用它。
实机验证:保存"测试昵称A"后重新打开群资料页,"群昵称"正确显示"测试昵称A","群名称"独立显示
"扫码测试群"。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-09-03 17:20:36 +08:00
Your Name and Claude Sonnet 5
e4c6e1b246
Fix group-profile nickname preview showing group name instead of my own nickname
...
GroupProfile's "群昵称" preview row showed group.name -- the group's own display name -- instead
of the current user's personal nickname within that group (a real, distinct concept, correctly
handled by the existing MyNicknameEditor/group-my-nickname page, just not wired into this preview
row). Ported the substance of a bug dev independently found and fixed in their own reimplementation
of this same page ("show saved group nickname", found while evaluating what from dev's post-fork
commits was worth bringing over). Reuses the same getGroupMembers+filter-by-myUserId approach
MyNicknameEditor already uses in this file (there's no working "me" shortcut on the
member-profile-by-id endpoint that would let this be fetched more directly -- confirmed by reading
server/im_http.go's routing, which never special-cases that literal string).
Also renamed the adjacent "群昵称"->"群名称" label for the group's own display name field, since
having two rows both labeled "群昵称" (one for my personal nickname, one for the group's name) is
exactly the confusion that caused this bug in the first place.
Evaluated the rest of dev's post-fork commits (9 commits fixing this same page's nickname-save
reliability, plus the wholesale chapter-view reimplementation) for anything else worth porting:
the version-conflict retry logic they built doesn't apply here since this branch already sends
version:0 (confirmed server/im_http.go:4793 treats <=0 as "skip the check" -- the exact mechanism
their fix was working around a different way), and their nickname maxLength bump (11->20) is
already exceeded by this branch's existing 32, which matches the real backend limit
(server/im_http.go:4789). Nothing else from dev's branch was found applicable.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com >
2026-09-03 17:08:38 +08:00
Your Name and Claude Sonnet 5
2c77a8e229
Ignore local .claude/ dev-server config
...
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com >
2026-09-03 17:01:13 +08:00
Your Name and Claude Sonnet 5
251c9de87c
Convert im_webapp from static mock prototypes to real backend integration
...
Implements all 11 product chapters (auth, messaging, contacts, groups,
files/favorites, calls, workplace/reports, settings, security) against the
real /v1/im REST API and native Tinode WS protocol, replacing the hardcoded
mock data the ba8f48ee prototype commit shipped with. Adds src/lib/im-api.js
as the REST client, plus supporting fixes across messages-view.jsx and the
attachment/upload/download pipeline (wrong SDK auth headers, group topic
naming, seq/timezone edge cases) found via live end-to-end testing against
the real backend.
Backup checkpoint before reconciling with origin/dev's parallel rewrite.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com >
2026-09-03 11:40:53 +08:00
Your Name
ca5e74ee98
修复静态资源发布后不生效: /umd/缓存策略从immutable改为no-cache
...
构建产物文件名不带内容哈希,一年免验证的缓存策略导致每次蓝绿发布后
浏览器和CDN都会继续吃旧版本,用户需要清缓存或开无痕窗口才能看到更新。
改为no-cache后浏览器/CDN每次都会带条件请求向源站确认,未变化时只是
一次很快的304,一旦文件真的变了会立刻拿到新内容,不再需要手动清缓存。
2026-08-12 12:54:41 +08:00
Your Name
111d9040a7
修复健康检查失败: nginx补上IPv6监听
...
首次部署时健康检查一直失败——容器内nginx只listen了IPv4(0.0.0.0:80),
但/etc/hosts里localhost解析到::1在前,wget http://localhost/因而连不上 。
补上 listen [::]:80 双栈监听解决。部署脚本那边也同步改成直连127.0.0.1,
避免再依赖localhost的解析顺序。
2026-08-11 12:52:06 +08:00
Your Name
85ac8ce43b
接入Gitea Actions蓝绿发布:API_KEY构建时注入、新增Dockerfile
...
- src/config.js 的 API_KEY 改为从构建时环境变量 TINODE_API_KEY 注入,
不再依赖官方demo默认值;未设置时保留原demo key作为本地快速测试的兜底
- webpack.config.js 新增 DefinePlugin 完成注入,并自动加载(gitignored的)
.env.local,开发者本地调试不需要每次手动export
- 新增 Dockerfile(node构建+nginx serve) 和 docker/nginx.conf
- 新增 .gitea/workflows/deploy.yml:手动触发的蓝绿发布流程
2026-08-11 12:40:12 +08:00