第六轮深度测试:7个并行agent覆盖全部11章,修复21处前端问题
Ch1-2: 用户名注册邀请码错误改为友好文案(原为原始TypeError泄露给用户); 企业注册页扫描图标补上点击反馈。 Ch3-4: 发名片消息补传typeHint(此前被后端误分类成text,搜索/历史摘要显示成JSON); 文件卡片按mime大类区分图标颜色(此前所有文件都是同一个灰色通用图标); 表情面板补上专属退格/发送按钮(浅蓝禁用/深蓝启用两态);订正一处与截图不符的代码注释。 Ch5-6: 群聊设置页"群成员"补上可点击的完整成员列表页(复用MemberPicker字母分组); 群文件页去掉无依据的硬编码"/10GB"容量上限显示。 Ch7: 收藏点击图片/视频缩略图补上预览;"查找聊天记录-链接"tab补上定位回原消息; 文件下载页返回入口按来源tab纠正;批量转发成功计数改为按目标会话去重 (原公式混用"收藏条数"和"目标会话数"两个维度,混选多条收藏转发时可能显示负数); 收藏/视频tab切换补上URL路由同步。 Ch8: topic.onInfo在通话期间补上事件转发(此前通话中"对方正在输入"和已读回执静默失效); 主叫等待接听页补上"正在等待对方接受邀请…"文案;语音通话最小化胶囊的还原按钮移出 拖拽区域(原来嵌在draggable内部,指针捕获可能吞掉点击);修复中等窗宽(641-750px)下 本地摄像头预览遮挡"切换摄像头"按钮的CSS重叠。 Ch9: 部门树展开时跳过child_count=0的注定空请求;月报字数上限从硬编码1000改为读取 后端真实的10000;发起会议补上"结束时间需晚于开始时间"的本地校验和更具体的报错; 日报/月报统计接口补上department_id透传(此前包装函数注释断言后端会忽略,实际已支持)。 Ch10-11: URL风险检测补上g标志(原来一条消息只检查第一个链接,第二个链接哪怕是高危 也不会被拦截);补上"安全教育"设置入口(原功能完整实现但零入口,需手改hash才能打开); 修改密码按钮补上busy态反馈;青少年模式PIN页补上"忘记独立密码"入口(后端已支持重置, 前端未接);"关于我们"补上"联系我们"行。 7个agent同时对全部11章存量后端问题条目逐一复核,结论详见待整理的后端问题清单更新 (Ch1-2发现一条P0级后端问题:验证码固定值"123456",已记录未修复,不在此commit修改 im_be仓库范围内)。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
d42591284f
commit
f42b8536e5
@@ -1337,9 +1337,16 @@ class MessagesView extends (react__WEBPACK_IMPORTED_MODULE_0___default().Compone
|
||||
}
|
||||
return result;
|
||||
};
|
||||
const urlMatch = originalText && originalText.match(/https?:\/\/\S+/);
|
||||
if (urlMatch) {
|
||||
return (0,_lib_im_api_js__WEBPACK_IMPORTED_MODULE_19__.checkURL)(urlMatch[0], 'message_compose').then(result => {
|
||||
const urlMatches = originalText && originalText.match(/https?:\/\/\S+/g);
|
||||
if (urlMatches) {
|
||||
const RISK_RANK = {
|
||||
block: 2,
|
||||
warn: 1,
|
||||
allow: 0
|
||||
};
|
||||
const urls = Array.from(new Set(urlMatches));
|
||||
return Promise.all(urls.map(url => (0,_lib_im_api_js__WEBPACK_IMPORTED_MODULE_19__.checkURL)(url, 'message_compose'))).then(results => {
|
||||
const result = results.reduce((worst, r) => (RISK_RANK[r.decision] || 0) > (RISK_RANK[worst.decision] || 0) ? r : worst);
|
||||
if (result.decision === 'allow') {
|
||||
return doSend();
|
||||
}
|
||||
@@ -2398,6 +2405,23 @@ __webpack_require__.r(__webpack_exports__);
|
||||
|
||||
|
||||
|
||||
const ATTACHMENT_TYPE_META = {
|
||||
image: ['image', '#3ba55c'],
|
||||
video: ['videocam', '#3b82c4'],
|
||||
audio: ['audiotrack', '#8b5cf6'],
|
||||
document: ['description', '#e05d44'],
|
||||
file: ['insert_drive_file', '#8a8f98']
|
||||
};
|
||||
function attachmentTypeFromMime(mime) {
|
||||
const m = (mime || '').toLowerCase();
|
||||
if (m.startsWith('image/')) return 'image';
|
||||
if (m.startsWith('video/')) return 'video';
|
||||
if (m.startsWith('audio/')) return 'audio';
|
||||
if (m === 'application/pdf' || m === 'text/plain' || m.includes('msword') || m.includes('wordprocessingml') || m.includes('spreadsheetml') || m.includes('presentationml') || m === 'application/vnd.ms-excel' || m === 'application/vnd.ms-powerpoint') {
|
||||
return 'document';
|
||||
}
|
||||
return 'file';
|
||||
}
|
||||
class Attachment extends (react__WEBPACK_IMPORTED_MODULE_0___default().Component) {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@@ -2469,12 +2493,16 @@ class Attachment extends (react__WEBPACK_IMPORTED_MODULE_0___default().Component
|
||||
description: "Call to save an attachment"
|
||||
}, void 0, false)]
|
||||
}, void 0, true);
|
||||
const [icon, color] = ATTACHMENT_TYPE_META[attachmentTypeFromMime(this.props.mimetype)];
|
||||
return (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)("div", {
|
||||
className: "attachment",
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)("div", {
|
||||
children: (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)("i", {
|
||||
className: "material-icons big gray",
|
||||
children: "insert_drive_file"
|
||||
className: "material-icons big",
|
||||
style: {
|
||||
color
|
||||
},
|
||||
children: icon
|
||||
}, void 0, false)
|
||||
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)("div", {
|
||||
className: "flex-column",
|
||||
@@ -3584,6 +3612,7 @@ class SendMessage extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureComp
|
||||
this.handleHoldVisibilityChange = this.handleHoldVisibilityChange.bind(this);
|
||||
this.toggleEmojiPanel = this.toggleEmojiPanel.bind(this);
|
||||
this.insertEmoji = this.insertEmoji.bind(this);
|
||||
this.deleteLastChar = this.deleteLastChar.bind(this);
|
||||
this.toggleAttachPanel = this.toggleAttachPanel.bind(this);
|
||||
this.openCardPicker = this.openCardPicker.bind(this);
|
||||
this.openFavPicker = this.openFavPicker.bind(this);
|
||||
@@ -3888,6 +3917,35 @@ class SendMessage extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureComp
|
||||
}
|
||||
});
|
||||
}
|
||||
deleteLastChar() {
|
||||
const ta = this.messageEditArea;
|
||||
const start = ta ? ta.selectionStart : this.state.message.length;
|
||||
const end = ta ? ta.selectionEnd : this.state.message.length;
|
||||
let newMessage, caretPos;
|
||||
if (start !== end) {
|
||||
newMessage = this.state.message.slice(0, start) + this.state.message.slice(end);
|
||||
caretPos = start;
|
||||
} else if (start > 0) {
|
||||
const before = Array.from(this.state.message.slice(0, start));
|
||||
before.pop();
|
||||
newMessage = before.join('') + this.state.message.slice(start);
|
||||
caretPos = before.join('').length;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
this.setState({
|
||||
message: newMessage
|
||||
});
|
||||
if (this.props.onMessageChange) {
|
||||
this.props.onMessageChange(newMessage);
|
||||
}
|
||||
requestAnimationFrame(() => {
|
||||
if (this.messageEditArea) {
|
||||
this.messageEditArea.focus();
|
||||
this.messageEditArea.setSelectionRange(caretPos, caretPos);
|
||||
}
|
||||
});
|
||||
}
|
||||
toggleAttachPanel(e) {
|
||||
e.preventDefault();
|
||||
this.setState(s => ({
|
||||
@@ -3925,7 +3983,7 @@ class SendMessage extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureComp
|
||||
const build = avatarUrl => {
|
||||
const card = new tinode_sdk__WEBPACK_IMPORTED_MODULE_2__.TheCard(item.display_name || item.user_id, avatarUrl);
|
||||
tinode_sdk__WEBPACK_IMPORTED_MODULE_2__.TheCard.setTinodeID(card, item.user_id);
|
||||
this.props.onSendMessage(tinode_sdk__WEBPACK_IMPORTED_MODULE_2__.Drafty.appendTheCard(null, card));
|
||||
this.props.onSendMessage(tinode_sdk__WEBPACK_IMPORTED_MODULE_2__.Drafty.appendTheCard(null, card), undefined, undefined, 'card');
|
||||
};
|
||||
if (item.avatar_file_id) {
|
||||
(0,_lib_im_api_js__WEBPACK_IMPORTED_MODULE_6__.getFileUrl)(item.avatar_file_id).then(build).catch(() => build(undefined));
|
||||
@@ -4217,7 +4275,33 @@ class SendMessage extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureComp
|
||||
},
|
||||
children: emoji
|
||||
}, emoji + i, false))
|
||||
}, void 0, false)]
|
||||
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_7__.jsxDEV)("div", {
|
||||
id: "emoji-panel-footer",
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_7__.jsxDEV)("a", {
|
||||
href: "#",
|
||||
onClick: e => {
|
||||
e.preventDefault();
|
||||
this.deleteLastChar();
|
||||
},
|
||||
title: "删除",
|
||||
children: (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_7__.jsxDEV)("i", {
|
||||
className: "material-icons",
|
||||
children: "backspace"
|
||||
}, void 0, false)
|
||||
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_7__.jsxDEV)("a", {
|
||||
href: "#",
|
||||
className: 'emoji-panel-send' + (this.state.message ? ' active' : ''),
|
||||
onClick: e => {
|
||||
e.preventDefault();
|
||||
this.handleSend(e);
|
||||
},
|
||||
title: formatMessage(messages.icon_title_send),
|
||||
children: (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_7__.jsxDEV)("i", {
|
||||
className: "material-icons",
|
||||
children: sendIcon
|
||||
}, void 0, false)
|
||||
}, void 0, false)]
|
||||
}, void 0, true)]
|
||||
}, void 0, true) : null, this.state.attachOpen ? (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_7__.jsxDEV)("div", {
|
||||
id: "attach-panel",
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_7__.jsxDEV)("a", {
|
||||
|
||||
Reference in New Issue
Block a user