<template>
|
<div class="app-container">
|
<!-- 页面标题 -->
|
<div class="page-header">
|
<div class="header-title">
|
<el-icon class="title-icon"><Setting /></el-icon>
|
<span>审批流程配置</span>
|
</div>
|
<div class="header-desc">为不同审批类型配置审批流程和审批人</div>
|
</div>
|
|
<!-- 审批类型切换 - 紧凑标签式 -->
|
<div class="type-tabs">
|
<div
|
v-for="type in approveTypes"
|
:key="type.value"
|
class="type-tab"
|
:class="{ active: activeTab === type.value }"
|
@click="activeTab = type.value; handleTabChange()"
|
>
|
<el-icon :size="14" :style="{ color: activeTab === type.value ? type.color : '#909399' }">
|
<component :is="type.icon" />
|
</el-icon>
|
<span class="tab-name">{{ type.label }}</span>
|
</div>
|
</div>
|
|
<!-- 主要内容区域 -->
|
<el-card class="config-card" shadow="hover" v-loading="loading">
|
<template #header>
|
<div class="card-header">
|
<div class="header-left">
|
<div class="type-icon" :style="{ backgroundColor: getTypeColor(currentApproveType) }">
|
<el-icon :size="20" color="#fff"><component :is="getTypeIcon(currentApproveType)" /></el-icon>
|
</div>
|
<div class="header-info">
|
<span class="type-name">{{ currentApproveTypeName }}</span>
|
<el-tag :type="approverList.length > 0 ? 'success' : 'warning'" size="small" effect="light">
|
{{ approverList.length > 0 ? `已配置 ${approverList.length} 个审批人` : '未配置审批人' }}
|
</el-tag>
|
</div>
|
</div>
|
<div class="header-actions" v-if="approverList.length > 0">
|
<el-button @click="handleReset" size="default">
|
<el-icon><RefreshLeft /></el-icon>
|
重置
|
</el-button>
|
<el-button type="primary" @click="handleSave" :loading="saveLoading" size="default">
|
<el-icon><Check /></el-icon>
|
保存配置
|
</el-button>
|
</div>
|
</div>
|
</template>
|
|
<!-- 审批流程展示 -->
|
<div class="flow-wrapper" v-if="approverList.length > 0">
|
<div class="flow-container">
|
<div
|
v-for="(item, index) in approverList"
|
:key="index"
|
class="flow-item"
|
>
|
<!-- 审批节点卡片 -->
|
<div class="node-card" :class="{ 'empty': !item.approverId }">
|
<!-- 顶部序号和级别 -->
|
<div class="node-badge">{{ index + 1 }}</div>
|
|
<!-- 头像区域 -->
|
<div class="node-avatar-section">
|
<div
|
class="node-avatar"
|
:class="{ 'has-user': item.approverId }"
|
:style="item.approverId ? { backgroundColor: getAvatarColor(item.approverName) } : {}"
|
>
|
<span v-if="item.approverId">{{ item.approverName.charAt(0) }}</span>
|
<el-icon v-else :size="24"><User /></el-icon>
|
</div>
|
<div class="node-level">{{ getLevelText(index) }}</div>
|
</div>
|
|
<!-- 选择区域 -->
|
<div class="node-select-section">
|
<el-select
|
v-model="item.approverId"
|
placeholder="选择审批人"
|
filterable
|
size="default"
|
@change="(val) => handleApproverChange(val, item)"
|
>
|
<el-option
|
v-for="user in userList"
|
:key="user.userId"
|
:label="user.nickName"
|
:value="user.userId"
|
/>
|
</el-select>
|
</div>
|
|
<!-- 操作按钮 -->
|
<div class="node-actions">
|
<el-button
|
type="primary"
|
circle
|
:disabled="index === 0"
|
@click="moveLeft(index)"
|
size="small"
|
class="action-btn"
|
title="前移"
|
>
|
<el-icon><ArrowLeft /></el-icon>
|
</el-button>
|
<el-button
|
type="primary"
|
circle
|
:disabled="index === approverList.length - 1"
|
@click="moveRight(index)"
|
size="small"
|
class="action-btn"
|
title="后移"
|
>
|
<el-icon><ArrowRight /></el-icon>
|
</el-button>
|
<el-button
|
type="danger"
|
circle
|
@click="handleDelete(index)"
|
size="small"
|
class="action-btn"
|
>
|
<el-icon><Delete /></el-icon>
|
</el-button>
|
</div>
|
</div>
|
|
<!-- 连接箭头 -->
|
<div class="arrow-connector" v-if="index < approverList.length - 1">
|
<div class="arrow-line"></div>
|
<el-icon class="arrow-icon"><ArrowRight /></el-icon>
|
</div>
|
</div>
|
|
<!-- 新增节点按钮 - 放在流程最后 -->
|
<div class="add-node-item">
|
<div class="arrow-connector" v-if="approverList.length > 0">
|
<div class="arrow-line"></div>
|
<el-icon class="arrow-icon"><ArrowRight /></el-icon>
|
</div>
|
<div class="add-node-card" @click="handleAdd">
|
<div class="add-icon-wrapper">
|
<el-icon :size="28"><Plus /></el-icon>
|
</div>
|
<span class="add-text">新增审批人</span>
|
</div>
|
</div>
|
</div>
|
</div>
|
|
<!-- 空状态 -->
|
<div class="empty-state" v-else>
|
<div class="empty-content">
|
<div class="empty-icon-wrapper">
|
<el-icon :size="48" color="#c0c4cc"><User /></el-icon>
|
</div>
|
<div class="empty-text">暂无审批人配置</div>
|
<div class="empty-subtext">点击下方按钮添加第一个审批人</div>
|
<el-button type="primary" size="large" @click="handleAdd" class="empty-add-btn">
|
<el-icon><Plus /></el-icon>
|
新增审批人
|
</el-button>
|
</div>
|
</div>
|
</el-card>
|
|
<!-- 底部提示 -->
|
<div class="bottom-tips">
|
<el-icon><InfoFilled /></el-icon>
|
<span>提示:每个流程至少配置一个审批人,审批按顺序流转,可通过箭头调整顺序</span>
|
</div>
|
</div>
|
</template>
|
|
<script setup>
|
import { ref, computed, onMounted } from 'vue';
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
import {
|
Plus, ArrowLeft, Delete, Check, RefreshLeft, Setting,
|
Suitcase, Calendar, Location, Money, ShoppingCart, DocumentChecked,
|
Van, ArrowRight, User, InfoFilled
|
} from '@element-plus/icons-vue';
|
import { getApproveProcessConfigNodeList, addApproveProcessConfigNode } from '@/api/collaborativeApproval/approvalManagement';
|
import { userListNoPage } from '@/api/system/user';
|
|
// 当前选中的标签页
|
const activeTab = ref('1');
|
|
// 审批类型配置数组
|
const approveTypes = [
|
{ value: '1', label: '公出管理', icon: 'Suitcase', color: '#409EFF' },
|
{ value: '2', label: '请假管理', icon: 'Calendar', color: '#67C23A' },
|
{ value: '3', label: '出差管理', icon: 'Location', color: '#E6A23C' },
|
{ value: '4', label: '报销管理', icon: 'Money', color: '#F56C6C' },
|
{ value: '5', label: '采购审批', icon: 'ShoppingCart', color: '#909399' },
|
{ value: '6', label: '报价审批', icon: 'DocumentChecked', color: '#9B59B6' },
|
{ value: '7', label: '发货审批', icon: 'Van', color: '#1ABC9C' },
|
];
|
|
// 审批类型名称映射
|
const approveTypeNameMap = {
|
1: '公出管理',
|
2: '请假管理',
|
3: '出差管理',
|
4: '报销管理',
|
5: '采购审批',
|
6: '报价审批',
|
7: '发货审批',
|
};
|
|
// 审批类型图标映射
|
const typeIconMap = {
|
1: 'Suitcase',
|
2: 'Calendar',
|
3: 'Location',
|
4: 'Money',
|
5: 'ShoppingCart',
|
6: 'DocumentChecked',
|
7: 'Van',
|
};
|
|
// 审批类型颜色映射
|
const typeColorMap = {
|
1: '#409EFF',
|
2: '#67C23A',
|
3: '#E6A23C',
|
4: '#F56C6C',
|
5: '#909399',
|
6: '#9B59B6',
|
7: '#1ABC9C',
|
};
|
|
// 头像颜色池
|
const avatarColors = ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C', '#9B59B6', '#1ABC9C', '#FF6B6B', '#4ECDC4'];
|
|
// 当前审批类型名称
|
const currentApproveTypeName = computed(() => {
|
return approveTypeNameMap[activeTab.value] || '未知类型';
|
});
|
|
// 当前审批类型
|
const currentApproveType = computed(() => {
|
return Number(activeTab.value);
|
});
|
|
// 获取类型图标
|
const getTypeIcon = (type) => typeIconMap[type] || 'Setting';
|
|
// 获取类型颜色
|
const getTypeColor = (type) => typeColorMap[type] || '#409EFF';
|
|
// 获取头像颜色
|
const getAvatarColor = (name) => {
|
if (!name) return '#C0C4CC';
|
let hash = 0;
|
for (let i = 0; i < name.length; i++) {
|
hash = name.charCodeAt(i) + ((hash << 5) - hash);
|
}
|
return avatarColors[Math.abs(hash) % avatarColors.length];
|
};
|
|
// 获取级别文本
|
const getLevelText = (index) => {
|
const texts = ['第一级', '第二级', '第三级', '第四级', '第五级', '第六级', '第七级', '第八级'];
|
return texts[index] || `第${index + 1}级`;
|
};
|
|
// 审批人列表(真实接口)
|
const userList = ref([]);
|
|
// 审批人列表
|
const approverList = ref([]);
|
|
// 原始数据,用于重置
|
const originalList = ref([]);
|
|
// 加载状态
|
const loading = ref(false);
|
const saveLoading = ref(false);
|
|
// 标签页切换处理
|
const handleTabChange = () => {
|
loadData();
|
};
|
|
// 加载审批配置数据(模拟)
|
const loadData = async () => {
|
loading.value = true;
|
try {
|
const res = await getApproveProcessConfigNodeList(currentApproveType.value);
|
const source = Array.isArray(res?.data)
|
? res.data
|
: Array.isArray(res?.rows)
|
? res.rows
|
: Array.isArray(res?.data?.records)
|
? res.data.records
|
: [];
|
const data = source.map((item, index) => ({
|
...item,
|
sortOrder: item.nodeOrder ?? item.sortOrder ?? index + 1,
|
}));
|
approverList.value = data.sort((a, b) => (a.sortOrder || 0) - (b.sortOrder || 0));
|
originalList.value = JSON.parse(JSON.stringify(approverList.value));
|
} catch (error) {
|
approverList.value = [];
|
originalList.value = [];
|
ElMessage.error('加载审批配置失败');
|
} finally {
|
loading.value = false;
|
}
|
};
|
|
const loadUserList = async () => {
|
try {
|
const res = await userListNoPage();
|
userList.value = Array.isArray(res?.data) ? res.data : [];
|
} catch (error) {
|
userList.value = [];
|
ElMessage.error('加载人员列表失败');
|
}
|
};
|
|
// 审批人选择变化
|
const handleApproverChange = (userId, row) => {
|
const user = userList.value.find((u) => u.userId === userId);
|
if (user) {
|
row.approverName = user.nickName;
|
}
|
};
|
|
// 新增审批人
|
const handleAdd = () => {
|
const newOrder = approverList.value.length + 1;
|
approverList.value.push({
|
id: null,
|
approveType: currentApproveType.value,
|
approverId: null,
|
approverName: '',
|
sortOrder: newOrder,
|
});
|
};
|
|
// 删除审批人
|
const handleDelete = (index) => {
|
ElMessageBox.confirm('确定删除该审批人吗?', '提示', {
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
type: 'warning',
|
})
|
.then(() => {
|
approverList.value.splice(index, 1);
|
approverList.value.forEach((item, idx) => {
|
item.sortOrder = idx + 1;
|
});
|
ElMessage.success('删除成功');
|
})
|
.catch(() => {});
|
};
|
|
// 前移
|
const moveLeft = (index) => {
|
if (index === 0) return;
|
const temp = approverList.value[index];
|
approverList.value[index] = approverList.value[index - 1];
|
approverList.value[index - 1] = temp;
|
approverList.value[index].sortOrder = index + 1;
|
approverList.value[index - 1].sortOrder = index;
|
};
|
|
// 后移
|
const moveRight = (index) => {
|
if (index === approverList.value.length - 1) return;
|
const temp = approverList.value[index];
|
approverList.value[index] = approverList.value[index + 1];
|
approverList.value[index + 1] = temp;
|
approverList.value[index].sortOrder = index + 1;
|
approverList.value[index + 1].sortOrder = index + 2;
|
};
|
|
// 保存配置
|
const handleSave = async () => {
|
if (approverList.value.length === 0) {
|
ElMessage.warning('请至少配置一个审批人');
|
return;
|
}
|
|
const hasEmptyApprover = approverList.value.some((item) => !item.approverId);
|
if (hasEmptyApprover) {
|
ElMessage.warning('请选择所有审批人');
|
return;
|
}
|
|
const approverIds = approverList.value.map((item) => item.approverId);
|
const uniqueIds = [...new Set(approverIds)];
|
if (uniqueIds.length !== approverIds.length) {
|
ElMessage.warning('审批人不能重复');
|
return;
|
}
|
|
saveLoading.value = true;
|
try {
|
const payload = approverList.value.map((item, index) => ({
|
approveType: currentApproveType.value,
|
nodeOrder: index + 1,
|
approverId: item.approverId,
|
approverName: item.approverName,
|
}));
|
await addApproveProcessConfigNode(payload);
|
ElMessage.success('保存成功');
|
await loadData();
|
} catch (error) {
|
ElMessage.error('保存失败');
|
} finally {
|
saveLoading.value = false;
|
}
|
};
|
|
// 重置
|
const handleReset = () => {
|
if (originalList.value.length === 0) {
|
approverList.value = [];
|
return;
|
}
|
ElMessageBox.confirm('确定要重置当前配置吗?未保存的更改将丢失。', '提示', {
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
type: 'warning',
|
})
|
.then(() => {
|
approverList.value = JSON.parse(JSON.stringify(originalList.value));
|
ElMessage.success('已重置');
|
})
|
.catch(() => {});
|
};
|
|
onMounted(async () => {
|
await loadUserList();
|
await loadData();
|
});
|
</script>
|
|
<style scoped>
|
.page-header {
|
margin-bottom: 20px;
|
}
|
|
.header-title {
|
display: flex;
|
align-items: center;
|
gap: 10px;
|
font-size: 20px;
|
font-weight: 600;
|
color: var(--el-text-color-primary, #303133);
|
margin-bottom: 6px;
|
}
|
|
.title-icon {
|
font-size: 24px;
|
color: var(--el-color-primary, #409EFF);
|
}
|
|
.header-desc {
|
font-size: 13px;
|
color: var(--el-text-color-secondary, #909399);
|
margin-left: 34px;
|
}
|
|
/* 审批类型切换 - 紧凑标签式 */
|
.type-tabs {
|
display: flex;
|
gap: 4px;
|
margin-bottom: 16px;
|
padding: 4px;
|
background: var(--el-fill-color-light, #f5f7fa);
|
border-radius: 8px;
|
overflow-x: auto;
|
}
|
|
.type-tab {
|
display: flex;
|
align-items: center;
|
gap: 6px;
|
padding: 8px 14px;
|
border-radius: 6px;
|
cursor: pointer;
|
transition: all 0.2s ease;
|
white-space: nowrap;
|
font-size: 13px;
|
color: var(--el-text-color-regular, #606266);
|
}
|
|
.type-tab:hover {
|
background: var(--el-color-primary-light-9, rgba(64, 158, 255, 0.1));
|
color: var(--el-color-primary, #409EFF);
|
}
|
|
.type-tab.active {
|
background: var(--el-bg-color, #fff);
|
color: var(--el-color-primary, #409EFF);
|
font-weight: 600;
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
}
|
|
.tab-name {
|
font-size: 13px;
|
}
|
|
.tab-count {
|
min-width: 16px;
|
height: 16px;
|
padding: 0 5px;
|
background: var(--el-color-success, #67C23A);
|
color: #fff;
|
border-radius: 8px;
|
font-size: 11px;
|
font-weight: 600;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
}
|
|
.config-card {
|
margin-bottom: 16px;
|
border-radius: 12px;
|
}
|
|
:deep(.el-card__header) {
|
padding: 16px 20px;
|
border-bottom: 1px solid var(--el-border-color-light, #ebeef5);
|
}
|
|
.card-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
}
|
|
.header-left {
|
display: flex;
|
align-items: center;
|
gap: 14px;
|
}
|
|
.type-icon {
|
width: 44px;
|
height: 44px;
|
border-radius: 10px;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
}
|
|
.header-info {
|
display: flex;
|
flex-direction: column;
|
gap: 6px;
|
}
|
|
.type-name {
|
font-size: 16px;
|
font-weight: 600;
|
color: var(--el-text-color-primary, #303133);
|
}
|
|
.header-actions {
|
display: flex;
|
gap: 10px;
|
}
|
|
.flow-wrapper {
|
overflow-x: auto;
|
padding: 8px 4px;
|
}
|
|
.flow-container {
|
display: flex;
|
align-items: center;
|
gap: 0;
|
min-width: min-content;
|
}
|
|
.flow-item {
|
display: flex;
|
align-items: center;
|
}
|
|
.node-card {
|
width: 200px;
|
background: var(--el-bg-color, #fff);
|
border: 2px solid var(--el-border-color, #e4e7ed);
|
border-radius: 12px;
|
padding: 16px;
|
position: relative;
|
transition: all 0.3s ease;
|
flex-shrink: 0;
|
}
|
|
.node-card:hover {
|
border-color: var(--el-color-primary, #409EFF);
|
box-shadow: 0 4px 16px rgba(64, 158, 255, 0.15);
|
transform: translateY(-2px);
|
}
|
|
.node-card.empty {
|
border-style: dashed;
|
border-color: var(--el-border-color, #c0c4cc);
|
background: var(--el-fill-color-light, #fafbfc);
|
}
|
|
.node-card.empty:hover {
|
border-color: var(--el-color-primary, #409EFF);
|
background: var(--el-fill-color-light, #f5f7fa);
|
}
|
|
.node-badge {
|
position: absolute;
|
top: -10px;
|
left: 16px;
|
width: 24px;
|
height: 24px;
|
background: var(--el-color-primary, #409EFF);
|
color: #fff;
|
border-radius: 50%;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
font-size: 13px;
|
font-weight: 700;
|
box-shadow: 0 2px 8px rgba(64, 158, 255, 0.4);
|
}
|
|
.node-avatar-section {
|
display: flex;
|
flex-direction: column;
|
align-items: center;
|
margin-bottom: 12px;
|
margin-top: 4px;
|
}
|
|
.node-avatar {
|
width: 56px;
|
height: 56px;
|
border-radius: 50%;
|
background: var(--el-fill-color, #f0f2f5);
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
margin-bottom: 8px;
|
color: var(--el-text-color-placeholder, #c0c4cc);
|
transition: all 0.3s ease;
|
}
|
|
.node-avatar.has-user {
|
color: #fff;
|
font-size: 22px;
|
font-weight: 600;
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
}
|
|
.node-level {
|
font-size: 12px;
|
color: var(--el-text-color-secondary, #909399);
|
font-weight: 500;
|
}
|
|
.node-select-section {
|
margin-bottom: 12px;
|
}
|
|
.node-select-section :deep(.el-select) {
|
width: 100%;
|
}
|
|
.node-actions {
|
display: flex;
|
justify-content: center;
|
gap: 8px;
|
padding-top: 12px;
|
border-top: 1px solid var(--el-border-color-light, #ebeef5);
|
}
|
|
.action-btn {
|
transition: all 0.2s;
|
}
|
|
.action-btn:hover:not(:disabled) {
|
transform: scale(1.1);
|
}
|
|
.arrow-connector {
|
display: flex;
|
align-items: center;
|
width: 50px;
|
position: relative;
|
}
|
|
.arrow-line {
|
flex: 1;
|
height: 2px;
|
background: var(--el-border-color, #c0c4cc);
|
}
|
|
.arrow-icon {
|
color: var(--el-text-color-placeholder, #c0c4cc);
|
font-size: 14px;
|
margin-left: -2px;
|
}
|
|
/* 新增节点样式 */
|
.add-node-item {
|
display: flex;
|
align-items: center;
|
}
|
|
.add-node-card {
|
width: 140px;
|
height: 200px;
|
border: 2px dashed var(--el-border-color, #c0c4cc);
|
border-radius: 12px;
|
display: flex;
|
flex-direction: column;
|
align-items: center;
|
justify-content: center;
|
gap: 12px;
|
cursor: pointer;
|
transition: all 0.3s ease;
|
background: var(--el-fill-color-light, #fafbfc);
|
flex-shrink: 0;
|
margin-left: 0;
|
}
|
|
.add-node-card:hover {
|
border-color: var(--el-color-primary, #409EFF);
|
background: var(--el-color-primary-light-9, #f0f7ff);
|
transform: translateY(-2px);
|
box-shadow: 0 4px 16px rgba(64, 158, 255, 0.15);
|
}
|
|
.add-icon-wrapper {
|
width: 48px;
|
height: 48px;
|
border-radius: 50%;
|
background: var(--el-color-primary, #409EFF);
|
color: #fff;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
box-shadow: 0 4px 12px rgba(64, 158, 255, 0.3);
|
transition: all 0.3s ease;
|
}
|
|
.add-node-card:hover .add-icon-wrapper {
|
transform: scale(1.1);
|
box-shadow: 0 6px 16px rgba(64, 158, 255, 0.4);
|
}
|
|
.add-text {
|
font-size: 14px;
|
color: var(--el-text-color-regular, #606266);
|
font-weight: 500;
|
}
|
|
.add-node-card:hover .add-text {
|
color: var(--el-color-primary, #409EFF);
|
}
|
|
/* 空状态 */
|
.empty-state {
|
padding: 50px 20px;
|
}
|
|
.empty-content {
|
display: flex;
|
flex-direction: column;
|
align-items: center;
|
gap: 16px;
|
}
|
|
.empty-icon-wrapper {
|
width: 80px;
|
height: 80px;
|
border-radius: 50%;
|
background: var(--el-fill-color-light, #f5f7fa);
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
margin-bottom: 8px;
|
}
|
|
.empty-text {
|
font-size: 16px;
|
font-weight: 600;
|
color: var(--el-text-color-regular, #606266);
|
}
|
|
.empty-subtext {
|
font-size: 13px;
|
color: var(--el-text-color-secondary, #909399);
|
}
|
|
.empty-add-btn {
|
margin-top: 8px;
|
padding: 12px 28px;
|
}
|
|
/* 底部提示 */
|
.bottom-tips {
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
gap: 8px;
|
padding: 12px 20px;
|
background: var(--el-fill-color-light, #f5f7fa);
|
border-radius: 8px;
|
color: var(--el-text-color-regular, #606266);
|
font-size: 13px;
|
}
|
|
.bottom-tips .el-icon {
|
color: var(--el-color-primary, #409EFF);
|
font-size: 16px;
|
}
|
|
@media (max-width: 768px) {
|
.type-tabs {
|
padding: 3px;
|
}
|
|
.type-tab {
|
padding: 6px 10px;
|
font-size: 12px;
|
}
|
|
.tab-name {
|
font-size: 12px;
|
}
|
|
.flow-container {
|
flex-wrap: wrap;
|
justify-content: center;
|
}
|
|
.arrow-connector {
|
width: 100%;
|
height: 30px;
|
flex-direction: row;
|
justify-content: center;
|
}
|
|
.arrow-line {
|
width: 2px;
|
height: 30px;
|
}
|
|
.arrow-icon {
|
right: auto;
|
top: auto;
|
bottom: -5px;
|
transform: rotate(90deg);
|
}
|
|
.add-node-item {
|
width: 100%;
|
justify-content: center;
|
margin-top: 10px;
|
}
|
|
.add-node-item .arrow-connector {
|
display: none;
|
}
|
}
|
</style>
|