middleground_code_v2/src/views/LinkUp/compoment/addDialogChunk.vue

933 lines
26 KiB
Vue
Raw Normal View History

2025-05-30 10:04:55 +08:00
<template>
<div class="addDialogChunk">
<base-right-dialog
@handleClose="examineHandleClose"
:dialogVisible="examineOperateDialog"
size="100%"
:appendBody="true"
:loading="sceneLoading"
:footerShow="true"
:submitShow="true"
@handleConfirmClick="handleConfirmClick"
:submitTitle="'发布'"
:submitIcon="'el-icon-upload2'"
:title="sceneName"
>
<template #operateTitle>
<img
style="width: 15px; height: 15px; margin-left: 10px; cursor: pointer"
src="../images/edit.svg"
@click="editSceneName"
/>
</template>
<div class="rightDialogClass_main drawContent" style="background: #fff">
<!-- 画布 -->
<div class="drawCanvas" v-if="drawShowList.length > 0">
<div
class="drawItem"
v-for="(ele, index) in drawShowList"
:key="ele.value"
>
<div class="title">{{ ele.title }}</div>
<div
@click="selectDrawItem(index)"
class="drawBox"
:class="{ active: index == drawSelectIndex }"
>
<template v-if="index == 0">
<div class="img">
<img src="../images/pingtai.svg" v-if="triggerMode == 2" />
<img
src="../images/naozhong.svg"
v-else-if="triggerMode == 1"
/>
<img src="../images/api.svg" v-else-if="triggerMode == 4" />
<img src="../images/point.svg" v-else-if="triggerMode == 3" />
</div>
<div style="width: calc(100% - 60px)">
<div class="actionName">
{{ index + 1 + "." + ele.actionName }}
</div>
<div
class="content DescribeContent"
v-if="!ele.options.taskType"
>
{{ ele.content }}
</div>
<div class="content" v-else>
{{ getTimeDivide(ele.options.taskType) }}
</div>
</div>
</template>
<template v-else>
<div
:class="
ele.options && ele.options.iconUrl ? 'iconStyle' : 'img'
"
>
<img
v-if="ele.options && ele.options.iconUrl"
:src="
ele.options.iconUrl
? ele.options.iconUrl.split('/wwwroot')[1]
: ''
"
/>
<img v-else src="../images/huaO.svg" />
</div>
<div style="width: calc(100% - 60px)">
<div class="actionName" v-if="!ele.options.appName">
{{ index + 1 + "." + ele.actionName }}
</div>
<div
class="actionName"
style="display: flex; align-items: center"
v-else
>
{{ index + 1 + "." + ele.options.appName }}
<img
class="acionImg"
v-if="
ele.options.resourcesType == 1 ||
ele.options.resourcesType == '1' ||
ele.options.resourcesType == 'API接口'
"
src="../images/apiison.svg"
alt=""
/>
<img
class="acionImg"
v-else-if="
ele.options.resourcesType == 2 ||
ele.options.resourcesType == '2' ||
ele.options.resourcesType == '插件'
"
src="../images/chajian.svg"
alt=""
/>
<img
v-else-if="
ele.options.resourcesType == 3 ||
ele.options.resourcesType == '3' ||
ele.options.resourcesType == '数据源'
"
class="acionImg"
src="../images/shujuyuan.svg"
alt=""
/>
</div>
<div
class="content DescribeContent"
v-if="ele.options.stepDescribe"
>
{{ ele.options.stepDescribe }}
</div>
<div class="content" v-else>{{ ele.content }}</div>
</div>
</template>
<div
@click.stop="delDrawItem(ele, index)"
v-if="index != 0"
class="del"
>
<img src="../images/close.svg" />
</div>
</div>
<div class="line-wrapper" v-if="index != drawShowList.length - 1">
<div class="line"></div>
<img
src="../images/addBtn.svg"
@click.stop="insertDrawItem(ele, index)"
/>
</div>
</div>
<div @click="addDrwaItem" class="drawItem drawItemBtn">
添加新步骤
</div>
</div>
<!-- 操作区 -->
<div class="drawAction" v-if="drawSelectIndex == 0">
<el-tabs v-model="activeTabName">
<el-tab-pane label="1. 选择操作" name="选择操作">
<div
class="currentDrawBox"
style="padding: 10px"
v-if="drawShowList.length > 0"
>
<div class="drawimg">
<img src="../images/pingtai.svg" v-if="triggerMode == 2" />
<img
src="../images/naozhong.svg"
v-else-if="triggerMode == 1"
/>
<img src="../images/api.svg" v-else-if="triggerMode == 4" />
<img src="../images/point.svg" v-else-if="triggerMode == 3" />
</div>
<div style="width: calc(100% - 60px)">
<div class="actionName">
{{ 1 + "." + drawShowList[0].actionName }}
</div>
<div class="content" v-if="!drawShowList[0].options.taskType">
{{ drawShowList[0].content }}
</div>
<div class="content" v-else>
{{ getTimeDivide(drawShowList[0].options.taskType) }}
</div>
</div>
</div>
<div class="timeWrap">
<template v-for="(item, index) in timeDivide">
<div
@click="handleTimeItem(item, index)"
:class="{ activTimeItem: activTimeIndex == item.id }"
class="timeItem"
>
<div class="imgBox">
<img src="../images/shandian.svg" />
</div>
<div>
<div class="title">{{ item.title }}</div>
<div class="content">{{ item.content }}</div>
</div>
</div>
</template>
</div>
</el-tab-pane>
<el-tab-pane label="2. 配置" name="配置">
<div
class="currentDrawBox"
style="padding: 10px"
v-if="drawShowList.length > 0"
>
<div class="drawimg">
<img src="../images/pingtai.svg" v-if="triggerMode == 2" />
<img
src="../images/naozhong.svg"
v-else-if="triggerMode == 1"
/>
<img src="../images/api.svg" v-else-if="triggerMode == 4" />
<img src="../images/point.svg" v-else-if="triggerMode == 3" />
</div>
<div style="width: calc(100% - 60px)">
<div class="actionName">
{{ 1 + "." + drawShowList[0].actionName }}
</div>
<div class="content" v-if="!drawShowList[0].options.taskType">
{{ drawShowList[0].content }}
</div>
<div class="content" v-else>
{{ getTimeDivide(drawShowList[0].options.taskType) }}
</div>
</div>
</div>
<div class="crontabBox">
<div class="crontabBoxTitle">cron表达式</div>
<FishCrontab
ref="fishCrontab"
class="crontab"
@fill="crontabFill"
:expression="expression"
:fiveTimes="false"
></FishCrontab>
</div>
</el-tab-pane>
</el-tabs>
</div>
</div>
</base-right-dialog>
<editSence ref="editSence" @handleConfirmClick="updateTitle"></editSence>
</div>
</template>
<script>
// 导入编辑场景组件
import baseRightDialog from "@/components/base/baseRightDialog/index.vue";
import editSence from "./editSence.vue";
import { authApi } from "@/api/apis/auth";
// 导入步骤添加和使用的常量
import { stepAdd, stepUse, timeDivide } from "./constant";
// 导入 cron 表达式组件
import FishCrontab from "fish-crontab";
export default {
components: {
editSence,
baseRightDialog,
FishCrontab,
},
data() {
return {
examineOperateDialog: false, //判断是都打开弹窗
sceneLoading: false, //遮照
sceneName: "", //场景名称
sceneID: "", //场景ID
// 画布列表,对应右侧操作区域
drawShowList: [],
drawSelectIndex: 0, // 当前选中的画布索引
// 应用列表
appList: [],
appCodeOrName: "", // 应用搜索关键字
appActivIndex: "", // 当前选中的应用 ID
//
timeDivide:timeDivide,
activeTabName: "选择操作", // 当步骤为1时 显示的操作栏
activTimeIndex: "", // 当前选择操作的类型
expression: "",
};
},
methods: {
/**
* 打开弹窗
* @param {string} sceneID 场景 ID
* @param {string} sceneName 场景名称
* @param {string} type 操作类型
* @param {number} triggerMode 触发模式
*/
openDialog(sceneID, sceneName, type, triggerMode) {
// 更新场景 ID
this.sceneID = sceneID;
// 更新场景类型
this.sceneType = type;
// 更新场景名称
this.sceneName = sceneName;
// 更新触发模式
this.triggerMode = triggerMode;
// 显示审核操作弹窗
this.examineOperateDialog = true;
// 显示场景加载状态
this.sceneLoading = true;
// 5 秒后隐藏场景加载状态
setTimeout(() => {
this.sceneLoading = false;
}, 5000);
if (type === "add") {
// 新增时生成第一步
let params = {
flowId: this.sceneID,
step: 1,
stepType: 2,
};
this.SaveSceneStepData(params, "first");
}
},
/**
* 新增实时修改场景步骤基本信息
* @param {Object} params 请求参数
* @param {string} type 操作类型
*/
async SaveSceneStepData(params, type, insertIndex) {
let res = await authApi(
"sysFlowStepService",
"",
"saveFlowStep",
"",
params
);
// 隐藏场景加载状态
this.sceneLoading = false;
if (res.status == "200") {
// 新增时
if (type === "first") {
let obj = [
{
...stepAdd,
options: {
// 步骤 id
stepID: res.attribute.id,
step: 1,
stepType: 2, // 步骤类型1、触发方式 2、应用 3、 数据集 4、条件
},
},
];
if (this.triggerMode === 2) {
obj[0].actionName = "平台触发配置";
} else if (this.triggerMode === 1) {
obj[0].actionName = "定时器配置";
} else if (this.triggerMode === 4) {
obj[0].actionName = "接口配置";
obj[0].content = "请输入 IP 白名单";
} else if (this.triggerMode === 3) {
obj[0].actionName = "手动触发";
}
// 更新画布列表
this.drawShowList = obj;
// 在下一个 DOM 更新周期后执行操作
this.$nextTick(() => {
// 选中第一个步骤
this.drawSelectIndex = 0;
this.selectDrawItem(this.drawSelectIndex);
// 获取应用列表
this.getAppList();
});
}
// 手动新增时
if (type === "add") {
// 将新步骤添加到画布列表
this.drawShowList.push({
...stepUse,
options: {
// 步骤 id
stepID: res.attribute.id,
},
});
// 在下一个 DOM 更新周期后执行操作
this.$nextTick(() => {
// 选中当前新增的步骤
this.drawSelectIndex = this.drawShowList.length - 1;
this.selectDrawItem(this.drawSelectIndex);
});
}
if (type == "insert") {
this.drawShowList.splice(insertIndex + 1, 0, {
...stepUse,
options: {
// 步骤 id
stepID: res.attribute.id,
},
});
// 在下一个 DOM 更新周期后执行操作
this.$nextTick(() => {
// 选中当前新增的步骤
this.drawSelectIndex = insertIndex + 1;
this.selectDrawItem(this.drawSelectIndex);
});
}
}
},
/**
* 手动新增场景步骤
* @param {string} type 操作类型
*/
addDrwaItem(type) {
// 新增步骤的参数
let params = {
flowId: this.sceneID,
step: this.drawShowList.length + 1,
stepType: 2,
};
// 保存场景步骤数据
this.SaveSceneStepData(params, "add");
},
/**
* 切换步骤时
* @param {number} index 步骤索引
*/
selectDrawItem(index) {
// 更新当前选中的步骤索引
this.drawSelectIndex = index;
},
/**
* 删除场景步骤
* @param {Object} ele 步骤数据
* @param {number} index 步骤索引
*/
delDrawItem(ele, index) {
// 获取步骤 ID
let stepID = ele.options.stepID || null;
if (!stepID) {
this.$vmNews("删除失败步骤ID丢失请联系管理员处理");
return;
}
// 弹出确认删除对话框
this.$confirm("确认删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(async () => {
if (stepID) {
let res = await authApi(
"sysFlowStepService",
"",
"saveFlowStep",
"",
{
id: stepID,
}
);
if (res.status == "200") {
// 提示删除成功
this.$vmNews("删除成功", "success");
// 从画布列表中删除该步骤
this.drawShowList.splice(index, 1);
if (this.drawSelectIndex === index) {
// 选中第一个步骤
this.drawSelectIndex = 0;
this.selectDrawItem(this.drawSelectIndex);
} else if (this.drawSelectIndex >= this.drawShowList.length) {
// 选中最后一个步骤
this.drawSelectIndex = this.drawShowList.length - 1;
this.selectDrawItem(this.drawSelectIndex);
}
}
} else {
// 提示删除成功
this.$vmNews("删除成功", "success");
// 从画布列表中删除该步骤
this.drawShowList.splice(index, 1);
if (this.drawSelectIndex === index) {
// 选中第一个步骤
this.drawSelectIndex = 0;
this.selectDrawItem(this.drawSelectIndex);
} else if (this.drawSelectIndex >= this.drawShowList.length) {
// 选中最后一个步骤
this.drawSelectIndex = this.drawShowList.length - 1;
this.selectDrawItem(this.drawSelectIndex);
}
}
})
.catch(() => {});
},
/**
* 插入场景步骤
* @param {any} value 标签页值
*/
insertDrawItem(ele, index) {
let params = {
flowId: this.sceneID,
step: index + 1,
stepType: 2,
};
// 保存场景步骤数据
this.SaveSceneStepData(params, "insert", index);
},
/**
* cron 表达式点击确定时时间插件回调
* @param {string} value cron 表达式的值
*/
crontabFill(value) {
// 更新 cron 表达式
this.expression = value;
// 更新当前步骤的任务值
this.drawShowList[this.drawSelectIndex].options.taskValue = value;
},
/**
* 获取应用列表
*/
async getAppList() {
// 获取应用列表的参数
let params = {
appName: this.appCodeOrName,
};
// 调用获取应用列表的 API
let res = await authApi(
"sysApplicationService",
"",
"queryEntity",
"",
params
);
// 隐藏搜索遮罩
this.drawMask = false;
if (res.status == "200") {
// 更新应用列表
this.appList = res.attribute;
}
},
/**
* 根据任务类型获取时间划分的标题
* @param {number} taskType 任务类型
* @returns {string} 时间划分的标题
*/
getTimeDivide(taskType) {
if (taskType === 1) {
return "秒级";
} else if (taskType === 2) {
return "分钟级";
} else if (taskType === 3) {
return "小时级";
} else if (taskType === 4) {
return "天级";
}
},
/**
* 编辑场景名称
*/
editSceneName() {
// 编辑场景名称的参数
let row = {
flowId: this.sceneID,
};
// 在下一个 DOM 更新周期后打开编辑场景名称的弹窗
this.$nextTick(() => {
this.$refs.editSence.openDialog(row, "edit");
});
},
/**
* 更新场景名称
* @param {string} sceneID 场景 ID
* @param {Object} res 响应数据
*/
updateTitle(sceneID, res) {
// 更新场景名称
this.sceneName = res.sceneName;
this.title = res.sceneName;
// 更新触发模式
this.triggerMode = res.triggerMode;
if (this.triggerMode === 2) {
this.drawShowList[this.drawSelectIndex].actionName = "平台触发配置";
} else if (this.triggerMode === 1) {
this.drawShowList[this.drawSelectIndex].actionName = "定时器配置";
} else if (this.triggerMode === 4) {
this.drawShowList[this.drawSelectIndex].actionName = "接口配置";
} else if (this.triggerMode === 3) {
this.drawShowList[this.drawSelectIndex].actionName = "手动触发";
}
},
// 场景步骤---【确定】
handleConfirmClick() {
this.examineHandleClose();
},
// 关闭场景步骤弹窗
examineHandleClose() {
// 触发关闭事件
this.$emit("examineHandleClose");
this.examineOperateDialog = false;
this.sceneName = "";
},
},
};
</script>
<style scoped lang="scss">
.drawContent {
width: 100%;
height: 100%;
display: flex;
.drawCanvas {
width: 40%;
height: 100%;
background: url("../images/background.png") no-repeat;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-ms-flex-direction: column;
flex-direction: column;
-ms-flex-pack: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
overflow-y: auto;
padding: 50px 0;
.drawItem {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.title {
font-weight: 400;
font-size: 14px;
color: #333333;
margin-bottom: 5px;
}
.drawBox {
width: 300px;
height: 58px;
background: #ffffff;
border-radius: 4px;
border: 1px solid #dbdde1;
font-weight: 400;
font-size: 14px;
color: #333333;
display: flex;
// justify-content: center;
align-items: center;
position: relative;
.img {
margin: 0 10px;
width: 30px;
height: 30px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid #f18709;
img {
width: 60%;
height: 60%;
}
}
.iconStyle {
margin: 0 10px;
width: 30px;
height: 30px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
img {
width: 100%;
height: 100%;
border-radius: 50%;
}
}
.actionName {
font-weight: 400;
font-size: 14px;
color: #333333;
}
.content {
font-weight: 500;
font-size: 14px;
color: #333333;
}
}
.drawBox:hover {
background: #f2fcff;
border: 1px solid #1478f5;
}
.del {
position: absolute;
right: -5px;
top: -3px;
cursor: pointer;
width: 16px;
height: 16px;
background: #fff;
img {
width: 100%;
height: 100%;
}
}
.active {
background: #f2fcff;
border: 1px solid #1478f5;
}
.line-wrapper {
width: 100%;
display: flex;
justify-content: center;
position: relative;
img {
position: absolute;
cursor: pointer;
width: 20px;
height: 20px;
top: 33px;
left: 140px;
display: none;
}
}
.line-wrapper:hover img {
display: block;
}
.line {
width: 1px;
height: 60px;
border: 1px solid #dbdde1;
margin: 10px 0;
}
}
}
.drawAction {
width: 60%;
height: 100%;
background-color: #f5f5f5;
position: relative;
.nextButton {
position: absolute;
right: 15px;
top: 8px;
color: #1477f3;
cursor: pointer;
font-size: 14px;
}
::v-deep .el-tabs__header {
margin: 0;
background: #ffffff;
.el-tabs__nav {
margin-left: 10px;
}
}
}
.drawItemBtn {
background: #ffffff;
padding: 10px 50px;
font-size: 14px;
color: #1478f6;
border: 1px dashed #dbdde1;
border-radius: 4px;
cursor: pointer;
margin-top: 50px;
}
.drawItemBtn:hover {
background: #f2fcff;
border: 1px dashed #1478f6;
}
}
// cron表达式样式
.crontabBox {
padding: 15px;
.crontabBoxTitle {
margin-bottom: 15px;
color: #333333;
}
::v-deep .el-tabs--border-card {
border-radius: 8px;
box-shadow: unset;
border: 1px solid #dadce0;
}
::v-deep .popup-main {
border-radius: 8px;
border: 1px solid #dadce0;
font-size: 14px;
}
::v-deep .popup-result {
border: unset;
margin: 0 auto;
padding: 15px 10px 5px 15px;
.title {
width: unset;
margin-left: unset;
background: transparent;
color: #333;
}
}
::v-deep .el-tabs__header {
border-radius: 8px 8px 0 0;
margin: 0;
background: #f5f7fa !important;
.el-tabs__nav {
margin-left: 0 !important;
}
}
::v-deep .el-tabs__header .el-tabs__item:first-child {
border-radius: 8px 0 0 0;
margin-left: -2px;
margin-top: 0px;
}
::v-deep .pop_btn {
text-align: center;
margin-top: 10px;
margin-bottom: 10px;
.el-button:last-child {
display: none;
}
}
}
.currentDrawBox {
background: #ffffff;
display: flex;
align-items: center;
font-size: 14px;
color: #333;
.img {
width: 44px;
height: 44px;
border-radius: 50%;
margin-right: 10px;
img {
width: 100%;
height: 100%;
border-radius: 50%;
}
}
.actionName {
font-weight: 400;
color: #333333;
margin-bottom: 5px;
}
.content {
font-weight: 500;
color: #333333;
margin-bottom: 5px;
}
.drawimg {
margin-right: 10px;
width: 44px;
height: 44px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid #f18709;
img {
width: 60%;
height: 60%;
}
}
}
// 选择操作
.timeWrap {
padding: 15px;
box-sizing: border-box;
.timeItem {
width: 100%;
height: 58px;
background: #ffffff;
border-radius: 4px;
border: 1px solid #dbdde1;
padding: 10px 14px;
box-sizing: border-box;
margin-bottom: 10px;
display: flex;
.imgBox {
width: 15px;
height: 20px;
margin-right: 3px;
img {
width: 100%;
height: 100%;
}
}
.title {
font-weight: 500;
font-size: 14px;
color: #333333;
}
.content {
font-weight: 400;
font-size: 14px;
color: #333333;
}
}
.timeItem:hover {
background: #f2fcff;
border: 1px solid #1478f5;
}
.activTimeItem {
background: #f2fcff;
border-radius: 4px;
border: 1px solid #1478f6;
}
}
</style>