feat(chat): 支持流式回复与用户节点导航

This commit is contained in:
2026-06-05 00:11:53 +08:00
parent 84e045f5ab
commit 7ab5aad938
8 changed files with 676 additions and 15 deletions

View File

@@ -92,10 +92,11 @@
</div>
</header>
<section class="chat-stage">
<div class="chat-scroll">
<section class="chat-stage" data-stream-url="{% url 'chat_stream' %}">
<div class="chat-scroll-wrap">
<div class="chat-scroll" id="chatScroll">
{% if current_conversation %}
<div class="conversation-header">
<div class="conversation-header" id="conversation-top" data-node-label="会话开始">
<div>
<p class="eyebrow">审核智能体</p>
<h1>{{ current_conversation.title|default:"新对话" }}</h1>
@@ -104,7 +105,11 @@
</div>
{% for message in messages %}
<article class="message {{ message.role }}">
<article
class="message {{ message.role }}"
id="message-{{ message.pk }}"
data-node-label="{% if message.role == 'assistant' %}AI{% else %}用户{% endif %} {{ forloop.counter }}"
>
<div class="message-avatar{% if message.role == 'user' %} user-mark{% endif %}">
{% if message.role == "assistant" %}AI{% else %}{{ request.user.username|slice:":1"|upper }}{% endif %}
</div>
@@ -121,14 +126,30 @@
</div>
{% endif %}
</div>
<nav class="node-rail{% if not current_conversation %} hidden{% endif %}" id="nodeRail" aria-label="对话节点导航">
<div class="node-rail-line"></div>
{% if current_conversation %}
{% for message in messages %}
{% if message.role == "user" %}
<a
class="node-anchor{% if forloop.last %} latest{% endif %}"
href="#message-{{ message.pk }}"
data-target="message-{{ message.pk }}"
title="用户 {{ forloop.counter }}"
>
<span class="node-dot"></span>
</a>
{% endif %}
{% endfor %}
{% endif %}
</nav>
</div>
<div class="composer-wrap">
<form class="composer" action="/" method="post">
<form class="composer" action="/" method="post" id="chatComposer">
{% csrf_token %}
<input type="hidden" name="action" value="send_message">
{% if current_conversation %}
<input type="hidden" name="conversation_id" value="{{ current_conversation.pk }}">
{% endif %}
<input type="hidden" name="conversation_id" id="conversationIdInput" value="{% if current_conversation %}{{ current_conversation.pk }}{% endif %}">
<label class="sr-only" for="prompt">输入消息</label>
<textarea id="prompt" name="prompt" rows="1" placeholder="输入审核问题、法规条款、说明书疑点或上传需求"></textarea>
<div class="composer-actions">
@@ -137,7 +158,7 @@
<span class="tool-chip passive-chip">说明书审核</span>
<span class="tool-chip passive-chip">风险识别</span>
</div>
<button class="send-button" type="submit">发送</button>
<button class="send-button" type="submit" id="sendButton">发送</button>
</div>
</form>
</div>