Browse Source

智能体:问答审查智能体集成

lwx_v27
han2015 2 weeks ago
parent
commit
152183624a
  1. 2
      .env.development
  2. 2
      .env.production
  3. 292
      src/components/DesignForm/public/form/aiassist.vue

2
.env.development

@ -12,3 +12,5 @@ VITE_APP_SJZT_URL = 'http://172.20.5.86/prod-api'
VITE_OFFICE_HOST='http://myvuetest.net/kkapi'
VITE_ONLYOFFICE_HOST = 'http://myvuetest.net/onlyoffice'
VITE_DEFAULT_AI_AGENT = '5bd9b0e9-d3f4-4089-670a-880009e925a8'
#流程制度
VITE_REGUL_AI_AGENT = 'e3be1378-3915-4e5c-b526-9f5447df39ea'

2
.env.production

@ -8,3 +8,5 @@ VITE_APP_SJZT_URL = 'http://120.224.6.6:29911/prod-api'
VITE_OFFICE_HOST='https://gyhlw.hxgk.group/kkapi'
VITE_ONLYOFFICE_HOST = 'https://gyhlw.hxgk.group/onlyoffice'
VITE_DEFAULT_AI_AGENT = '74938263-ffe5-43c5-90af-25e62d34a51f'
#流程制度
VITE_REGUL_AI_AGENT = 'e3be1378-3915-4e5c-b526-9f5447df39ea'

292
src/components/DesignForm/public/form/aiassist.vue

