Files
X-Financial/web/src/views/ChatView.vue
DESKTOP-72TV0V4\caoxiaozhu 9785fb527b refactor: split project into web and server directories
- Move frontend to web/ directory
- Add server/ directory for backend
- Restructure project for前后端分离架构

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-06 11:00:38 +08:00

179 lines
7.5 KiB
Vue
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.
<template>
<section class="qa-view">
<div class="qa-layout">
<aside class="left-column">
<article class="panel side-panel conversation-list">
<header>
<h3>问答会话</h3>
<button class="outline-action" type="button" @click="emit('draft', '')">
<i class="mdi mdi-plus"></i>
<span>新建会话</span>
</button>
</header>
<div class="session-scroll">
<button
v-for="item in sessions"
:key="item.title"
class="session-row"
:class="{ active: item.active }"
type="button"
@click="applyPrompt(item.title)"
>
<span><i class="mdi mdi-message-processing-outline"></i></span>
<strong>{{ item.title }}</strong>
<time>{{ item.time }}</time>
</button>
</div>
</article>
</aside>
<article class="panel chat-panel">
<div ref="localMessageList" class="message-stream" aria-live="polite">
<div class="talk-row user">
<span class="avatar user-avatar"></span>
<div class="talk-content">
<header><strong>张明</strong><time>10:32</time></header>
<p class="user-question">北京出差酒店超标报销怎么处理</p>
</div>
</div>
<div class="talk-row assistant">
<span class="avatar assistant-avatar"><i class="mdi mdi-robot-outline"></i></span>
<div class="talk-content">
<header><strong>财务AI助手</strong><time>10:32</time></header>
<div class="answer-card">
<section>
<h4>结论</h4>
<p>酒店费用超过标准的部分原则上不予报销特殊情况可申请例外报销</p>
</section>
<section>
<h4>处理建议</h4>
<ul>
<li>超标部分由个人自理或按制度退回保留超标说明和相关凭证</li>
<li>符合公司相关政策的可提交佐证材料申请例外报销</li>
</ul>
</section>
<section>
<h4>适用规则</h4>
<ul>
<li>差旅报销管理办法2024第十二条住宿标准及超标处理</li>
<li>费用报销审批流程附件1国内差旅住宿标准</li>
</ul>
</section>
<footer>
<span>是否有帮助</span>
<button type="button" aria-label="有帮助"><i class="mdi mdi-thumb-up-outline"></i></button>
<button type="button" aria-label="无帮助"><i class="mdi mdi-thumb-down-outline"></i></button>
</footer>
</div>
</div>
</div>
<div class="talk-row user">
<span class="avatar user-avatar"></span>
<div class="talk-content">
<header><strong>张明</strong><time>10:35</time></header>
<p class="user-question">如果出差地公司名称不一致还能报销吗</p>
</div>
</div>
<div class="talk-row assistant">
<span class="avatar assistant-avatar"><i class="mdi mdi-robot-outline"></i></span>
<div class="talk-content">
<header><strong>财务AI助手</strong><time>10:35</time></header>
<div class="answer-card compact">
<section>
<h4>结论</h4>
<p>一般情况下差旅地与参会公司名称不一致需按异常处理建议提供情况说明并加盖公章或补充邀请材料</p>
</section>
<section>
<h4>适用规则</h4>
<ul>
<li>发票管理规定及失误销细则第二章发票基本要求</li>
<li>差旅报销管理办法附件1报销凭证要求</li>
</ul>
</section>
</div>
</div>
</div>
<div v-for="message in messages" :key="message.id" class="talk-row" :class="message.role === 'user' ? 'user' : 'assistant'">
<span class="avatar" :class="message.role === 'user' ? 'user-avatar' : 'assistant-avatar'">
<template v-if="message.role === 'user'"></template>
<i v-else class="mdi mdi-robot-outline"></i>
</span>
<div class="talk-content">
<header>
<strong>{{ message.role === 'user' ? '我' : '财务AI助手' }}</strong>
<time>刚刚</time>
</header>
<p :class="message.role === 'user' ? 'user-question' : 'agent-answer'">{{ message.text }}</p>
</div>
</div>
</div>
<div class="composer-wrap">
<div class="prompt-toolbar">
<span>猜你想问</span>
<button v-for="prompt in visiblePrompts" :key="prompt.text" type="button" @click="applyPrompt(prompt.text)">
<i :class="prompt.icon"></i>
{{ prompt.short }}
</button>
<button class="icon-refresh" type="button" aria-label="换一批问题" @click="rotatePrompts">
<i class="mdi mdi-refresh"></i>
</button>
</div>
<div class="composer">
<textarea
:value="draft"
rows="2"
placeholder="请输入你的问题,例如:差旅报销特殊标准是什么?"
@input="emit('draft', $event.target.value)"
@keydown.ctrl.enter.prevent="emit('send')"
></textarea>
<button class="send-button" type="button" aria-label="发送问题" @click="emit('send')">
<i class="mdi mdi-send"></i>
</button>
</div>
</div>
</article>
<aside class="right-column">
<article class="panel info-panel hot-top-panel">
<header>
<h3><i class="mdi mdi-fire"></i> 热门问题 Top10</h3>
<button type="button" @click="rotatePrompts">换一批 <i class="mdi mdi-refresh"></i></button>
</header>
<div class="top-question-list">
<button v-for="(item, index) in hotQuestions" :key="item" type="button" @click="applyPrompt(item)">
<strong>{{ String(index + 1).padStart(2, '0') }}</strong>
<span>{{ item }}</span>
<i class="mdi mdi-chevron-right"></i>
</button>
</div>
</article>
<article class="panel info-panel similar-panel">
<header>
<h3>相似历史问题</h3>
<button type="button">查看全部 <i class="mdi mdi-chevron-right"></i></button>
</header>
<div class="similar-scroll">
<button v-for="item in similarQuestions" :key="item.text" class="similar-row" type="button" @click="applyPrompt(item.text)">
<span><i class="mdi mdi-file-question-outline"></i>{{ item.text }}</span>
<strong>{{ item.score }}</strong>
<i class="mdi mdi-chevron-right"></i>
</button>
</div>
</article>
</aside>
</div>
</section>
</template>
<script src="./scripts/ChatView.js"></script>
<style scoped src="../assets/styles/views/chat-view.css"></style>