Browse Source

Merge branch 'han_v3'

space_permission
herenshan112 4 months ago
parent
commit
ab597ecbbd
  1. 4
      src/api/DesignForm/filterUnit.ts
  2. 6
      src/api/DesignForm/types.ts
  3. 1
      src/api/DesignForm/utils.ts
  4. 11
      src/api/doc/space.ts
  5. 64
      src/components/DesignForm/formControlPropertiNew.vue
  6. 12
      src/components/DesignForm/public/expand/digitpage.vue
  7. 177
      src/components/DesignForm/public/form/aiassist.vue
  8. 74
      src/components/DesignForm/public/form/form.vue
  9. 15
      src/components/DesignForm/public/form/formItem.vue

4
src/api/DesignForm/filterUnit.ts

@ -12,6 +12,8 @@ const analysisFromUnit = (unitInfo:formStruct) => {
unitInfo.formData.list.forEach((item:any) => { unitInfo.formData.list.forEach((item:any) => {
// console.log("解析出表单可作为AI变量的元素------1---1--->",item.label?1:2) // console.log("解析出表单可作为AI变量的元素------1---1--->",item.label?1:2)
if(!layoutUnit.includes(item.type)){ if(!layoutUnit.includes(item.type)){
//by han2015: 暂时只支持普通类型字段
if (item.type!='input' && item.type!='digitpage') return;
let labelName = "" let labelName = ""
if(item.label){ if(item.label){
labelName = item.label labelName = item.label
@ -20,7 +22,7 @@ const analysisFromUnit = (unitInfo:formStruct) => {
}else{ }else{
labelName = item.unitName labelName = item.unitName
} }
console.log("解析出表单可作为AI变量的元素----2--1-1----->",item) //console.log("解析出表单可作为AI变量的元素----2--1-1----->",item)
optionsInfo.push({ optionsInfo.push({
label:labelName, label:labelName,
value:item.name value:item.name

6
src/api/DesignForm/types.ts

@ -57,6 +57,12 @@ export interface FormData {
labelStyle:{}, labelStyle:{},
inputStyle:{} inputStyle:{}
} }
aiConfig?:{
library:string[];
title:string[];
trigger:number;
openShowType:number;
}[]
} }
export interface TableData { export interface TableData {

1
src/api/DesignForm/utils.ts

@ -106,3 +106,4 @@ export const constSetFormOptions = prefix + 'SetFormOptions' // 使用setOptions
export const constGetControlByName = prefix + 'GetControlByName' // 根据name从formData.list查找数据 export const constGetControlByName = prefix + 'GetControlByName' // 根据name从formData.list查找数据
export const constFormBtnEvent = prefix + 'FormBtnEvent' // 按钮组件事件 export const constFormBtnEvent = prefix + 'FormBtnEvent' // 按钮组件事件
export const constFormProps = prefix + 'FormProps' // 按钮组件事件 export const constFormProps = prefix + 'FormProps' // 按钮组件事件
export const constAiEffect = prefix + 'AiEffect' // 表单组件触发AI查询事件

11
src/api/doc/space.ts

@ -178,4 +178,15 @@ export function setAiChat(data: any){
method: 'post', method: 'post',
data: data data: data
}); });
}
/**
*
*/
export function getAiagentList(data?: any){
return request({
url: '/aibot/agent/list',
method: 'post',
data: data
});
} }

64
src/components/DesignForm/formControlPropertiNew.vue

@ -21,6 +21,10 @@ import {
optionsInfo, optionsInfo,
} from "@/api/DesignForm/types"; } from "@/api/DesignForm/types";
import {
getAiagentList
} from "@/api/doc/space";
import { import {
chineseToPinyin, chineseToPinyin,
customerFormGroupList, customerFormGroupList,
@ -3561,6 +3565,14 @@ const gainFormGroupList = () => {
} }
}); });
}; };
//by han2015
const gainAiagentList=()=>{
getAiagentList().then(resp=>{
aiAgentList.value=resp.data
})
};
//liwenxuan 2025 start //liwenxuan 2025 start
const scanTypes = [ const scanTypes = [
{ {
@ -3666,6 +3678,7 @@ watch(
onMounted(() => { onMounted(() => {
gainFormGroupList(); gainFormGroupList();
analysisFromUnit(props.state); analysisFromUnit(props.state);
gainAiagentList()
}); });
watch( watch(
@ -4033,24 +4046,31 @@ const addPickTracn = () => {
]; ];
} }
}; };
function delList(dex:number){
if(props.formInfo.aiConfig){
props.formInfo.aiConfig.splice(dex,1)
}
}
/** /**
@ 作者: 秦东 @ 作者: 秦东
@ 时间: 2025-04-10 08:12:21 @ 时间: 2025-04-10 08:12:21
@ 功能: 知识库 @ 功能: 知识库
*/ */
const libraryList = ref([ const aiAgentList = ref([
{ // {
label: "法律法规", // label: "",
value: 1, // value: 1,
}, // },
{ // {
label: "安全环保", // label: "",
value: 2, // value: 2,
}, // },
{ // {
label: "员工守则", // label: "",
value: 3, // value: 3,
}, // },
]); ]);
</script> </script>
<template> <template>
@ -5424,9 +5444,9 @@ const libraryList = ref([
</el-form-item> </el-form-item>
<el-form-item label="触发方式"> <el-form-item label="触发方式">
<el-radio-group v-model="item.trigger"> <el-radio-group v-model="item.trigger">
<el-radio :value="1">全部有值</el-radio> <el-radio :value="1">任一有值</el-radio>
<el-radio :value="2">任一有值</el-radio> <el-radio :value="2">半数以上有值</el-radio>
<el-radio :value="3">半数以上有值</el-radio> <el-radio :value="3">全部有值</el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item label="采用的知识库"> <el-form-item label="采用的知识库">
@ -5437,14 +5457,14 @@ const libraryList = ref([
placeholder="请选择采用的知识库" placeholder="请选择采用的知识库"
> >
<el-option <el-option
v-for="lItem in libraryList" v-for="lItem in aiAgentList"
:key="lItem.value" :key="lItem.uuid"
:label="lItem.label" :label="lItem.name"
:value="lItem.value" :value="lItem.uuid"
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="结果呈现方式"> <!-- <el-form-item label="结果呈现方式">
<el-radio-group v-model="item.openShowType"> <el-radio-group v-model="item.openShowType">
<el-radio :value="1">底部展示</el-radio> <el-radio :value="1">底部展示</el-radio>
<el-radio :value="2">消息弹出框</el-radio> <el-radio :value="2">消息弹出框</el-radio>
@ -5452,7 +5472,7 @@ const libraryList = ref([
<el-radio :value="4">消息提示</el-radio> <el-radio :value="4">消息提示</el-radio>
<el-radio :value="5">通知框</el-radio> <el-radio :value="5">通知框</el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item> -->
</el-form> </el-form>
</el-card> </el-card>

12
src/components/DesignForm/public/expand/digitpage.vue

@ -10,6 +10,7 @@ import {
constControlChange, constControlChange,
constSetFormOptions, constSetFormOptions,
constFormProps, constFormProps,
constAiEffect,
constGetControlByName, constGetControlByName,
} from "@/api/DesignForm/utils"; } from "@/api/DesignForm/utils";
import { import {
@ -40,6 +41,14 @@ const value = computed({
const config = computed(() => { const config = computed(() => {
return props.data.config || {}; return props.data.config || {};
}); });
//----------by han2015: support AI event emitting----------------
const changeEvent = inject(constAiEffect, '') as any
function onValueChange(){
changeEvent &&
changeEvent({key:props.data.name,value:props.modelValue, field:props.data.item.label})
}
//--------------------------------------
/** /**
@ 作者: 秦东 @ 作者: 秦东
@ 时间: 2024-03-01 09:07:11 @ 时间: 2024-03-01 09:07:11
@ -70,6 +79,7 @@ const getInputSlot = (key?: string) => {
} }
return control; return control;
}; };
/** /**
@ 作者: 秦东 @ 作者: 秦东
@ 时间: 2024-07-27 15:11:42 @ 时间: 2024-07-27 15:11:42
@ -128,6 +138,7 @@ const judgeIsDisabled = (key: string) => {
v-model="value" v-model="value"
:style="getFormItemInputStyle(configStyle, 2)" :style="getFormItemInputStyle(configStyle, 2)"
:input-style="getFormItemInputStyle(configStyle, 3)" :input-style="getFormItemInputStyle(configStyle, 3)"
@change="onValueChange"
oninput="value=value.replace(/[^\d.]/g, '').replace(/\.{2,}/g, '.').replace('.', '$#$').replace(/\./g, '').replace('$#$', '.').replace(/^\./g, '')" oninput="value=value.replace(/[^\d.]/g, '').replace(/\.{2,}/g, '.').replace('.', '$#$').replace(/\./g, '').replace('$#$', '.').replace(/^\./g, '')"
placeholder="请输入" placeholder="请输入"
> >
@ -138,7 +149,6 @@ const judgeIsDisabled = (key: string) => {
:disabled="judgeIsDisabled(data.name)" :disabled="judgeIsDisabled(data.name)"
:transform-option="transformOption" :transform-option="transformOption"
type="slot" type="slot"
@change="inputSlotChange"
/> />
</div> </div>
<span v-else>{{ config.append }}</span> <span v-else>{{ config.append }}</span>

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

@ -0,0 +1,177 @@
<!--
@ 作者: han2015
@ 时间: 2025-05-12 15:39:13
@ 备注: aibot组件
-->
<script lang="ts" setup>
import { doAiChat,aiChatData} from "@/api/doc/space"
import {ElText,ElInput, ButtonInstance} from "element-plus";
import { VueMarkdown } from '@crazydos/vue-markdown'
import rehypeRaw from 'rehype-raw'
import remarkGfm from 'remark-gfm'
//
const checkedModel = ref([])
const baseURL=import.meta.env.VITE_APP_BASE_API
const conversation=ref("") //uuid
const myquestion=ref('')
const controller = ref<AbortController | null>(null)
const interact_msg=ref<{ask:boolean,think:string,content:string}[]>([])
const props = withDefaults(defineProps<{
//closefunc:()=>void,
//agent:{model:boolean,name:string,uuid:string[]}
}>(),{})
//
interface message{
ask:boolean,
think:string,
content:string
}
//
interface chatRecord{
uuid:string,
agentuuid:string,
brief:string,
messages:message[]
}
/* 中断函数,供按钮调用 */
function abortFetch() {
if (controller.value) {
controller.value.abort()
controller.value = null
}
}
defineExpose({onSendParamToAI})
async function onSendParamToAI(user:string,arr:Array<{ uuids: string[]; params: { [key: string]: any } }>){
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(user,uid,ele.params)
}
}
}
async function doRequest(_user:string,uuid:string,param:any){
let mRespMsg=""
const params={
"onlineSearch":"否",
"useDataset":"否"
}
for (let item of checkedModel.value){
if(item==="onlineSearch") params.onlineSearch="是"
if(item==="useDataset") params.useDataset="是"
}
controller.value = new AbortController();
try{
const res= await doAiChat(`${baseURL}/aibot/assisted/${uuid}/chat`,{
inputs: params,
query:JSON.stringify(param),
response_mode:"streaming",
conversation_id:"",//conversation.value,
user:_user,//base64
},controller.value.signal
)
if (!res.ok) {
throw new Error(`HTTP ${res.status} ${res.statusText}`);
}
const reader = res.body!.getReader();
const decoder = new TextDecoder('utf-8');
let chunk = ''; //
while (true) {
const {done, value} = await reader.read()
if (done) break;
//
chunk += decoder.decode(value, {stream: true});
const lines = chunk.split(/\n/);
chunk = lines.pop() || ''
for (const line of lines) {
if (!line.trim()) continue; //
if (line.startsWith('data: ')) {
const data = line.slice(6);
const json = JSON.parse(data);
if(json.event==="message"){
//conversation.value=json.conversation_id
mRespMsg+=json.answer
}
}
}
}
}catch (e: any) {
if (e.name === 'AbortError') {
console.log('用户手动中断')
}
}
interact_msg.value.unshift({ask:true,think:"", content:JSON.stringify(param)})
const arr=mRespMsg.split("</think>")
if(arr.length===1){
interact_msg.value.unshift({ask:false,think:"",content:arr[0]})
}else{
//
interact_msg.value.unshift({ask:false,think:arr[0],content:arr[1]})
}
}
function resetContext(){
interact_msg.value=[]
conversation.value=""
//props.closefunc()
}
//
// 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">
{{ msg.content }}
<!-- <VueMarkdown :markdown="msg.content"></VueMarkdown> -->
</div>
</template>
</div>
</div>
</template>
<style lang="scss" scoped>
.reply_area{
width: 260px;
background: white;
overflow-y: auto;
display: flex;
flex-direction: column;
overflow-wrap:anywhere;
}
.t_ask{
margin: 5px;
align-self: end;
background-color: rgb(188 211 241);
border-radius:10px;
}
.t_resp{
margin: 5px;
align-self: start;
color: black;
background-color: rgb(222, 243, 222);
}
</style>

74
src/components/DesignForm/public/form/form.vue

@ -21,6 +21,7 @@ import {
constControlChange, constControlChange,
constFormProps, constFormProps,
appendOrRemoveStyle, appendOrRemoveStyle,
constAiEffect,
} from "@/api/DesignForm/utils"; } from "@/api/DesignForm/utils";
import formatResult from "@/utils/DesignForm/formatResult"; import formatResult from "@/utils/DesignForm/formatResult";
import formChangeValue from "@/utils/DesignForm/formChangeValue"; import formChangeValue from "@/utils/DesignForm/formChangeValue";
@ -75,6 +76,7 @@ const props = withDefaults(
labelStyle: {}, labelStyle: {},
inputStyle: {}, inputStyle: {},
}, },
aiConfig:[]
}; };
}, },
dict: () => { dict: () => {
@ -156,6 +158,13 @@ const resultDict = ref({});
const model = ref<any>({}); const model = ref<any>({});
// model // model
const getInitModel = () => { const getInitModel = () => {
if(props.formData.aiConfig?.length>0){
props.formData.aiConfig?.forEach(item=>{
currentAgent.value.push({name:"test",model:false,uuid:item.library,fields:item.title,trigger:item.trigger,params:{}})
})
}
const obj = {}; const obj = {};
forEachGetFormModel(props.formData.list, obj); forEachGetFormModel(props.formData.list, obj);
// console.log("obj===>",obj) // console.log("obj===>",obj)
@ -484,6 +493,39 @@ watch(
{ deep: true } { deep: true }
); );
//-----------------------AI setting--------------------------
//AIform
const currentAgent=ref<{model:boolean,name:string,uuid:string[],fields:string[],trigger:number,params:{[key: string]: any}}[]>([])
const aiassistRef=ref()
//AI
provide(constAiEffect, ({ key, value, field}: any) => {
//ai_envents
const ai_events: Array<{ uuids: string[]; params: { [key: string]: any } }> = [];
currentAgent.value.forEach(ag=>{
if(ag.fields.includes(key)){ //trigger: 1: 2 3
ag.params[field]=value;//keyfieldName
switch(ag.trigger){
case 2:
if(Object.keys(ag.params).length>=ag.fields.length/2){
ai_events.push({uuids:ag.uuid,params:ag.params})
}
break;
case 3:
if(Object.keys(ag.params).length==ag.fields.length){
ai_events.push({uuids:ag.uuid,params:ag.params})
}
break;
default:
ai_events.push({uuids:ag.uuid,params:ag.params})
}
}
})
if(ai_events.length>0){
aiassistRef.value.onSendParamToAI(props.formData.form.formName,ai_events)
}
})
//------------------------------------------------------------
// tProp // tProp
provide(constControlChange, ({ key, value, data, tProp, type, attribute }: any) => { provide(constControlChange, ({ key, value, data, tProp, type, attribute }: any) => {
// console.log("----------1--------->", key); // console.log("----------1--------->", key);
@ -493,6 +535,7 @@ provide(constControlChange, ({ key, value, data, tProp, type, attribute }: any)
// console.log("----------5--------->", type); // console.log("----------5--------->", type);
// console.log("----------6--------->", attribute); // console.log("----------6--------->", attribute);
// console.log("----------11--------->", model.value); // console.log("----------11--------->", model.value);
let fieldVal = {}; let fieldVal = {};
for (let i in model.value) { for (let i in model.value) {
if (i == key) { if (i == key) {
@ -518,7 +561,6 @@ provide(constControlChange, ({ key, value, data, tProp, type, attribute }: any)
let newFormConfig = props.formData.config.groupKey; let newFormConfig = props.formData.config.groupKey;
let odlHideField = props.formData.config.hideField; let odlHideField = props.formData.config.hideField;
delete props.formData.config.groupKey; delete props.formData.config.groupKey;
console.log(props.formData);
delete props.formData.config.hideField; delete props.formData.config.hideField;
let sendInfo = { let sendInfo = {
fieldKey: key, fieldKey: key,
@ -556,13 +598,11 @@ provide(constControlChange, ({ key, value, data, tProp, type, attribute }: any)
} }
props.formData.config.groupKey = newFormConfig; props.formData.config.groupKey = newFormConfig;
props.formData.config.hideField = odlHideField; props.formData.config.hideField = odlHideField;
console.log(props.formData);
}); });
}) })
.finally(() => { .finally(() => {
props.formData.config.groupKey = newFormConfig; props.formData.config.groupKey = newFormConfig;
props.formData.config.hideField = odlHideField; props.formData.config.hideField = odlHideField;
console.log(props.formData);
}); });
} }
// }) // })
@ -715,8 +755,6 @@ function showOrHide(data: any) {
//console.log(leftOperatorsAndRight) //console.log(leftOperatorsAndRight)
//console.log(data) //console.log(data)
if (data.name == leftArr[2]) { if (data.name == leftArr[2]) {
console.log("ghasdhasdfhhsadhasd");
console.log(props.formData.list[i].name);
nextTick(() => { nextTick(() => {
console.log(model.value[leftArr[2]]); console.log(model.value[leftArr[2]]);
if (leftOperatorsAndRight.operator == "==") { if (leftOperatorsAndRight.operator == "==") {
@ -2145,7 +2183,8 @@ const webPage = computed({
<slot></slot> <slot></slot>
</el-form> </el-form>
</div> </div>
<div v-else v-loading="loading" class="pcBox"> <div v-else v-loading="loading" class="pcBox" :class="{boxAI:type!=5 && currentAgent.length>0}">
<Aiassist ref="aiassistRef" v-if="type!=5 && currentAgent.length>0" :agent="currentAgent"></Aiassist>
<el-form <el-form
v-bind="formData.form" v-bind="formData.form"
ref="ruleForm" ref="ruleForm"
@ -2168,6 +2207,8 @@ const webPage = computed({
<slot></slot> <slot></slot>
</el-form> </el-form>
</div> </div>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
.webBox { .webBox {
@ -2188,4 +2229,25 @@ const webPage = computed({
overflow-x: hidden; overflow-x: hidden;
position: relative; position: relative;
} }
.boxAI{
display: grid;
grid-template-columns:1fr 4fr;
}
.t_ask{
align-self: end;
line-height: 34px;
background-color: rgb(188 211 241);
padding: 0 30px;
border-radius:10px;
margin: 15px;
}
.t_resp{
align-self: start;
line-height: 30px;
margin: 20px 33px;
font-size: 18px;
color: black;
}
</style> </style>

15
src/components/DesignForm/public/form/formItem.vue

@ -16,6 +16,7 @@ import {
constControlChange, constControlChange,
constSetFormOptions, constSetFormOptions,
constFormProps, constFormProps,
constAiEffect,
constGetControlByName, constGetControlByName,
} from "@/api/DesignForm/utils"; } from "@/api/DesignForm/utils";
import validate from "@/api/DesignForm/validate"; import validate from "@/api/DesignForm/validate";
@ -122,6 +123,17 @@ const updateModel = (val: any) => {
attribute: controlAttribute, attribute: controlAttribute,
}); });
}; };
//----------by han2015: support AI event emitting----------------
//changeEventchangeEventfieldChange
const fieldChangeEnt = inject(constAiEffect, '') as any
function onValueChange(_type:string){
if(_type=="password") return;
fieldChangeEnt &&
fieldChangeEnt({key:props.data.name,value:props.modelValue, field:props.data.item.label})
}
//--------------------------------------
const value = computed({ const value = computed({
get() { get() {
if (props.tProp) { if (props.tProp) {
@ -1222,10 +1234,11 @@ const diGuiJilian = (val: any, options: any[]) => {
:style="getFormItemInputStyle(configStyle, 2)" :style="getFormItemInputStyle(configStyle, 2)"
:input-style="getFormItemInputStyle(configStyle, 3)" :input-style="getFormItemInputStyle(configStyle, 3)"
v-if="['input', 'password'].includes(data.type)" v-if="['input', 'password'].includes(data.type)"
@change="onValueChange(data.type)"
:placeholder=" :placeholder="
data.control.placeholder data.control.placeholder
? data.control.placeholder ? data.control.placeholder
: '请输入' + getLabel(data.item) : '请输入>>>' + getLabel(data.item)
" "
> >
<template #prepend v-if="config.prepend"> <template #prepend v-if="config.prepend">

Loading…
Cancel
Save