@ -7,17 +7,24 @@
import { doAiChat,aiChatData} from "@/api/doc/space"
import { useUserStore } from "@/store/modules/user";
import { VueMarkdown } from '@crazydos/vue-markdown'
import rehypeRaw from 'rehype-raw'
//
const userStore = useUserStore();
const userid="p0"+userStore.userInfoCont.userId;
const regulaKey=import.meta.env.VITE_REGUL_AI_AGENT;
const baseURL=import.meta.env.VITE_APP_BASE_API
const regulaURL =`${baseURL}/aibot/agents/${regulaKey}/chat`
const conversation=ref("") //uuid
const controller = ref<AbortController | null>(null)
const interact_msg=ref<{ask:boolean,think:string,content:string}[]>([])
const interact_msg=ref<{ask:boolean,think:string,content:string}[]>([{ask:false,think:"是",content:`你好!我是你的AI助手,
你可以直接向我提问或者编辑表单我会自动为你提供相关信息`}])
//
const inputText = ref('');
const respMsg=ref("") //markdown
//
interface message{
@ -37,29 +44,34 @@ interface chatRecord{
defineExpose({onSendParamToAI})
async function onSendParamToAI(arr:Array<{ uuids: string[]; params: { [key: string]: any } }>){
interact_msg.value=[]
//interact_msg.value=[]
for (let ele of arr){
//interact_msg.value.unshift({ask:true,think:"", content:"AI"})
for (let uid of ele.uuids){
await doRequest(userid,uid,ele.params)
let para={
inputs: {
"checkType":"travel",
"checkInfo":JSON.stringify(ele.params)
},
response_mode:"streaming",
user:userid,//base64
}
//
interact_msg.value.push({ask:true,think:"", content:JSON.stringify(para)})
await doRequest(`${baseURL}/aibot/assisted/${uid}/workflow`,para)
}
}
}
async function doRequest(_user:string,uuid:string,param:any){
async function doRequest(furl:string,param:any){
let mRespMsg=""
const params={
"checkType":"travel",
"checkInfo":JSON.stringify(param)
}
controller.value = new AbortController();
try{
const res= await doAiChat(`${baseURL}/aibot/assisted/${uuid}/workflow`,{
inputs: params,
response_mode:"streaming",
user:_user,//base64
},controller.value.signal
const res= await doAiChat(
furl,
param,
controller.value.signal
)
if (!res.ok) {
@ -86,6 +98,9 @@ async function doRequest(_user:string,uuid:string,param:any){
if(json.event==="text_chunk"){
//conversation.value=json.conversation_id
mRespMsg+=json.data.text
}else if(json.event==="message"){
respMsg.value+=json.answer
mRespMsg+=json.answer
}
}
}
@ -95,19 +110,18 @@ async function doRequest(_user:string,uuid:string,param:any){
console.log('用户手动中断')
}
}
interact_msg.value.unshift({ask:true,think:"", content:JSON.stringify(param)})
respMsg.value=""
const arr=mRespMsg.split("</think>")
if(arr.length===1){
interact_msg.value.unshift({ask:false,think:"",content:arr[0]})
interact_msg.value.push({ask:false,think:"",content:arr[0]})
}else{
//
let st = arr[1].trim().match(/({.*})/s)
if (st){
let res= JSON.parse(st[1])
interact_msg.value.unshift({ask:false,think:res.success,content:res.reason})
interact_msg.value.push({ask:false,think:res.success,content:res.reason})
}else{
interact_msg.value.unshift({ask:false,think:arr[0],content:arr[1]})
interact_msg.value.push({ask:false,think:arr[0],content:arr[1]})
}
}
}
@ -118,50 +132,242 @@ function resetContext(){
//props.closefunc()
}
//
const sendMessage = () => {
const content = inputText.value.trim();
if (!content) return;
//
interact_msg.value.push({ ask: true,think:"", content });
const params={
inputs: {"onlineSearch":"否",
"useDataset":"是",
"queryUrl":""},
query:content,
response_mode:"streaming",
conversation_id:conversation.value,
user:userid
}
doRequest(regulaURL,params)
//
inputText.value = '';
};
//
// onMounted(() => {
// });
</script>
<template>
<div :style="{backgroundColor:'#f3f3f3'}">
<div class="reply_area" >
<template v-for="msg of interact_msg">
<div v-if="msg.ask" class="t_ask" >{{ msg.content }}</div>
<div v-else class="t_resp" :class="{merr:msg.think==false}">
<div class="chat-container">
<!-- 头部 -->
<div class="chat-header">
<span class="header-icon">🤖</span>
AI 助手
</div>
<!-- 消息区域 -->
<div class="reply-area">
<template v-for="(msg, index) in interact_msg" :key="index">
<!-- 用户消息 -->
<div v-if="msg.ask" class="message message-ask">
{{ msg.content }}
<!-- <VueMarkdown :markdown="msg.content"></VueMarkdown> -->
</div>
<!-- AI 回复 -->
<div v-else class="message message-resp" :class="{ 'message-error': msg.think == false }">
<VueMarkdown :markdown="msg.content" :rehype-plugins="[rehypeRaw]" ></VueMarkdown>
</div>
</template>
<div v-show="respMsg" class="message message-resp">
<VueMarkdown :markdown="respMsg" :rehype-plugins="[rehypeRaw]" class="t_resp"></VueMarkdown>
</div>
</div>
<!-- 底部输入区域 -->
<div class="input-area">
<input
v-model="inputText"
placeholder="输入您的问题..."
class="input-box"
type="text"
/>
<button
@click="sendMessage"
:disabled="!inputText.trim()"
class="send-button"
>
<span>发送</span>
</button>
</div>
</div>
</template>
<style lang="scss" scoped>
.reply_area{
width: 260px;
background: white;
.chat-container {
width: 360px;
background: #ffffff;
border-radius: 20px;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.12);
display: flex;
flex-direction: column;
overflow: hidden;
font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
}
/* 头部样式 */
.chat-header {
background: linear-gradient(180deg, #469edf, #bbdefb);
color: white;
padding: 8px 20px;
font-size: 18px;
font-weight: 600;
text-align: center;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.header-icon {
margin-right: 8px;
font-size: 20px;
}
/* 消息区域 */
.reply-area {
flex: 1;
padding: 20px;
overflow-y: auto;
background: #f8f9ff;
display: flex;
flex-direction: column;
overflow-wrap:anywhere;
gap: 12px;
}
/* 消息气泡 */
.message {
max-width: 85%;
padding: 12px 16px;
border-radius: 18px;
line-height: 1.5;
font-size: 14px;
word-wrap: break-word;
animation: fadeIn 0.3s ease-out;
}
/* 用户消息 - 右对齐 */
.message-ask {
align-self: flex-end;
background: linear-gradient(135deg, #4b6cb7 0%, #3a56a0 100%);
color: white;
border-bottom-right-radius: 6px;
box-shadow: 0 4px 12px rgba(75, 108, 183, 0.25);
}
/* AI 回复 - 左对齐 */
.message-resp {
align-self: flex-start;
background: #e8f5e9;
color: #2e7d32;
border-bottom-left-radius: 6px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.05);
}
/* 错误状态 */
.message-error {
background: #ffebee;
color: #c62828;
}
/* 底部输入区域 */
.input-area {
display: flex;
padding: 16px;
background: white;
border-top: 1px solid #e8eaf6;
gap: 10px;
}
/* 输入框 */
.input-box {
flex: 1;
padding: 12px 18px;
border: 1px solid #e0e0e0;
border-radius: 24px;
outline: none;
font-size: 14px;
transition: all 0.3s ease;
background: #f5f7ff;
}
.input-box:focus {
border-color: #4b6cb7;
background: white;
box-shadow: 0 0 0 3px rgba(75, 108, 183, 0.15);
}
/* 发送按钮 */
.send-button {
padding: 12px 22px;
background: linear-gradient(135deg, #4b6cb7 0%, #3a56a0 100%);
color: white;
border: none;
border-radius: 24px;
font-size: 14px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
min-width: 64px;
}
.send-button:hover:not(:disabled) {
transform: translateY(-2px);
box-shadow: 0 6px 16px rgba(75, 108, 183, 0.35);
filter: brightness(1.05);
}
.send-button:active:not(:disabled) {
transform: translateY(0);
}
.send-button:disabled {
opacity: 0.5;
cursor: not-allowed;
transform: none;
}
.t_ask{
margin: 5px;
align-self: end;
background-color: rgb(188 211 241);
border-radius:10px;
/* 动画效果 */
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(8px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.t_resp{
margin: 5px;
font-size:14px;
align-self: start;
color: black;
background-color: rgb(222, 243, 222);
/* 滚动条美化 */
.reply-area::-webkit-scrollbar {
width: 6px;
}
.merr{
background-color: rgb(253 176 211);
.reply-area::-webkit-scrollbar-track {
background: #f1f4ff;
}
.reply-area::-webkit-scrollbar-thumb {
background: #4b6cb7;
border-radius: 3px;
}
.reply-area::-webkit-scrollbar-thumb:hover {
background: #3a56a0;
}
</style>

Loading…
Cancel
Save