|
|
|
@ -4,7 +4,12 @@ |
|
|
|
@ 备注: 预览页面 |
|
|
|
--> |
|
|
|
<script lang='ts' setup> |
|
|
|
import { formStruct } from '@/api/DesignForm/types'; |
|
|
|
import { constAiEffect } from '@/api/DesignForm/utils'; |
|
|
|
import { nodePoweInfo } from '@/api/taskapi/types'; |
|
|
|
import FormDesign from '@/components/DesignForm/public/form/form.vue' |
|
|
|
import FlowStep from "@/views/sysworkflow/lowcodepage/pageFlow/flowStep.vue"; |
|
|
|
import AiPage from "@/views/sysworkflow/lowcodepage/pageFlow/aiPage.vue"; |
|
|
|
const props = defineProps({ |
|
|
|
state:{ |
|
|
|
type:Object, |
|
|
|
@ -12,6 +17,14 @@ const props = defineProps({ |
|
|
|
return {} |
|
|
|
} |
|
|
|
}, |
|
|
|
versiontitle: { |
|
|
|
type: String, |
|
|
|
default: "", |
|
|
|
}, |
|
|
|
drawerwith: { |
|
|
|
type: Number, |
|
|
|
default: 900 |
|
|
|
}, |
|
|
|
isWeb:{ |
|
|
|
type:Boolean, |
|
|
|
default(){ |
|
|
|
@ -21,7 +34,7 @@ const props = defineProps({ |
|
|
|
}); |
|
|
|
const emits = defineEmits<{ |
|
|
|
(e: 'update:state', val: any): void |
|
|
|
(e: 'clickClose'): void |
|
|
|
(e: 'clickClose', val: boolean): void |
|
|
|
}>() |
|
|
|
const state = computed({ |
|
|
|
get() { |
|
|
|
@ -56,39 +69,305 @@ const previewSubmit = () => { |
|
|
|
@ 时间: 2024-05-15 13:16:09 |
|
|
|
@ 功能: 关闭预览 |
|
|
|
*/ |
|
|
|
const clickClose = () => { |
|
|
|
const clickClosePick = () => { |
|
|
|
// console.log("关闭预览") |
|
|
|
emits('clickClose', false) |
|
|
|
} |
|
|
|
const formType = ref(1) |
|
|
|
const drawTitle = computed(() => state.value.formData.form.formName) |
|
|
|
const drawLoading = ref(false) |
|
|
|
const aiConfigArea =ref(false) |
|
|
|
const isFlowTable = ref(false); //判断是不是流程表单 |
|
|
|
const currterNodePower = ref<nodePoweInfo[]>([]) |
|
|
|
const nodeKey = ref<string>(""); |
|
|
|
const flowLoading = ref(false); //loading |
|
|
|
const flowMap = ref<any[]>(); //工作流 |
|
|
|
const nextStep = ref<number>(0); |
|
|
|
const drawBodyWidth = ref(props.drawerwith) |
|
|
|
//-----------------------AI setting-------------------------- |
|
|
|
//当前AI智能体,根据form表单的配置来初始化 |
|
|
|
//params 主表字段参数 subparams子表字段参数,子表触发时需要清空 ; rowdex:表示子表的第几条数据,没有的话说明不是子表数据 |
|
|
|
const currentAgent = ref< |
|
|
|
{ |
|
|
|
model: boolean; |
|
|
|
name: string; |
|
|
|
rowdex:number, |
|
|
|
uuid: string[]; |
|
|
|
fields: string[]; |
|
|
|
trigger: number; |
|
|
|
params: { [key: string]: any }; |
|
|
|
subparams:{[key: string]: any}[]; |
|
|
|
}[] |
|
|
|
>([]); |
|
|
|
const aiassistRef = ref(); |
|
|
|
//触发AI查询事件 |
|
|
|
provide(constAiEffect, ({ key, value, field,rowdex}: 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:全部 |
|
|
|
if (rowdex!=null){//子表操作 |
|
|
|
ag.rowdex=rowdex //更新智能体的rowdex |
|
|
|
if(rowdex>=ag.subparams.length){ |
|
|
|
ag.subparams.push({[field]:value}) |
|
|
|
}else{ |
|
|
|
ag.subparams[rowdex][field]=value |
|
|
|
} |
|
|
|
}else{ //主表操作, 直接加入params种 |
|
|
|
ag.params[field]=value; //这个地方把key换成fieldName |
|
|
|
} |
|
|
|
let mergedObj; |
|
|
|
if(ag.subparams.length>0){ |
|
|
|
mergedObj = Object.assign({}, ag.params, ag.subparams[ag.rowdex]); //合并子表和主表 |
|
|
|
}else{ |
|
|
|
mergedObj = ag.params |
|
|
|
} |
|
|
|
switch(ag.trigger){ |
|
|
|
case 2: |
|
|
|
if(Object.keys(mergedObj).length>=ag.fields.length/2){ |
|
|
|
ai_events.push({uuids:ag.uuid,params:mergedObj }) |
|
|
|
} |
|
|
|
break; |
|
|
|
case 3: |
|
|
|
if(Object.keys(mergedObj).length==ag.fields.length){ |
|
|
|
ai_events.push({uuids:ag.uuid,params:mergedObj}) |
|
|
|
} |
|
|
|
break; |
|
|
|
default: |
|
|
|
ai_events.push({uuids:ag.uuid,params:mergedObj}) |
|
|
|
} |
|
|
|
} |
|
|
|
}) |
|
|
|
if(ai_events.length>0){ |
|
|
|
aiassistRef.value.onSendParamToAI(ai_events) |
|
|
|
} |
|
|
|
}) |
|
|
|
|
|
|
|
provide('flowNodePower', currterNodePower) |
|
|
|
provide('currentNodeKey', nodeKey) |
|
|
|
|
|
|
|
onMounted(()=>{ |
|
|
|
if(state.value.formData&&state.value.formData.aiConfig&&state.value.formData.aiConfig.length>0){ |
|
|
|
aiConfigArea.value=true |
|
|
|
drawBodyWidth.value = 1080 |
|
|
|
}else{ |
|
|
|
drawBodyWidth.value = 780 |
|
|
|
} |
|
|
|
}) |
|
|
|
</script> |
|
|
|
<template> |
|
|
|
<div> |
|
|
|
|
|
|
|
|
|
|
|
<el-drawer |
|
|
|
v-model="state.previewVisible" |
|
|
|
title="预览" |
|
|
|
:append-to-body="true" |
|
|
|
size="1170" |
|
|
|
:size="drawBodyWidth" |
|
|
|
:with-header="false" |
|
|
|
> |
|
|
|
<FormDesign |
|
|
|
ref="previewForm" |
|
|
|
:type="1" |
|
|
|
:form-data="state.formDataPreview" |
|
|
|
:dict="state.formDict" |
|
|
|
:is-web="props.isWeb" |
|
|
|
/> |
|
|
|
<template #footer> |
|
|
|
<div v-loading="drawLoading" :class="aiConfigArea&&isFlowTable?'drawBody treePage':(aiConfigArea&&!isFlowTable)?'drawBody twoPageAi':(!aiConfigArea&&isFlowTable)?'drawBody twoPageFlow':'drawBody'"> |
|
|
|
<AiPage |
|
|
|
v-if="state.type != 5 && aiConfigArea" |
|
|
|
ref="aiassistRef" |
|
|
|
:agent="currentAgent" |
|
|
|
/> |
|
|
|
<AppForm |
|
|
|
ref="formEl" |
|
|
|
:drawTitle="drawTitle" |
|
|
|
:numrun="formType" |
|
|
|
:form-data="state.formData" |
|
|
|
:type="formType" |
|
|
|
:dict="state.dict" |
|
|
|
:close-app-submit="clickClosePick" |
|
|
|
/> |
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<!-- <template #footer> |
|
|
|
<div class="dialog-footer"> |
|
|
|
<el-button size="small" type="primary" @click="previewSubmit"> |
|
|
|
提交 |
|
|
|
</el-button> |
|
|
|
<el-button size="small" @click="clickClose"> |
|
|
|
<el-button size="small" @click="clickClosePick"> |
|
|
|
取消 |
|
|
|
</el-button> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
</template> --> |
|
|
|
</el-drawer> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
<style lang='scss' scoped> |
|
|
|
.drawerClass{ |
|
|
|
:deep .el-drawer__header{ |
|
|
|
border-bottom: 1px solid #ECECEC; |
|
|
|
} |
|
|
|
} |
|
|
|
.drawHeader { |
|
|
|
width: 100%; |
|
|
|
display: flex; |
|
|
|
justify-content: space-between; |
|
|
|
align-items: center; |
|
|
|
} |
|
|
|
.drawBody{ |
|
|
|
width: 100%; |
|
|
|
height: 100%; |
|
|
|
padding: 10px 10px; |
|
|
|
:deep .el-card{ |
|
|
|
border-radius: 15px; |
|
|
|
} |
|
|
|
:deep .el-card__header{ |
|
|
|
padding: 15px 15px; |
|
|
|
} |
|
|
|
:deep .el-card__body{ |
|
|
|
padding: 0; |
|
|
|
} |
|
|
|
:deep .el-card__footer{ |
|
|
|
padding: 10px 10px; |
|
|
|
} |
|
|
|
} |
|
|
|
.twoPageAi{ |
|
|
|
display: grid; |
|
|
|
grid-template-columns: minmax(150px, 300px) 1fr; /* 左右最小150px,最大250px,中间自适应 */ |
|
|
|
grid-template-rows: auto; |
|
|
|
gap: 10px; |
|
|
|
max-width: 100%; |
|
|
|
margin: 0 auto; |
|
|
|
} |
|
|
|
.twoPageFlow{ |
|
|
|
display: grid; |
|
|
|
grid-template-columns: 1fr minmax(150px, 300px); /* 左右最小150px,最大250px,中间自适应 */ |
|
|
|
grid-template-rows: auto; |
|
|
|
gap: 10px; |
|
|
|
max-width: 100%; |
|
|
|
margin: 0 auto; |
|
|
|
} |
|
|
|
.treePage{ |
|
|
|
display: grid; |
|
|
|
grid-template-columns: minmax(150px, 300px) 1fr minmax(150px, 300px); /* 左右最小150px,最大250px,中间自适应 */ |
|
|
|
grid-template-rows: auto; |
|
|
|
gap: 10px; |
|
|
|
max-width: 100%; |
|
|
|
margin: 0 auto; |
|
|
|
} |
|
|
|
.svgBox{ |
|
|
|
background: linear-gradient(135deg, #0020C2, #4d6cff); |
|
|
|
color: white; |
|
|
|
width: 40px; |
|
|
|
height: 40px; |
|
|
|
border-radius: 50%; |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
justify-content: center; |
|
|
|
font-size: 1.2rem; |
|
|
|
} |
|
|
|
.card-header{ |
|
|
|
font-size: 1.4rem; |
|
|
|
font-weight: 700; |
|
|
|
color: #0020C2; |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
gap: 10px; |
|
|
|
} |
|
|
|
.scroBox{ |
|
|
|
padding: 10px 15px; |
|
|
|
height: calc(100vh - 200px); |
|
|
|
} |
|
|
|
.formBody{ |
|
|
|
width: 100%; |
|
|
|
overflow-x: auto; |
|
|
|
} |
|
|
|
.flowBody{ |
|
|
|
padding: 10px 15px; |
|
|
|
height: calc(100vh - 260px); |
|
|
|
} |
|
|
|
|
|
|
|
.bootemWorkFlow{ |
|
|
|
width: 100%; |
|
|
|
text-align: center; |
|
|
|
.bootemWorkFlowBut{ |
|
|
|
width: 100%; |
|
|
|
padding: 10px 0; |
|
|
|
text-align: center; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.btn { |
|
|
|
padding: 14px 16px; |
|
|
|
border-radius: 10px; |
|
|
|
font-weight: 600; |
|
|
|
font-size: 1rem; |
|
|
|
cursor: pointer; |
|
|
|
transition: all 0.3s; |
|
|
|
border: none; |
|
|
|
} |
|
|
|
.btn:hover { |
|
|
|
transform: translateY(-2px); |
|
|
|
box-shadow: 0 5px 15px rgba(0, 32, 194, 0.15); |
|
|
|
} |
|
|
|
.approve-btn { |
|
|
|
background: linear-gradient(135deg, #00cc66, #33dd88); |
|
|
|
color: white; |
|
|
|
} |
|
|
|
.reject-btn { |
|
|
|
background: linear-gradient(135deg, #ff3366, #ff5588); |
|
|
|
color: white; |
|
|
|
} |
|
|
|
|
|
|
|
.bootemAi{ |
|
|
|
display: grid; |
|
|
|
grid-template-columns: 1fr 50px; /* 左右最小150px,最大250px,中间自适应 */ |
|
|
|
grid-template-rows: auto; |
|
|
|
gap: 10px; |
|
|
|
max-width: 100%; |
|
|
|
margin: 0 auto; |
|
|
|
:deep .el-input__wrapper{ |
|
|
|
border-radius: 10px; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.ai-send-btn { |
|
|
|
background: linear-gradient(135deg, #0020C2, #4d6cff); |
|
|
|
color: white; |
|
|
|
border: none; |
|
|
|
width: 46px; |
|
|
|
border-radius: 10px; |
|
|
|
cursor: pointer; |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
justify-content: center; |
|
|
|
transition: all 0.3s; |
|
|
|
} |
|
|
|
|
|
|
|
.ai-send-btn:hover { |
|
|
|
background: linear-gradient(135deg, #0019a0, #3a5aff); |
|
|
|
transform: translateY(-2px); |
|
|
|
} |
|
|
|
.ai-conversation { |
|
|
|
flex: 1; |
|
|
|
display: flex; |
|
|
|
flex-direction: column; |
|
|
|
gap: 15px; |
|
|
|
margin-bottom: 20px; |
|
|
|
} |
|
|
|
.message { |
|
|
|
padding: 12px 16px; |
|
|
|
border-radius: 12px; |
|
|
|
max-width: 90%; |
|
|
|
line-height: 1.5; |
|
|
|
} |
|
|
|
|
|
|
|
.user-message { |
|
|
|
background: #eef2ff; |
|
|
|
align-self: flex-end; |
|
|
|
border-top-right-radius: 4px; |
|
|
|
border: 1px solid rgba(0, 32, 194, 0.2); |
|
|
|
} |
|
|
|
|
|
|
|
.ai-message { |
|
|
|
background: linear-gradient(to right, #f0f5ff, #ffffff); |
|
|
|
align-self: flex-start; |
|
|
|
border-top-left-radius: 4px; |
|
|
|
border: 1px solid rgba(0, 32, 194, 0.1); |
|
|
|
} |
|
|
|
</style> |
|
|
|
|