修复全页面走查发现的问题(第三批:转发、i18n、自聊天显示名)
第4章 批量转发
- 确认弹层里那栏留言是个只读 <div>,需求 4.19 与对接文档要求的"附加留言"根本没法填,
comment 永远是空串。改成真实输入框(方括号那段是占位文案不是内容),并补 input 的样式。
- 无条数上限:服务端硬卡 sources ≤ 100(im_http.go:3560),超了直接 400 MALFORMED_REQUEST,
用户只看到一句无从下手的"转发失败"。本地先拦并说清超了多少。
- 无目标数上限:bootstrap 下发 limits.max_forward_targets=9、服务端硬限 20,前端两个都不读。
读各视图已在写的同一份 bootstrap 缓存,不额外发请求;选择视图也补上错误显示。
i18n(这几条影响真实页面,不只是演示页)
- menu_item_forward "重定向" → "转发",forward_to "重定向消息" → "转发给"。Forward 被当网络
术语直译了,第4章通篇和参考图用的都是"转发"。
- last_seen_timestamp 中英两侧都丢了 {timestamp} 占位符,离线时头部只显示"最后可见"没有时间。
- peers_messaging_disabled "成员间消息已禁用" → "对方已关闭消息"(原文是 Peer's)。
- search_no_results "搜索返回任何结果" 缺"无";icon_title_send "发信息" → "发送消息"。
- 已跑 build:i18n 同步 src/i18n.min/(那份才是打包进产物的)。
自聊天显示名
- topicDisplayName 不处理 slf,消息首页把"已保存的消息"显示成"未命名会话"。该显示名靠
Tinode.isSelfTopicName 特判得出、不在 public 里。集中到这个共享函数,所有调用点都受益。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
02b98cceae
commit
c9b8125013
@@ -12,6 +12,11 @@ import SearchContacts from './search-contacts.jsx';
|
||||
|
||||
import { forwardMessages } from '../lib/im-api.js';
|
||||
import { topicDisplayName } from '../lib/utils.js';
|
||||
import { readCachedData } from '../lib/use-cached-data.js';
|
||||
|
||||
// 与服务端 im_http.go:3560 的硬限一致。目标数另有一层更严的产品限制,见 maxTargets()。
|
||||
const MAX_FORWARD_SOURCES = 100;
|
||||
const MAX_FORWARD_TARGETS = 20;
|
||||
|
||||
export default class BatchForwardDialog extends React.Component {
|
||||
constructor(props) {
|
||||
@@ -22,6 +27,7 @@ export default class BatchForwardDialog extends React.Component {
|
||||
multiSelect: false,
|
||||
selectedTargets: [],
|
||||
confirmTargets: null,
|
||||
comment: '',
|
||||
sending: false,
|
||||
error: null
|
||||
};
|
||||
@@ -34,6 +40,7 @@ export default class BatchForwardDialog extends React.Component {
|
||||
this.handleConfirmTargets = this.handleConfirmTargets.bind(this);
|
||||
this.handleCancelConfirm = this.handleCancelConfirm.bind(this);
|
||||
this.handleSend = this.handleSend.bind(this);
|
||||
this.handleCommentChange = this.handleCommentChange.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@@ -73,10 +80,25 @@ export default class BatchForwardDialog extends React.Component {
|
||||
this.setState({confirmTargets: [uid]});
|
||||
return;
|
||||
}
|
||||
this.setState(s => ({
|
||||
selectedTargets: s.selectedTargets.includes(uid) ?
|
||||
s.selectedTargets.filter(t => t != uid) : s.selectedTargets.concat(uid)
|
||||
}));
|
||||
this.setState(s => {
|
||||
if (s.selectedTargets.includes(uid)) {
|
||||
return {selectedTargets: s.selectedTargets.filter(t => t != uid), error: null};
|
||||
}
|
||||
// 目标数上限:优先用 bootstrap 下发的 limits.max_forward_targets(服务端当前给 9),
|
||||
// 拿不到就退到服务端硬限 20(im_http.go:3560)。原来两个都不读,选到 21 个才会撞 400。
|
||||
const max = this.forwardTargetLimit();
|
||||
if (s.selectedTargets.length >= max) {
|
||||
return {error: `最多同时转发给 ${max} 个会话`};
|
||||
}
|
||||
return {selectedTargets: s.selectedTargets.concat(uid), error: null};
|
||||
});
|
||||
}
|
||||
|
||||
forwardTargetLimit() {
|
||||
// 读各视图已经在写的同一份 bootstrap 缓存('bootstrap:'+myUserId),不额外发请求。
|
||||
const boot = this.props.myUserId ? readCachedData('bootstrap:' + this.props.myUserId) : null;
|
||||
const configured = boot && boot.limits && Number(boot.limits.max_forward_targets);
|
||||
return configured > 0 ? Math.min(configured, MAX_FORWARD_TARGETS) : MAX_FORWARD_TARGETS;
|
||||
}
|
||||
|
||||
handleConfirmTargets(e) {
|
||||
@@ -90,11 +112,21 @@ export default class BatchForwardDialog extends React.Component {
|
||||
this.setState({confirmTargets: null, error: null});
|
||||
}
|
||||
|
||||
handleCommentChange(e) {
|
||||
this.setState({comment: e.target.value});
|
||||
}
|
||||
|
||||
handleSend() {
|
||||
// seq must be a JSON string (server struct tag is `json:"seq,string"`), same as favoriteMessages.
|
||||
const sources = this.props.seqs.map(seq => ({topic: this.props.topicName, seq: String(seq)}));
|
||||
// 服务端硬卡 sources ≤ 100、target_topics ≤ 20(im_http.go:3560),超了直接 400 MALFORMED_REQUEST,
|
||||
// 用户只会看到一句无从下手的"转发失败"。在本地先拦住并说清楚超了多少。
|
||||
if (sources.length > MAX_FORWARD_SOURCES) {
|
||||
this.setState({error: `一次最多转发 ${MAX_FORWARD_SOURCES} 条消息,当前已选 ${sources.length} 条`});
|
||||
return;
|
||||
}
|
||||
this.setState({sending: true, error: null});
|
||||
forwardMessages('separate', sources, this.state.confirmTargets).then(result => {
|
||||
forwardMessages('separate', sources, this.state.confirmTargets, this.state.comment.trim()).then(result => {
|
||||
const failed = (result && result.failed) || [];
|
||||
if (failed.length) {
|
||||
this.setState({sending: false, error: `${failed.length} 条转发失败,请重试`});
|
||||
@@ -119,7 +151,11 @@ export default class BatchForwardDialog extends React.Component {
|
||||
<i className="material-icons">chevron_right</i>
|
||||
</li>)}
|
||||
</ul>
|
||||
<div className="batch-forward-comment">{'[逐条转发]共' + this.props.seqs.length + '条消息'}</div>
|
||||
{/* 参考图这一栏是可输入的留言框,原来是个只读 <div>,需求 4.19 与对接文档要求的
|
||||
"附加留言"根本没法填,comment 永远是空串。方括号那段是占位文案,不是内容。 */}
|
||||
<input className="batch-forward-comment" type="text" value={this.state.comment}
|
||||
onChange={this.handleCommentChange} disabled={this.state.sending}
|
||||
placeholder={'[逐条转发]共' + this.props.seqs.length + '条消息'} />
|
||||
{this.state.error ? <div className="auth-field-error">{this.state.error}</div> : null}
|
||||
<div className="batch-forward-actions">
|
||||
<button type="button" onClick={this.handleCancelConfirm} disabled={this.state.sending}>取消</button>
|
||||
@@ -149,6 +185,7 @@ export default class BatchForwardDialog extends React.Component {
|
||||
</div>
|
||||
</div>
|
||||
<SearchContacts placeholder="搜索联系人" onSearchContacts={this.handleSearchContacts} />
|
||||
{this.state.error ? <div className="auth-field-error">{this.state.error}</div> : null}
|
||||
<ContactList
|
||||
tinode={this.props.tinode}
|
||||
contacts={contacts}
|
||||
|
||||
Reference in New Issue
Block a user