feat: 完善流程节点展示

master
donghao 4 days ago
parent a801c4ed74
commit 727d05b7d5

@ -69,6 +69,132 @@ $ npm run build:mac
$ npm run build:linux
```
# 项目结构 (Project Structure)
这是一个基于 Electron + Vite + TypeScript 的桌面应用程序项目结构,使用 Tailwind CSS 进行样式设计,并通过 electron-builder 进行打包分发。
## 目录结构
### 📁 `build/`
- **构建配置目录**
包含与打包相关的脚本和资源文件
- `icons/` - 应用程序图标集(不同尺寸)
- `installer.nsh` - NSIS 安装脚本配置
- `scripts/` - 构建相关脚本
### 📁 `node_modules/`
- **依赖库目录**
存储所有 npm/yarn 安装的第三方依赖包
*(此目录不应手动修改)*
### 📁 `out/`
- **临时输出目录**
存放开发/构建过程中生成的临时文件
- `main/` - 主进程编译输出
- `renderer/` - 渲染进程编译输出
### 📁 `release/`
- **发布目录**
最终生成的应用程序安装包和可执行文件
### 📁 `resources/`
- **资源文件目录**
包含应用程序使用的静态资源
- `icons/` - 应用程序图标资源
- `data/` - 其他静态数据文件
### 📁 `src/`
- **核心源代码目录**
应用程序的主要逻辑和界面代码
- `main/` - Electron 主进程代码
- `preload/` - Electron 预加载脚本
- `renderer/` - 渲染进程代码
- `src/` - Vite 应用源码
- `api/` - 用于与后端或外部服务进行数据交互的API请求
- `assets/` - 前端资源文件 (images, fonts, etc.)
- `components/` - UI 组件
- `config/` - 项目配置相关
- `hooks/` - 自定义 Vue Hooks
- `layout/` - 页面布局组件
- `mock/` - 模拟数据用于开发和测试
- `plugins/` - 项目插件
- `router/` - 前端路由配置
- `stores/` - 状态管理 (Pinia)
- `styles/` - 全局样式Sass
- `utils/` - 工具函数 (日期格式化,数据处理等)
- `views/` - 页面级别的组件 (Pages)
- `Design/` - 设计面板页面
- `CommManagement/` (通信管理)
- `ControllerManagement/` (控制器管理)
- `Controls/` (设计控制控件集合组件)
- `ImagesCapture/` (图像集 design-panel-controls)
- `LogManagement/` (日志管理)
- `Settings/` - (设置)
- `Workflow/` - (工作流)
- `index.vue` - 设计面板页面入口文件。
- `App.vue` - 主应用组件 (Vue.js)
- `main.ts` - 渲染进程入口
- `env.d.ts` - 环境变量类型定义
- `auto-imports.d.ts` - 自动导入的模块类型定义
- `components.d.ts` - 组件类型定义
- `index.html` - HTML 入口文件
- `types/` - 全局类型定义
### 📁 `test/`
- **测试目录**
包含应用程序的各种测试
- `e2e/` - 端到端测试
- `unit/` - 单元测试
- `mocks/` - 测试用模拟数据
## 配置文件
### ⚙️ 基础配置
| 文件 | 用途 |
|------|------|
| `package.json` | 项目元数据、依赖项和 NPM 脚本 |
| `package-lock.json` | 锁定依赖版本确保一致性 |
| `tsconfig.json` | TypeScript 基础配置 |
| `tsconfig.node.json` | Node.js 环境 TypeScript 配置 |
| `tsconfig.web.json` | 浏览器环境 TypeScript 配置 |
### 🛠️ 构建工具
| 文件 | 用途 |
|------|------|
| `electron.vite.config.ts` | Vite 的 Electron 专用配置 |
| `electron-builder.yml` | Electron 应用打包配置 |
| `postcss.config.js` | PostCSS 处理配置 |
| `tailwind.config.js` | Tailwind CSS 样式框架配置 |
### 🧹 代码质量
| 文件 | 用途 |
|------|------|
| `.editorconfig` | 跨编辑器/IDE 的代码风格统一 |
| `.eslintrc.cjs` | ESLint 代码检查配置 |
| `.eslintignore` | ESLint 忽略文件配置 |
| `.prettierrc.yaml` | Prettier 代码格式化配置 |
| `.prettierignore` | Prettier 忽略文件配置 |
### 📌 其他文件
| 文件 | 用途 |
|------|------|
| `.gitignore` | Git 版本控制忽略规则 |
| `.npmrc` | npm 配置 |
| `README.md` | 项目说明文档 |
## 技术栈概览
- **核心框架**: Electron
- **开发语言**: TypeScript
- **构建工具**: Vite
- **UI 框架**: Element Plus
- **样式方案**: Tailwind CSS
- **代码质量**: ESLint + Prettier
- **打包工具**: electron-builder
- **CSS 处理**: PostCSS
- **测试框架**: Vitest
## Examples
- [electron-vite-bytecode-example](https://github.com/alex8088/electron-vite-bytecode-example), source code protection

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 725 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 730 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 604 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 778 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 917 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 663 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 816 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

@ -2,19 +2,21 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2025-07-14 16:48:31
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2025-07-17 13:32:04
* @LastEditTime: 2025-07-23 15:30:06
* @FilePath: \Robot-Al-Platform-Web\src\renderer\src\components\LogicFlowNodes\src\imageNode.vue
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
<div class="flex items-center node-title" ref="myNode">
<span class="node-icon">
<img src="@/assets/electron.svg" alt="" />
<img :src="ImageNodeActiveIcon" alt="" />
</span>
</div>
</template>
<script setup lang="ts">
import ImageNodeActiveIcon from '@/assets/images/ImagesCapture/image-node-active.png' //
import * as variables from '@/styles/logic-flow-core.scss'
const props = defineProps({
properties: {
@ -22,7 +24,7 @@ const props = defineProps({
default: null
}
})
let myNode = ref(null)
const myNode = ref(null)
const name = ref('图像源')
@ -32,6 +34,7 @@ onMounted(() => {
borderColor = variables.dangerColor
}
myNode.value.style.border = `1px solid ${borderColor}` //stroke
console.log('imageNode_props', props)
})
</script>
@ -41,13 +44,13 @@ onMounted(() => {
height: 100%;
padding: 0 10px;
border-radius: 20px;
border: 2px solid #154ddd;
border: 2px solid var(--ds-color-primary);
background-color: #fff;
}
.node-icon {
.node-icon {
font-size: 16px;
img {
width: 19px;
}
}
}
</style>

@ -1,22 +1,27 @@
<!--
* @Author: donghao donghao@supervision.ltd
* @Date: 2025-07-15 17:27:57
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2025-07-23 15:28:57
* @FilePath: \Robot-Al-Platform-Web\src\renderer\src\components\LogicFlowNodes\src\viewNode.vue
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
<div class="node-wrap">
<div class="node-title" :class="{ error: isError }">
<div :ellipsis="{ row: 1, showTooltip: true }" class="node-name">
{{ properties.id || '操作' }}
</div>
</div>
<div class="error-info" v-if="isError && isActive">
{{ errorInfo }}
</div>
<div class="flex items-center node-wrap" ref="myNode">
<span class="node-icon">
<img :src="fetchIconType" alt="" />
</span>
</div>
</template>
<script setup lang="ts">
import * as variables from '@/styles/logic-flow-core.scss'
import { BaseNodeModel } from '@logicflow/core'
import { OPERATION_NODE_TYPE_MAP } from '@/config/designComm'
import MultiImageNodeActiveIcon from '@/assets/images/ImagesCapture/multi-image-node-active.png' //
import OutputImageNodeActiveIcon from '@/assets/images/ImagesCapture/output-image-node-active.png' //
import CashImageNodeActiveIcon from '@/assets/images/ImagesCapture/cash-image-node-active.png' //
const props = defineProps({
properties: {
type: Object,
@ -26,27 +31,50 @@ const props = defineProps({
type: BaseNodeModel,
required: true
},
nodeInfo: {
type: Object,
required: true
},
isSelected: Boolean,
isHovered: Boolean
})
const isActive = computed(() => props.isHovered || props.isSelected)
const isError = computed(() => {
if (props.properties.type === OPERATION_NODE_TYPE_MAP['NI-VISA']) {
return props.properties.id === '' || props.properties.command === ''
} else if (props.properties.type === OPERATION_NODE_TYPE_MAP['FUNCTION']) {
return props.properties.id === ''
} else {
return props.properties.id === ''
const iconType = ref<string>('')
const myNode = ref(null)
const initStyle = () => {
let borderColor = variables.dragNodeBorderColor
if (props.properties.frontend_status == '0') {
borderColor = variables.dangerColor
}
})
myNode.value.style.border = `1px solid ${borderColor}` //stroke
}
const errorInfo = '信息不完整'
const fetchIconType = computed({
get() {
let iconType = ''
switch (props.nodeInfo?.type) {
case 'multi-image-node':
iconType = MultiImageNodeActiveIcon
break
case 'output-image-node':
iconType = OutputImageNodeActiveIcon
break
case 'cash-image-node':
iconType = CashImageNodeActiveIcon
break
}
return iconType
}
})
onMounted(() => {
initStyle()
})
watch(
() => isError.value,
() => props.nodeInfo,
(value) => {
props.model.setProperty('isError', value)
console.log(props.nodeInfo?.type, 'watch_props_nodeInfo')
},
{ immediate: true }
)
@ -56,58 +84,15 @@ watch(
.node-wrap {
width: 100%;
height: 100%;
color: black;
display: flex;
justify-content: space-between;
align-items: center;
.node-title {
width: 100%;
height: 100%;
display: inline-flex;
align-items: center;
border: 1px solid #bac1d0;
padding: 0 10px;
border-radius: 4px;
background: #fff;
overflow: hidden;
&.error {
border: 3px dashed rgb(220, 16, 16);
}
border: 2px solid var(--ds-color-primary);
background-color: #fff;
.node-icon {
display: inline-block;
width: 26px;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background: rgb(90, 204, 109);
font-size: 16px;
img {
width: 18px;
height: 18px;
filter: drop-shadow(#ffffff 100px 0);
transform: translateX(-100px);
}
}
.node-name {
width: 0px;
margin-bottom: 0px;
flex: 1;
text-align: center;
width: 19px;
}
}
.error-info {
width: 100%;
position: absolute;
bottom: 0;
font-size: 12px;
color: red;
text-align: center;
transform: translateY(105%);
}
}
</style>

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2025-07-15 17:28:05
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2025-07-15 17:58:50
* @LastEditTime: 2025-07-18 17:46:25
* @FilePath: \Robot-Al-Platform-Web\src\renderer\src\components\LogicFlowNodes\viewNode.ts
* @Description: viewNode
*/
@ -16,6 +16,7 @@ import {
import OperationNode from './src/viewNode.vue'
import { createApp, h, ref } from 'vue'
import { NODE_WIDTH, NODE_HEIGHT } from '@/config/designComm'
import { generateId } from '@/utils/plugins/random'
class OperationNodeView extends HtmlNode {
root: HTMLDivElement
@ -58,7 +59,8 @@ class OperationNodeView extends HtmlNode {
properties: this.props.model.properties,
isSelected: this.props.model.isSelected,
isHovered: this.props.model.isHovered,
model: this.props.model
model: this.props.model,
nodeInfo: { id: generateId(), type: this.props.model.type }
}
} else {
// @ts-expect-error 暂时不解决
@ -66,7 +68,8 @@ class OperationNodeView extends HtmlNode {
properties: this.props.model.properties,
isSelected: this.props.model.isSelected,
isHovered: this.props.model.isHovered,
model: this.props.model
model: this.props.model,
nodeInfo: { id: generateId(), type: this.props.model.type }
})
this.vm = createApp({
render: () => h(this.vueComponent, this.vmProps!.value)
@ -76,14 +79,21 @@ class OperationNodeView extends HtmlNode {
}
}
// class OutputImageNodeView extends OperationNodeView {
// }
class OperationNodeModel extends HtmlNodeModel {
createId() {
return generateId() // 生成唯一id
}
setAttributes() {
this.width = NODE_WIDTH
this.height = NODE_HEIGHT
}
getDefaultAnchor(): Model.AnchorConfig[] {
const { width, x, y, id } = this
const { width, height, x, y, id } = this
return [
{
x: x - width / 2,
@ -96,13 +106,25 @@ class OperationNodeModel extends HtmlNodeModel {
y,
name: 'right',
id: `${id}_1`
},
{
x: x,
y: y + height / 2,
name: 'bootom',
id: `${id}_2`
},
{
x: x,
y: y - height / 2,
name: 'top',
id: `${id}_3`
}
]
}
}
export default {
type: 'operation-node',
model: OperationNodeModel,
view: OperationNodeView
}
export default [
{ type: 'multi-image-node', model: OperationNodeModel, view: OperationNodeView },
{ type: 'output-image-node', model: OperationNodeModel, view: OperationNodeView },
{ type: 'cash-image-node', model: OperationNodeModel, view: OperationNodeView }
]

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2025-07-14 14:30:34
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2025-07-17 13:33:52
* @LastEditTime: 2025-07-23 14:52:08
* @FilePath: \Robot-Al-Platform-Web\src\renderer\src\config\designCanvas.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
@ -15,7 +15,7 @@ export const logicFlowConf = {
stroke: '#ff0000', // 对齐线颜色
strokeWidth: 1 // 对齐线宽度
},
textEdit: true, //是否开启文本编辑
textEdit: false, //是否开启文本编辑
adjustEdge: true, //允许调整边
adjustEdgeStartAndEnd: false, //是否允许拖动边的端点来调整连线
edgeSelectedOutline: true, //鼠标 hover 的时候显示边的外框

@ -2,10 +2,11 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2025-07-14 13:45:30
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2025-07-17 16:21:20
* @LastEditTime: 2025-07-23 14:31:26
* @FilePath: \Robot-Al-Platform-Web\src\renderer\src\config\designControl.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
// 顶部设计控制栏
import SaveIcon from '@/assets/images/navBar/save.png'
import PrevIcon from '@/assets/images/navBar/prev.png'
import NextIcon from '@/assets/images/navBar/next.png'
@ -21,81 +22,167 @@ import ContinuousExecIcon from '@/assets/images/navBar/continuous_execution.png'
import RunInterfaceIcon from '@/assets/images/navBar/run_interface.png'
import RunModelIcon from '@/assets/images/navBar/run_model.png'
// 左侧控制栏
import GatherIcon from '@/assets/images/panelBar/gather.png' // 采集
import LocateIcon from '@/assets/images/panelBar/locate.png' // 定位
import IdentifyIcon from '@/assets/images/panelBar/identify.png' // 识别
import CalibrateIcon from '@/assets/images/panelBar/calibrate.png' // 校准
import ImageProcessingIcon from '@/assets/images/panelBar/image_processing.png' // 图片处理
import ColorProcessingIcon from '@/assets/images/panelBar/color_processing.png' // 色彩处理
import ImageGenerationIcon from '@/assets/images/panelBar/image_generation.png' // 图片生成
import LogicalToolsIcon from '@/assets/images/panelBar/logical_tools.png' // 逻辑工具
import CommunicationIcon from '@/assets/images/panelBar/communication.png' // 通讯
import DeepLearningIcon from '@/assets/images/panelBar/deep_learning.png' // 深度学习
// 节点图标
import imageNodeIcon from '@/assets/images/ImagesCapture/image-node.png' // 图像源
import multiImageNodeIcon from '@/assets/images/ImagesCapture/multi-image-node.png' // 多图采集
import outputImageNodeIcon from '@/assets/images/ImagesCapture/output-image-node.png' // 输出图像
import CashImageNodeIcon from '@/assets/images/ImagesCapture/cash-image-node.png' // 缓存图像
export interface designLFNodeType {
type: string
icon: string
label: string
}
// 控制按钮类型
export interface ControlsItemType {
icon: any
text: string
label: string
type: string
children?: designLFNodeType[]
}
// 顶部导航栏控制按钮集合
export const navControlsConf: ControlsItemType[] = [
{
icon: SaveIcon,
text: '保存',
label: '保存',
type: 'save'
},
{
icon: PrevIcon,
text: '上一步',
label: '上一步',
type: 'undo'
},
{
icon: NextIcon,
text: '下一步',
label: '下一步',
type: 'redo'
},
{
icon: LockIcon,
text: '锁定',
label: '锁定',
type: 'lock'
},
{
icon: CameraIcon,
text: '相机管理',
label: '相机管理',
type: 'camera'
},
{
icon: ControlIcon,
text: '控制器管理',
label: '控制器管理',
type: 'control'
},
{
icon: GlobalIcon,
text: '全局变量',
label: '全局变量',
type: 'global'
},
{
icon: CommIcon,
text: '通信管理',
label: '通信管理',
type: 'comm'
},
{
icon: TriggerIcon,
text: '全局触发',
label: '全局触发',
type: 'trigger'
},
{
icon: ScriptIcon,
text: '全局脚本',
label: '全局脚本',
type: 'script'
},
{
icon: SingleExecIcon,
text: '单次执行',
label: '单次执行',
type: 'singleExec'
},
{
icon: ContinuousExecIcon,
text: '连续执行',
label: '连续执行',
type: 'continuousExec'
},
{
icon: RunInterfaceIcon,
text: '编辑运行界面',
label: '编辑运行界面',
type: 'runInterface'
},
{
icon: RunModelIcon,
text: '运行模型',
label: '运行模型',
type: 'runModel'
}
]
// 左侧面板控制按钮集合
export const panelControlsConf: ControlsItemType[] = [
{
icon: GatherIcon,
label: '采集',
children: [
{
type: 'image-node',
label: '图像源',
icon: imageNodeIcon
},
{
type: 'multi-image-node',
label: '多图采集',
icon: multiImageNodeIcon
},
{
type: 'output-image-node',
label: '输出图像',
icon: outputImageNodeIcon
},
{
type: 'cash-image-node',
label: '缓存图像',
icon: CashImageNodeIcon
}
]
},
{
icon: LocateIcon,
label: '定位'
},
{
icon: IdentifyIcon,
label: '识别'
},
{
icon: CalibrateIcon,
label: '校准'
},
{
icon: ImageProcessingIcon,
label: '图片处理'
},
{
icon: ColorProcessingIcon,
label: '色彩处理'
},
{
icon: ImageGenerationIcon,
label: '图片生成'
},
{
icon: CommunicationIcon,
label: '通讯'
},
{
icon: DeepLearningIcon,
label: '深度学习'
}
]

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2025-07-14 14:33:03
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2025-07-17 13:15:40
* @LastEditTime: 2025-07-21 16:28:24
* @FilePath: \Robot-Al-Platform-Web\src\renderer\src\hooks\useLoginFlow.ts
* @Description:
*
@ -11,38 +11,83 @@ export const useLogicFlow = () => {
const graphData = {
nodes: [
{
id: 'node_id_1',
id: '6b4be470-8515-4cec-9bb7-7f64eaae0d2a',
type: 'image-node',
x: 200,
y: 120,
text: { x: 200, y: 120, value: '图像源' },
properties: {}
x: 329.1111068725586,
y: 110.1111068725586,
properties: { width: 132, height: 40 },
text: { x: 329.1111068725586, y: 110.1111068725586, value: '图像源' }
},
{
id: 'node_id_2',
type: 'circle',
x: 200,
y: 300,
text: { x: 200, y: 300, value: '节点2' },
properties: {}
id: 'b3d05799-6137-4dbf-929a-95967e95c945',
type: 'multi-image-node',
x: 329.1111068725586,
y: 229.1111068725586,
properties: { width: 132, height: 40 },
text: { x: 329.1111068725586, y: 229.1111068725586, value: '多图采集' }
},
{
id: '0865bdd5-fd06-40a6-85ed-c176d2b153e0',
type: 'output-image-node',
x: 329.1111068725586,
y: 355.1111068725586,
properties: { width: 132, height: 40 },
text: { x: 329.1111068725586, y: 355.1111068725586, value: '输出图像' }
},
{
id: 'e35754f0-c85a-4d70-8bca-f0b995a2b31e',
type: 'cash-image-node',
x: 329.1111068725586,
y: 488.1111068725586,
properties: { width: 132, height: 40 },
text: { x: 329.1111068725586, y: 488.1111068725586, value: '缓存图像' }
}
],
edges: [
{
id: 'edge_id',
id: 'f20f421d-dec5-4d49-83cc-e46e22eb9972',
type: 'polyline',
sourceNodeId: 'node_id_1',
targetNodeId: 'node_id_2',
text: { x: 200, y: 200, value: '' },
startPoint: { x: 200, y: 140 },
endPoint: { x: 200, y: 250 },
properties: {},
sourceNodeId: '6b4be470-8515-4cec-9bb7-7f64eaae0d2a',
targetNodeId: 'b3d05799-6137-4dbf-929a-95967e95c945',
sourceAnchorId: '6b4be470-8515-4cec-9bb7-7f64eaae0d2a_2',
targetAnchorId: 'b3d05799-6137-4dbf-929a-95967e95c945_3',
startPoint: { x: 329.1111068725586, y: 130.1111068725586 },
endPoint: { x: 329.1111068725586, y: 209.1111068725586 },
pointsList: [
{ x: 200, y: 140 },
{ x: 200, y: 200 },
{ x: 200, y: 200 },
{ x: 200, y: 250 }
],
properties: {}
{ x: 329.1111068725586, y: 130.1111068725586 },
{ x: 329.1111068725586, y: 209.1111068725586 }
]
},
{
id: '97ecf536-9362-4440-a259-d68188cced67',
type: 'polyline',
properties: {},
sourceNodeId: 'b3d05799-6137-4dbf-929a-95967e95c945',
targetNodeId: '0865bdd5-fd06-40a6-85ed-c176d2b153e0',
sourceAnchorId: 'b3d05799-6137-4dbf-929a-95967e95c945_2',
targetAnchorId: '0865bdd5-fd06-40a6-85ed-c176d2b153e0_3',
startPoint: { x: 329.1111068725586, y: 249.1111068725586 },
endPoint: { x: 329.1111068725586, y: 335.1111068725586 },
pointsList: [
{ x: 329.1111068725586, y: 249.1111068725586 },
{ x: 329.1111068725586, y: 335.1111068725586 }
]
},
{
id: '238d6ce5-03fa-40b2-ab46-7fdbd224a2e7',
type: 'polyline',
properties: {},
sourceNodeId: '0865bdd5-fd06-40a6-85ed-c176d2b153e0',
targetNodeId: 'e35754f0-c85a-4d70-8bca-f0b995a2b31e',
sourceAnchorId: '0865bdd5-fd06-40a6-85ed-c176d2b153e0_2',
targetAnchorId: 'e35754f0-c85a-4d70-8bca-f0b995a2b31e_3',
startPoint: { x: 329.1111068725586, y: 375.1111068725586 },
endPoint: { x: 329.1111068725586, y: 468.1111068725586 },
pointsList: [
{ x: 329.1111068725586, y: 375.1111068725586 },
{ x: 329.1111068725586, y: 468.1111068725586 }
]
}
]
}

@ -113,7 +113,39 @@
font-size: 14px;
color: var(--ds-color-info);
}
.el-tabs__item{
.el-tabs__item {
padding: 0 14px;
}
}
/* el-dropdown-menu */
/* el-popper */
.el-dropdown__popper.el-popper,
.el-dropdown__popper.el-popper .el-popper__arrow:before {
border: none;
background-color: var(--ds-bg-color-light-4);
color: var(--ds-color-info);
}
.el-dropdown__popper {
.el-dropdown-menu__item:not(.is-disabled):focus,
.el-dropdown-menu__item:not(.is-disabled):hover {
background-color: var(--ds-color-primary);
color: var(--ds-color-info);
}
}
.ds-popper-dropdown {
.title {
padding: 5px 16px;
line-height: 22px;
border-bottom: 1px solid var(--ds-bg-color-light-3);
}
.el-dropdown-menu__item {
color: var(--ds-color-info);
}
.el-dropdown-menu--large {
padding: 0;
.el-dropdown-menu__item {
padding: 10px 16px;
}
}
}

@ -1,5 +1,5 @@
/* //TODO0715 logicFlow 设计样式 */
/* logicFlow 设计样式 */
$base-menu-color: #fff;
$base-menu-color-active: #000;
$base-menu-color-hover: #000;

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2025-07-15 11:26:14
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2025-07-17 15:29:05
* @LastEditTime: 2025-07-21 16:16:41
* @FilePath: \Robot-Al-Platform-Web\src\renderer\src\views\Design\Controls\flowCtrl.vue
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
@ -71,11 +71,6 @@ const editableTabs = ref([
title: '流程1',
name: '1',
content: ''
},
{
title: '流程2',
name: '2',
content: ''
}
])

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2025-07-03 10:36:38
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2025-07-17 16:20:55
* @LastEditTime: 2025-07-23 14:31:46
* @FilePath: \Robot-Al-Platform-Web\src\renderer\src\views\Design\Controls\navCtrl.vue
* @Description: 顶部操作栏
-->
@ -12,7 +12,7 @@
<template v-for="(item, index) in navControlsConf" :key="index">
<el-button size="small" class="custom-btn" @click="handleClick(item)">
<img class="nav-icon" :src="item.icon" alt="" />
<span>{{ item.text }}</span>
<span>{{ item.label }}</span>
</el-button>
</template>
</div>

@ -43,13 +43,15 @@
}
}
}
.panel-controls-menu{
.panel-controls-menu-box {
// background-color: red;
.panel-controls-menu {
background-color: transparent !important;
.node-content {
.node-icon {
background-color: #565656 !important;
width: 24px;
height: 24px !important;
}
}
}
}

@ -6,6 +6,8 @@
<el-dropdown trigger="click" placement="right-start">
<img class="panel-icon" :src="v.icon" alt="" />
<template #dropdown>
<div class="panel-controls-menu-box ds-popper-dropdown">
<p class="title">{{ v.label }}</p>
<el-dropdown-menu class="panel-controls-menu">
<el-dropdown-item v-for="item in v?.children" :key="item?.type" class="node-item">
<div
@ -20,24 +22,18 @@
</div>
</el-dropdown-item>
</el-dropdown-menu>
</div>
</template>
</el-dropdown>
</el-button>
</div>
</div>
</template>
<script lang="ts" setup>
import draggable from 'vuedraggable'
import GatherIcon from '@/assets/images/panelBar/gather.png' //
import LocateIcon from '@/assets/images/panelBar/locate.png' //
import IdentifyIcon from '@/assets/images/panelBar/identify.png' //
import CalibrateIcon from '@/assets/images/panelBar/calibrate.png' //
import ImageProcessingIcon from '@/assets/images/panelBar/image_processing.png' //
import ColorProcessingIcon from '@/assets/images/panelBar/color_processing.png' //
import ImageGenerationIcon from '@/assets/images/panelBar/image_generation.png' //
import LogicalToolsIcon from '@/assets/images/panelBar/logical_tools.png' //
import CommunicationIcon from '@/assets/images/panelBar/communication.png' //
import DeepLearningIcon from '@/assets/images/panelBar/deep_learning.png' //
import { panelControlsConf } from '@/config/designControl'
defineOptions({
name: 'PanelControlBar'
})
@ -47,84 +43,7 @@ const props = defineProps({
type: Object
}
})
const nodeTypes = [
{
icon: GatherIcon,
text: '采集',
children: [
{
type: 'image-node',
label: '图像源',
icon: LocateIcon,
style: { fill: '#F5F5F5', stroke: '#1890FF' }
},
{
type: 'operation-node',
label: '多图采集',
icon: IdentifyIcon,
style: { fill: '#F5F5F5', stroke: '#52C41A' }
},
{
type: 'view',
label: '输出图像',
icon: CalibrateIcon,
style: { fill: '#F5F5F5', stroke: '#FAAD14' }
},
{
type: 'picture',
label: '缓存图像',
icon: ImageProcessingIcon,
style: { fill: '#F5F5F5', stroke: '#F5222D' }
}
]
},
{
icon: LocateIcon,
text: '定位'
},
{
icon: IdentifyIcon,
text: '识别'
},
{
icon: CalibrateIcon,
text: '校准'
},
{
icon: ImageProcessingIcon,
text: '图片处理'
},
{
icon: ColorProcessingIcon,
text: '色彩处理'
},
{
icon: ImageGenerationIcon,
text: '图片生成'
},
{
icon: CommunicationIcon,
text: '通讯'
},
{
icon: DeepLearningIcon,
text: '深度学习'
}
]
// const handleDragStart = (item: any) => {
// ElMessage.info(`: ${item.label}`)
// // 使
// }
// const startDrag = (item: any) => {
// // mousedown
// const event = window.event as DragEvent
// if (event && event.dataTransfer) {
// event.dataTransfer.setData('logicflow/node', item.type)
// }
// }
const nodeTypes = panelControlsConf
const handleDragStart = (event: DragEvent, node: Record<string, any>) => {
if (event.dataTransfer) {
// event.dataTransfer.setData('application/node-type', node);
@ -132,9 +51,9 @@ const handleDragStart = (event: DragEvent, node: Record<string, any>) => {
}
console.log('handleDragStart', event, node)
//
}
</script>
<style lang="scss">
@import url('./panelCtrl.scss');
</style>

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2025-07-03 10:27:47
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2025-07-17 16:01:16
* @LastEditTime: 2025-07-23 16:09:34
* @FilePath: \electron-project\Robot-Al\Robot-Al-Platform-Web\src\renderer\src\views\Design\Workflow\logicFlowView.vue
* @Description: 流程设计器面板
-->
@ -30,13 +30,13 @@
<div id="lf-container" @dragover="handleDragOver" @drop="handleDrop"></div>
</div>
</div>
<div class="attr-model-box" v-if="showAttribute"></div>
</div>
</template>
<script setup lang="ts">
import LogicFlow, { RectNode } from '@logicflow/core'
// import '@logicflow/core/dist/style/index.css';
// import '@logicflow/extension/lib/style/index.css'
import { Menu, Snapshot, MiniMap } from '@logicflow/extension'
import CalibrateIcon from '@/assets/images/panelBar/calibrate.png'
import { DSButton } from '@/components/Button'
@ -57,6 +57,12 @@ const { graphData } = useLogicFlow()
const lf = ref<LogicFlow | null>(null)
const flowDetail = reactive({})
//
const hideAttrPanel = () => {
showAttribute.value = false
}
//
const initDesignFlow = (record) => {
console.log('initDesignFlow_record', record.type)
if (!showLf.value) {
@ -103,12 +109,17 @@ const setEdgeType = (data) => {
//
const initEvents = () => {
lf.value.on('node:dbclick', ({ data }) => {
lf.value.on('node:click', ({ data }) => {
nodeData.value = data
console.log('node:click-nodeData', nodeData.value)
if (['imageNode'].includes(data.type)) {
showAttribute.value = true
}
})
lf.value.on('node:dbclick', ({ data }) => {
nodeData.value = data
console.log('node:dbclick-nodeData', nodeData.value)
})
lf.value.on('edge:dbclick', ({ data }) => {
nodeData.value = data
showAttribute.value = true
@ -119,11 +130,12 @@ const initEvents = () => {
showAttribute.value = true
})
lf.value.on('element:click', () => {
// hideAddPanel() //
hideAttrPanel() //
// console.log(lf.value.getGraphData(), 'getGraphData_click', JSON.stringify(lf.value.getGraphData()))
})
lf.value.on('blank:contextmenu', (e, position) => {
console.log('blank_contextmenu', e, position)
// hideAddPanel() //
// hideAttrPanel() //
})
lf.value.on('connection:not-allowed', (data) => {
if (data.msg) {
@ -138,7 +150,8 @@ const initEvents = () => {
//
const initRegisterNode = () => {
lf.value.batchRegister([OperationNode, ImageNode])
console.log(ImageNode, 'initRegisterNode_ImageNode')
lf.value.batchRegister([...OperationNode, ImageNode])
showTop.value = true
// lf.value.render() //
initEvents()
@ -205,7 +218,6 @@ const handleDrop = (e: DragEvent) => {
// properties: dragData.value.properties || {}
})
// lf.value.render()
//
// dragData.value = null
}
@ -220,5 +232,4 @@ defineExpose({ initDesignFlow })
<style lang="scss" scoped>
@import url('./logicFlowView.scss');
@import url('@/styles/logic-flow-core.scss');
</style>

Loading…
Cancel
Save