Files
DEMO-AGENT/templates/chat/index.html

484 lines
22 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "base.html" %}
{% block title %}审核智能体{% endblock %}
{% block content %}
<section class="page-header">
<span class="eyebrow">Agent Workspace</span>
<h1 class="page-title">审核智能体</h1>
<p class="page-lead">以会话为中心组织资料包上传、节点式审核结果和动态任务信息卡。</p>
{% if conversation %}
<div class="badge-row">
<span class="pill pill-accent">批次:{{ conversation.batch_id }}</span>
<span class="pill">产品:{{ conversation.product_name|default:"未识别产品名称" }}</span>
<span class="pill">阶段:{{ conversation_context.task_status }}</span>
</div>
{% endif %}
</section>
{% if conversation %}
<section class="grid-2">
<article class="panel">
<h2 class="section-title">顶部对话上下文</h2>
<p class="section-copy">进入会话后,先用当前批次、产品和风险状态快速建立审核上下文。</p>
<ul class="detail-list">
<li class="detail-item"><strong>批次编号</strong><div>{{ conversation_context.batch_id }}</div></li>
<li class="detail-item"><strong>产品名称</strong><div>{{ conversation_context.product_name|default:"未识别产品名称" }}</div></li>
<li class="detail-item"><strong>当前流程类型</strong><div>{{ conversation_context.workflow_type }}</div></li>
<li class="detail-item"><strong>当前审核阶段</strong><div>{{ conversation_context.task_status }}</div></li>
<li class="detail-item"><strong>当前最高风险等级</strong><div>{{ conversation_context.highest_risk_level }}</div></li>
<li class="detail-item"><strong>是否允许正式导出</strong><div>{{ conversation_context.export_allowed }}</div></li>
</ul>
</article>
<article class="panel">
<h2 class="section-title">推荐提问模板</h2>
<p class="section-copy">用这些提问模板快速进入目录汇总、完整性检查、字段抽取和风险分析。</p>
<div class="button-row">
{% for item in prompt_templates %}
<span class="pill pill-accent">{{ item }}</span>
{% endfor %}
</div>
</article>
</section>
{% endif %}
<section class="workspace-grid" style="grid-template-columns: 320px minmax(0, 1fr) 360px;">
<div class="stack">
<article class="panel">
<h2 class="section-title">会话历史</h2>
<p class="section-copy">左侧保留历史会话,标题默认使用解析后的产品名称。</p>
<ul class="detail-list">
{% for item in conversation_history %}
<li class="detail-item">
<strong><a href="{% url 'chat:detail' item.conversation_id %}">{{ item.title }}</a></strong>
<div class="muted">产品:{{ item.product_name|default:"未识别" }}</div>
<div class="muted">批次:{{ item.batch_id|default:"未绑定" }}</div>
<div class="muted">风险:{{ item.risk_level }}</div>
<div class="muted">最近更新:{{ item.updated_at|date:"Y-m-d H:i" }}</div>
<div class="badge-row" style="margin-top: 8px;">
<span class="pill pill-accent">{{ item.batch_binding_label }}</span>
</div>
</li>
{% empty %}
<li class="detail-item">
<strong>暂无历史会话</strong>
<div class="muted">可以直接在中间区域提问Agent 会优先检索知识库。</div>
</li>
{% endfor %}
</ul>
</article>
</div>
<div class="stack">
<article class="panel">
<div class="section-heading">
<div>
<h2 class="section-title">对话区与节点导航</h2>
<p class="section-copy">中间区域承接用户问题、Agent 回答和节点式结果摘要。</p>
</div>
</div>
{% if node_results %}
<div class="badge-row" style="margin-bottom: 14px;">
{% for node in node_results %}
<span class="pill {% if node.status == '已完成' %}pill-success{% else %}pill-signal{% endif %}">{{ node.label }} / {{ node.status }}</span>
{% endfor %}
</div>
{% endif %}
<form method="post" class="stack" action="{% if conversation %}{% url 'chat:detail' conversation.conversation_id %}{% else %}{% url 'chat:index' %}{% endif %}">
{% csrf_token %}
<div>
{{ form.message.label_tag }}
{{ form.message }}
{% if form.message.errors %}
<p class="notice notice-error">{{ form.message.errors|join:" " }}</p>
{% endif %}
</div>
<div>
{{ form.document_ids.label_tag }}
<div class="checkbox-list">
{% for checkbox in form.document_ids %}
<label class="checkbox-item">
{{ checkbox.tag }}
<span>{{ checkbox.choice_label }}</span>
</label>
{% empty %}
<div class="notice">未选择文档时Agent 会按问题检索当前知识库。</div>
{% endfor %}
</div>
</div>
<div class="button-row">
<button type="submit">发送问题</button>
</div>
</form>
{% if result %}
<div class="detail-item" style="margin-top: 16px;">
<strong>Agent 回答</strong>
<div>{{ result.answer|linebreaksbr }}</div>
</div>
{% elif not conversation %}
<div class="notice" style="margin-top: 16px;">可以先不上传资料,直接询问注册法规、资料清单、模板字段或历史知识库内容。</div>
{% endif %}
</article>
<article class="panel">
<h2 class="section-title">节点式结果</h2>
{% if analysis_card or export_card or risk_card or notify_card %}
<div class="stack">
{% if analysis_card %}
<div class="detail-item">
<strong>{{ analysis_card.title }}</strong>
{% if analysis_card.summary %}
<div>{{ analysis_card.summary }}</div>
{% endif %}
</div>
<div class="panel" style="padding: 14px;">
<h3 class="section-title" style="font-size: 1rem;">摘要指标</h3>
<div class="badge-row">
{% for item in analysis_card.stats %}
<span class="pill pill-accent">{{ item.label }}{{ item.value }}</span>
{% endfor %}
</div>
</div>
<div class="panel" style="padding: 14px;">
<h3 class="section-title" style="font-size: 1rem;">节点结果明细</h3>
<ul class="detail-list">
{% if analysis_card.kind == "overview" %}
{% for item in analysis_card.items %}
<li class="detail-item">{{ item.chapter_code }} / {{ item.document_count }} 份</li>
{% empty %}
<li class="detail-item">当前无目录汇总结果。</li>
{% endfor %}
{% elif analysis_card.kind == "completeness" %}
{% for item in analysis_card.items %}
<li class="detail-item">
<strong>{{ item.document_name|default:"必交项" }}</strong>
<div>章节点:{{ item.chapter_code|default:"-" }}</div>
<div>{{ item.reason|default:"当前资料包未提供该资料。" }}</div>
</li>
{% empty %}
<li class="detail-item">当前无缺失项。</li>
{% endfor %}
{% elif analysis_card.kind == "consistency" %}
{% for item in analysis_card.items %}
<li class="detail-item">
<strong>{{ item.field_name|default:"冲突字段" }}</strong>
<div>{{ item.issue|default:item }}</div>
</li>
{% empty %}
<li class="detail-item">当前无一致性冲突。</li>
{% endfor %}
{% elif analysis_card.kind == "field_extraction" %}
{% for item in analysis_card.items %}
<li class="detail-item">
<strong>{{ item.field_name|default:"抽取字段" }}</strong>
<div>{{ item.field_value|default:"-" }}</div>
{% if item.source_document %}
<div class="muted">来源:{{ item.source_document }}</div>
{% endif %}
</li>
{% empty %}
<li class="detail-item">当前无抽取字段。</li>
{% endfor %}
{% else %}
{% for item in analysis_card.items %}
<li class="detail-item">{{ item }}</li>
{% empty %}
<li class="detail-item">当前无明细结果。</li>
{% endfor %}
{% endif %}
</ul>
</div>
<div class="panel" style="padding: 14px;">
<h3 class="section-title" style="font-size: 1rem;">提示与异常</h3>
<ul class="detail-list">
{% for item in analysis_card.warnings %}
<li class="detail-item">
{% if analysis_card.kind == "field_extraction" %}
<strong>{{ item.field_name|default:"低置信度字段" }}</strong>
<div>{{ item.field_value|default:"-" }}</div>
{% if item.source_document %}
<div class="muted">来源:{{ item.source_document }}</div>
{% endif %}
{% elif analysis_card.kind == "completeness" %}
<strong>{{ item.document_name|default:"错放项" }}</strong>
<div>目标章节点:{{ item.chapter_code|default:"-" }}</div>
<div>当前归类:{{ item.current_location|default:"未识别" }}</div>
{% else %}
{{ item }}
{% endif %}
</li>
{% empty %}
<li class="detail-item">当前无额外提示。</li>
{% endfor %}
</ul>
</div>
{% endif %}
{% if risk_card %}
<div class="detail-item">
<strong>风险预警能力卡</strong>
<div>总风险等级:{{ risk_card.highest_risk_level|default:"-" }}</div>
<div>是否通过:{{ risk_card.pass_status|default:"-" }}</div>
{% if risk_card.summary %}
<div>{{ risk_card.summary }}</div>
{% endif %}
</div>
<div class="panel" style="padding: 14px;">
<h3 class="section-title" style="font-size: 1rem;">待复核与风险项</h3>
<ul class="detail-list">
{% for item in risk_card.manual_review_items %}
<li class="detail-item">{{ item }}</li>
{% empty %}
{% for item in risk_card.risk_items %}
<li class="detail-item">
<strong>{{ item.title|default:item.issue }}</strong>
<div class="muted">{{ item.risk_level|default:"-" }}</div>
</li>
{% empty %}
<li class="detail-item">当前无待复核项。</li>
{% endfor %}
{% endfor %}
</ul>
</div>
<div class="panel" style="padding: 14px;">
<h3 class="section-title" style="font-size: 1rem;">责任角色</h3>
<div class="table-wrap">
<table class="data-table">
<thead>
<tr>
<th>owner_role</th>
<th>owner_name</th>
<th>department</th>
<th>chapter_scope</th>
<th>risk_scope</th>
<th>feishu_user_id</th>
<th>feishu_open_id</th>
<th>feishu_name</th>
<th>notify_enabled</th>
</tr>
</thead>
<tbody>
{% for item in risk_card.owner_roles %}
<tr>
<td>{{ item.owner_role }}</td>
<td>{{ item.owner_name }}</td>
<td>{{ item.department }}</td>
<td>{{ item.chapter_scope }}</td>
<td>{{ item.risk_scope }}</td>
<td>{{ item.feishu_user_id }}</td>
<td>{{ item.feishu_open_id }}</td>
<td>{{ item.feishu_name }}</td>
<td>{{ item.notify_enabled|yesno:"True,False" }}</td>
</tr>
{% empty %}
<tr><td colspan="9">当前无责任角色。</td></tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endif %}
<div class="detail-item">
{% if export_card %}
<strong>Word 导出能力卡</strong>
<div>模板:{{ export_card.template_name }} / {{ export_card.template_version|default:"-" }}</div>
<div>当前导出状态:{{ export_card.export_status|default:"-" }}</div>
{% elif notify_card %}
<strong>飞书通知能力卡</strong>
<div>通知原因:{{ notify_card.notify_reason|default:"-" }}</div>
<div>消息状态:{{ notify_card.message_status|default:"-" }}</div>
{% endif %}
</div>
{% if export_card %}
<div class="panel" style="padding: 14px;">
<h3 class="section-title" style="font-size: 1rem;">回填字段表</h3>
<div class="table-wrap">
<table class="data-table">
<thead>
<tr>
<th>占位符</th>
<th>字段名</th>
<th>字段值</th>
<th>来源</th>
<th>回填状态</th>
<th>是否必填</th>
</tr>
</thead>
<tbody>
{% for item in export_card.filled_fields %}
<tr>
<td>{{ item.placeholder }}</td>
<td>{{ item.field_name }}</td>
<td>{{ item.field_value }}</td>
<td>{{ item.source }}</td>
<td>{{ item.fill_status }}</td>
<td>{{ item.required|yesno:"是,否" }}</td>
</tr>
{% empty %}
<tr><td colspan="6">当前暂无回填字段。</td></tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endif %}
{% if export_card %}
<div class="panel" style="padding: 14px;">
<h3 class="section-title" style="font-size: 1rem;">拦截项区</h3>
<ul class="detail-list">
{% for item in export_card.blocked_fields %}
<li class="detail-item">
<strong>{{ item.field_name }}</strong>
<div>拦截原因:{{ item.block_reason }}</div>
<div class="muted">来源:{{ item.risk_source }}</div>
</li>
{% empty %}
<li class="detail-item">当前无拦截项。</li>
{% endfor %}
</ul>
</div>
{% endif %}
{% if notify_card %}
<div class="panel" style="padding: 14px;">
<h3 class="section-title" style="font-size: 1rem;">飞书通知能力卡</h3>
<ul class="detail-list">
<li class="detail-item"><strong>通知原因</strong><div>{{ notify_card.notify_reason|default:"-" }}</div></li>
<li class="detail-item"><strong>消息状态</strong><div>{{ notify_card.message_status|default:"-" }}</div></li>
<li class="detail-item"><strong>被 @ 处理人</strong><div>{{ notify_card.mentioned_users|join:" / "|default:"-" }}</div></li>
<li class="detail-item"><strong>Web 详情链接</strong><div>{{ notify_card.web_detail_url|default:"-" }}</div></li>
</ul>
</div>
{% endif %}
<div class="button-row">
{% if export_card %}
<a class="button" href="{% url 'platform_ui:knowledge-base' %}?view=template_mappings">维护 Word 模板</a>
<a class="button" href="{% url 'platform_ui:knowledge-base' %}?view=field_schemas">维护字段映射</a>
<a class="button" href="{% url 'audit:list' %}">查看导出记录</a>
{% endif %}
{% if risk_card %}
<a class="button" href="{% url 'platform_ui:knowledge-base' %}?view=owner_mappings">查看责任人映射</a>
{% endif %}
{% if notify_card %}
<a class="button" href="{% url 'platform_ui:knowledge-base' %}?view=feishu_configs">查看飞书配置</a>
{% endif %}
</div>
</div>
{% elif result and result.structured_output %}
<table class="kv-table">
<tbody>
{% for key, value in result.structured_output.items %}
<tr>
<th>{{ key }}</th>
<td><pre class="code-block">{{ value }}</pre></td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<div class="notice">执行任务后,这里会展示结构化节点结果。</div>
{% endif %}
</article>
</div>
<div class="stack">
<article class="panel">
<h2 class="section-title">上传区</h2>
<p class="section-copy">右侧保留资料包上传入口和当前会话的资料上下文。</p>
{% if batch %}
<ul class="detail-list">
<li class="detail-item">
<strong>当前资料包</strong>
<div>批次:{{ batch.batch_id }}</div>
<div>文件数:{{ batch.file_count }}</div>
<div>页数:{{ batch.page_count }}</div>
<div>导入状态:{{ batch.get_import_status_display_text }}</div>
</li>
</ul>
<form method="post" action="{% url 'chat:upload-documents' conversation.conversation_id %}" enctype="multipart/form-data" class="stack" style="margin-top: 16px;">
{% csrf_token %}
<div>
{{ upload_form.files.label_tag }}
{{ upload_form.files }}
</div>
<div class="button-row">
<button type="submit">继续上传资料</button>
<a class="button" href="{% url 'documents:list' %}">返回资料包</a>
</div>
</form>
<div class="button-row" style="margin-top: 16px;">
<a class="button" href="{% url 'documents:upload' %}">导入新资料包</a>
</div>
<form method="post" action="{% url 'chat:export-word' conversation.conversation_id %}" class="stack" style="margin-top: 16px;">
{% csrf_token %}
<div class="button-row">
<button type="submit">生成导出草稿</button>
</div>
</form>
{% else %}
<div class="notice">暂无绑定资料包,仍可先通过中间对话区查询知识库。</div>
<form method="post" action="{% url 'documents:upload' %}" enctype="multipart/form-data" class="stack" style="margin-top: 16px;">
{% csrf_token %}
<input type="hidden" name="scenario_id" value="document_review">
<div>
{{ upload_form.files.label_tag }}
{{ upload_form.files }}
<p class="help-text">支持 PDF、DOCX、MD、TXT、ZIP、7Z 与 RAR。上传后会自动形成资料包并绑定新的审核会话。</p>
</div>
<div class="button-row">
<button type="submit">导入资料包</button>
<a class="button" href="{% url 'documents:upload' %}">打开导入向导</a>
</div>
</form>
{% endif %}
</article>
<article class="panel">
<h2 class="section-title">动态信息卡</h2>
<ul class="detail-list">
<li class="detail-item">
<strong>最高风险等级</strong>
<div>{{ workspace_summary.highest_risk_level }}</div>
</li>
<li class="detail-item">
<strong>是否允许正式导出</strong>
<div>{{ workspace_summary.export_allowed }}</div>
</li>
<li class="detail-item">
<strong>通知状态</strong>
<div>{{ workspace_summary.notify_status }}</div>
</li>
<li class="detail-item">
<strong>导出状态</strong>
<div>{{ workspace_summary.export_status }}</div>
</li>
<li class="detail-item">
<strong>导出下载地址</strong>
<div>
{% if workspace_summary.download_url %}
<a href="{{ workspace_summary.download_url }}">下载导出文件</a>
{% else %}
-
{% endif %}
</div>
</li>
<li class="detail-item">当前会话围绕 conversation_id / batch_id / product_name 串联;未绑定资料包时以知识库问答方式执行。</li>
{% if audit_log %}
<li class="detail-item"><a href="{% url 'audit:detail' audit_log.id %}">查看本次处理历史</a></li>
{% endif %}
</ul>
</article>
</div>
</section>
{% endblock %}