Przeglądaj źródła

feat: 流程设计

zhanghaijun 1 rok temu
rodzic
commit
9d9640085a

+ 1 - 1
.prettierrc

@@ -1,5 +1,5 @@
 {
-  "printWidth": 100,
+  "printWidth": 200,
   "tabWidth": 2,
   "useTabs": false,
   "semi": false,

+ 18 - 0
src/api/auth.api.ts

@@ -0,0 +1,18 @@
+import request from '@/utils/http'
+
+interface LoginParams {
+  userName: string
+  password: string
+}
+interface LoginResponse {
+  token: string
+  refreshToken: string
+}
+
+export class AuthService {
+  // 登录
+  static login = (params: LoginParams) =>
+    request.post<LoginResponse>({ url: '/auth/login', params })
+  // 退出登录
+  static logout = () => request.post({ url: '/auth/logout' })
+}

+ 13 - 0
src/api/course.api.ts

@@ -0,0 +1,13 @@
+export interface Course {
+  courseNumber: string // 课程编号
+  courseName: string // 课程名称
+  courseDesc: string // 课程描述
+  courseFlow: string // 课程流程
+  courseType: string // 课程类型,基础操作/故障处置/非正常处置
+  courseTarget: string // 培训对象,行车调度员/电力调度员/供电检修工
+  courseDuration: number // 课程时长
+  courseLine: string // 培训线路,如:成渝高铁线/成西高铁线/青藏高铁线
+  courseImage: string // 课程封面图片
+  authorName: string // 作者名称
+  authorAvatar: string // 作者头像
+}

+ 41 - 0
src/components/business/EasyProcess/common/data.ts

@@ -0,0 +1,41 @@
+import { EasyProcess } from './data.type'
+
+export const nodeConfigData: Record<EasyProcess.NodeType, EasyProcess.Node> = {
+  start: {
+    title: '发起人',
+    color: '#FFFFFF',
+    bgColor: '#1e83e9',
+    canAdd: false,
+    canRemoved: false,
+    hasDrawer: false,
+    icon: { name: 'start', color: '#1e83e9' },
+    defaultNode: { nodeName: '发起人', nodeType: 'start', nodeData: {} }
+  },
+  router: {
+    title: '条件分支',
+    canAdd: true,
+    hasDrawer: false,
+    icon: { name: 'router', color: '#3CB371' },
+    defaultNode: {
+      nodeName: '路由',
+      nodeType: 'router',
+      nodeData: {},
+      conditionNodes: [
+        { nodeName: '条件', nodeType: 'condition', isLastCondition: false, nodeData: {} },
+        { nodeName: '条件', nodeType: 'condition', isLastCondition: true, nodeData: {} }
+      ]
+    }
+  },
+  condition: {
+    title: '条件',
+    color: '#FFFFFF',
+    bgColor: '#3CB371',
+    canAdd: false,
+    canRemoved: true,
+    hasDrawer: true,
+    icon: { name: 'condition', color: '#3CB371' },
+    defaultNode: { nodeName: '条件', nodeType: 'condition', isLastCondition: false, nodeData: {} }
+  }
+}
+
+export const blankProcessData: EasyProcess.NodeConfig = nodeConfigData['start'].defaultNode

+ 59 - 0
src/components/business/EasyProcess/common/data.type.d.ts

@@ -0,0 +1,59 @@
+/**
+ * EasyProcess 相关类型定义
+ */
+export declare namespace EasyProcess {
+  /**
+   * ==============================
+   * 流程配置结构定义
+   * ==============================
+   */
+  export interface Node {
+    title: string // 节点标题
+    color?: string // 节点标题颜色
+    bgColor?: string // 节点标题背景颜色
+    canAdd: boolean // 节点是否可以增加
+    canRemoved?: boolean // 节点是否能够移除
+    hasDrawer: boolean // 节点是否可以进行配置
+    icon: {
+      name: string // 图标名
+      color: string // 图标颜色
+    }
+    defaultNode: NodeConfig // 默认节点结构,用于添加节点时
+  }
+  /**
+   * ==============================
+   * 流程数据结构定义
+   * ==============================
+   */
+  // 节点类型枚举
+  export type BaseType = 'start' | 'router' | 'condition'
+  export type NodeType = BaseType | (string & { _?: never })
+  // 基础节点配置
+  export interface BaseNode {
+    nodeName: string
+    nodeType: NodeType
+    nodeData?: Record<string, unknown>
+  }
+
+  // 通用节点,支持 childNode
+  export interface NormalNode extends BaseNode {
+    nodeType: Exclude<NodeType, 'router' | 'condition'>
+    childNode?: NodeConfig
+  }
+
+  // 路由节点,包含条件分支和一个默认 childNode
+  export interface RouterNode extends BaseNode {
+    nodeType: 'router'
+    conditionNodes: ConditionNode[]
+    childNode?: NodeConfig
+  }
+
+  // 条件节点,包含一个条件配置和子节点
+  export interface ConditionNode extends BaseNode {
+    nodeType: 'condition'
+    isLastCondition: boolean
+    childNode?: NodeConfig
+  }
+  // 节点配置类型,可以是普通节点、路由节点或条件节点
+  export type NodeConfig = NormalNode | RouterNode | ConditionNode
+}

+ 0 - 0
src/components/business/EasyProcess/config/data.ts


+ 0 - 36
src/components/business/EasyProcess/config/type.d.ts

@@ -1,36 +0,0 @@
-/**
- * EasyProcess 相关类型定义
- */
-declare namespace EasyProcess {
-  type NodeType = 'start' | 'end' | 'router' | 'condition'
-
-  interface NodeConfig {
-    [key: NodeType]: unknown
-  }
-  interface NodeConfigData {
-    title: string // 节点标题
-    description: string // 节点描述
-    icon: {
-      name: string // 节点图标名称
-      color: string // 节点图标颜色
-    }
-    defaultNode: NodeData // 默认节点数据,用于添加节点时使用
-  }
-
-  interface Node {
-    nodeId?: string // 节点唯一标识
-    nodeType: NodeType // 节点类型
-    nodeName: string // 节点名称
-    childNode?: Node | null // 子节点,仅路由节点使用
-    conditionNodes?: Node[] // 条件节点数组,仅路由节点使用
-    isLastCondition?: boolean // 是否是最后一个条件节点,仅条件节点使用
-    config: unknown // 节点配置
-  }
-
-  interface NodeData {
-    icon?: {
-      name: string
-      color: string
-    }
-  }
-}

+ 2 - 6
src/components/business/EasyProcess/ProcessDesigner.vue

@@ -35,10 +35,10 @@
   import EndNode from './node/end/endNode.vue'
 
   import { ref, watchEffect, provide, nextTick } from 'vue'
-  import { defaultConfig } from './config/defaultConfig'
   import { copy } from './utils/tools'
   import { createValidator } from './utils/validator'
   import { KEY_VALIDATOR, KEY_PROCESS_DATA } from './config/keys'
+  import { blankProcessData } from './common/data'
 
   const props = defineProps({
     data: {
@@ -61,11 +61,7 @@
   provide(KEY_PROCESS_DATA, processData)
 
   watchEffect(() => {
-    if (props.data?.nodeConfig) {
-      processData.value = copy(props.data)
-    } else {
-      processData.value = copy(defaultConfig)
-    }
+    processData.value = copy(props.data?.nodeConfig ? props.data : blankProcessData)
     nextTick(() => validate())
   })
 

+ 15 - 11
src/components/business/EasyProcess/node/NodeWrap.vue

@@ -3,9 +3,19 @@
     <!-- 路由节点 -->
     <RouterNode :node="props.node" @removeNode="removeNode" v-if="props.node.nodeType == ROUTER" />
     <!-- 普通节点 -->
-    <BaseNode :node="props.node" :conditionNodes="props.conditionNodes" :conditionIndex="props.conditionIndex" @removeNode="removeNode" v-else />
+    <BaseNode
+      :node="props.node"
+      :conditionNodes="props.conditionNodes"
+      :conditionIndex="props.conditionIndex"
+      @removeNode="removeNode"
+      v-else
+    />
     <!-- 子节点 -->
-    <NodeWrap :node="props.node.childNode" @removeNode="removeChildNode" v-if="props.node.childNode && props.node.childNode.nodeType" />
+    <NodeWrap
+      :node="props.node.childNode"
+      @removeNode="removeChildNode"
+      v-if="props.node.childNode && props.node.childNode.nodeType"
+    />
   </div>
 </template>
 
@@ -13,19 +23,19 @@
   defineOptions({ name: 'NodeWrap' })
   import BaseNode from './base/BaseNode.vue'
   import RouterNode from './router/routerNode.vue'
-  import { ref, onMounted, getCurrentInstance } from 'vue'
+  import { onMounted } from 'vue'
   import { ROUTER } from '../config/nodeType'
 
   const props = defineProps({
     node: {
       // 当前流程节点数据
       type: Object,
-      default: {}
+      default: () => {}
     },
     conditionNodes: {
       // 条件集合,当节点类型为condition时有效
       type: Array,
-      default: []
+      default: () => []
     },
     conditionIndex: {
       // 当前条件节点的顺序,当节点类型为condition时有效
@@ -38,12 +48,6 @@
       default: true
     }
   })
-
-  const { proxy } = getCurrentInstance()
-
-  // 流程配置数据
-  let config = ref({})
-
   onMounted(async () => {})
 
   // 移除当前节点

+ 2 - 7
src/components/business/EasyProcess/node/approver/approverNode.vue

@@ -4,8 +4,8 @@
 </template>
 
 <script setup name="ApproverNode">
-  import { getCurrentInstance, inject } from 'vue'
-  import { KEY_VALIDATOR, KEY_PROCESS_DATA } from '../../config/keys'
+  import { inject } from 'vue'
+  import { KEY_VALIDATOR } from '../../config/keys'
 
   const props = defineProps({
     tempNodeId: {
@@ -18,11 +18,6 @@
       default: () => {}
     }
   })
-
-  const { proxy } = getCurrentInstance()
-
-  // 获取流程数据
-  const processData = inject(KEY_PROCESS_DATA)
   // 获取流程验证器实例
   const validator = inject(KEY_VALIDATOR)
 

+ 19 - 3
src/components/business/EasyProcess/node/base/AddNode.vue

@@ -1,8 +1,20 @@
 <template>
   <div class="ep-node-add">
-    <div ref="nodeAddBtn" class="ep-node-add-btn" v-on:mouseenter="showAddSelect(true)" v-on:mouseleave="showAddSelect(false)">
+    <div
+      ref="nodeAddBtn"
+      class="ep-node-add-btn"
+      v-on:mouseenter="showAddSelect(true)"
+      v-on:mouseleave="showAddSelect(false)"
+    >
       <svg-icon icon-class="plus" class="ep-node-add-btn-icon" color="#FFFFFF" />
-      <div ref="nodeAddSelect" :class="['ep-node-add-select-box', nodeAddSelectPostion == 1 ? 'ep-node-add-left' : 'ep-node-add-right']" v-if="isShowAddSelect">
+      <div
+        ref="nodeAddSelect"
+        :class="[
+          'ep-node-add-select-box',
+          nodeAddSelectPostion == 1 ? 'ep-node-add-left' : 'ep-node-add-right'
+        ]"
+        v-if="isShowAddSelect"
+      >
         <div
           :class="{ 'ep-node-add-select-item': true, 'ep-node-add-selected': item.selected }"
           v-for="(item, index) in nodeSelect"
@@ -11,7 +23,11 @@
           v-on:mouseenter="addNodeSelected(item, true)"
           v-on:mouseleave="addNodeSelected(item, false)"
         >
-          <svg-icon :icon-class="item.icon.name" class="ep-node-add-select-item-icon" :color="item.selected ? '#FFFFFF' : item.icon.color" />
+          <svg-icon
+            :icon-class="item.icon.name"
+            class="ep-node-add-select-item-icon"
+            :color="item.selected ? '#FFFFFF' : item.icon.color"
+          />
           <div class="ep-node-add-select-item-title">
             {{ item.title }}
           </div>

+ 4 - 4
src/components/business/EasyProcess/node/base/BaseDrawer.vue

@@ -15,7 +15,7 @@
   import Drawer from '@/components/business/Drawer/Drawer.vue'
   import Button from '@/components/business/Button/Button.vue'
   import { ref, shallowRef, defineAsyncComponent } from 'vue'
-  import { nodeConfig } from '../../config/nodeConfig'
+  import { nodeConfigData } from '../../common/data'
   import { copy } from '../../utils/tools'
 
   // 节点数据的副本
@@ -28,8 +28,8 @@
   // 加载节点抽屉组件
   const modules = import.meta.glob('../*/*Drawer.vue')
   const drawerComponents = shallowRef({})
-  Object.keys(nodeConfig).forEach((key) => {
-    let item = nodeConfig[key]
+  Object.keys(nodeConfigData).forEach((key) => {
+    let item = nodeConfigData[key]
     if (item.hasDrawer) {
       let component = defineAsyncComponent(modules[`../${key}/${key}Drawer.vue`])
       drawerComponents.value[key] = component
@@ -40,7 +40,7 @@
   const show = (data) => {
     // 复制数据
     node.value = copy(data)
-    config.value = nodeConfig[node.value.nodeType]
+    config.value = nodeConfigData[node.value.nodeType]
 
     isShow.value = true
   }

+ 45 - 7
src/components/business/EasyProcess/node/base/BaseNode.vue

@@ -1,15 +1,33 @@
 <template>
   <div :class="{ 'ep-node': true, 'ep-node-arrows': !isStart }">
-    <div :class="{ 'ep-node-content': true, 'ep-node-error': isError }" @mouseenter="mouseenter(true)" @mouseleave="mouseleave(false)">
+    <div
+      :class="{ 'ep-node-content': true, 'ep-node-error': isError }"
+      @mouseenter="mouseenter(true)"
+      @mouseleave="mouseleave(false)"
+    >
       <!-- header -->
-      <div class="ep-node-header" :style="{ color: config.color, 'background-color': config.bgColor }">
+      <div
+        class="ep-node-header"
+        :style="{ color: config.color, 'background-color': config.bgColor }"
+      >
         <svg-icon :icon-class="config.icon.name" class="ep-node-icon" color="#FFFFFF" />
         <div class="ep-node-header-title">{{ config.title }}</div>
-        <svg-icon icon-class="close" class="ep-node-close" color="#FFFFFF" v-if="canRemoved" @click="removeNode" />
+        <svg-icon
+          icon-class="close"
+          class="ep-node-close"
+          color="#FFFFFF"
+          v-if="canRemoved"
+          @click="removeNode"
+        />
       </div>
       <!-- body -->
       <div class="ep-node-body" @click="showNodeDrawer">
-        <component ref="node" :is="nodeComponents[props.node.nodeType]" :tempNodeId="tempNodeId" :node="props.node" />
+        <component
+          ref="node"
+          :is="nodeComponents[props.node.nodeType]"
+          :tempNodeId="tempNodeId"
+          :node="props.node"
+        />
       </div>
       <!-- 同级节点左移动 -->
       <div class="ep-node-move ep-node-move-left" v-if="isShowLeftMoveBtn">
@@ -36,7 +54,13 @@
       <!-- 校验错误提示 -->
       <div class="ep-node-error-msg" v-if="isError">
         <div class="ep-node-error-msg-box">
-          <svg-icon icon-class="tips" class="ep-node-error-icon" color="red" @mouseenter="showErrorTips(true)" @mouseleave="showErrorTips(false)" />
+          <svg-icon
+            icon-class="tips"
+            class="ep-node-error-icon"
+            color="red"
+            @mouseenter="showErrorTips(true)"
+            @mouseleave="showErrorTips(false)"
+          />
           <div class="ep-node-error-tips" v-if="errorTips && errorMsg">{{ errorMsg }}</div>
         </div>
       </div>
@@ -44,14 +68,28 @@
     <AddNode :node="props.node" />
 
     <!-- 节点配置Drawer -->
-    <BaseDrawer ref="nodeDrawer" @updateConfig="updateConfig" @cancelUpdateConfig="cancelUpdateConfig" />
+    <BaseDrawer
+      ref="nodeDrawer"
+      @updateConfig="updateConfig"
+      @cancelUpdateConfig="cancelUpdateConfig"
+    />
   </div>
 </template>
 
 <script setup name="BaseNode">
   import BaseDrawer from './BaseDrawer.vue'
   import AddNode from './AddNode.vue'
-  import { ref, shallowRef, onMounted, getCurrentInstance, defineAsyncComponent, watch, computed, onUnmounted, inject } from 'vue'
+  import {
+    ref,
+    shallowRef,
+    onMounted,
+    getCurrentInstance,
+    defineAsyncComponent,
+    watch,
+    computed,
+    onUnmounted,
+    inject
+  } from 'vue'
   import { nodeConfig } from '../../config/nodeConfig'
   import { getUUID } from '../../utils/tools'
   import { START, CONDITION } from '../../config/nodeType'

+ 13 - 10
src/components/business/EasyProcess/node/router/routerNode.vue

@@ -3,9 +3,18 @@
   <div class="ep-node-router">
     <div class="ep-condition-node-add" @click="addCondition">添加条件</div>
     <div class="ep-node-router-box">
-      <div v-for="(condition, index) in props.node.conditionNodes" :key="condition.id || index" class="ep-node-router-col">
+      <div
+        v-for="(condition, index) in props.node.conditionNodes"
+        :key="condition.id || index"
+        class="ep-node-router-col"
+      >
         <!-- 生成节点 -->
-        <NodeWrap :node="condition" :conditionNodes="props.node.conditionNodes" :conditionIndex="index" @removeNode="removeCondition(index)" />
+        <NodeWrap
+          :node="condition"
+          :conditionNodes="props.node.conditionNodes"
+          :conditionIndex="index"
+          @removeNode="removeCondition(index)"
+        />
         <!-- 用来遮挡最左列的线 -->
         <template v-if="index == 0">
           <div class="cover-line top-left-cover-line"></div>
@@ -26,7 +35,7 @@
 <script setup name="RouterNode">
   import NodeWrap from '../NodeWrap.vue'
   import AddNode from '../base/AddNode.vue'
-  import { ref, onMounted, getCurrentInstance } from 'vue'
+  import { onMounted } from 'vue'
   import { copy } from '../../utils/tools'
   import { nodeConfig } from '../../config/nodeConfig'
   import { CONDITION } from '../../config/nodeType'
@@ -35,15 +44,9 @@
     node: {
       // 传入的流程配置数据
       type: Object,
-      default: {}
+      default: () => {}
     }
   })
-
-  const { proxy } = getCurrentInstance()
-
-  // 流程配置数据
-  let config = ref({})
-
   onMounted(async () => {})
 
   // 移除条件

+ 1 - 9
src/components/business/EasyProcess/node/start/startDrawer.vue

@@ -10,21 +10,13 @@
 </template>
 
 <script setup name="StartDrawer">
-  import { getCurrentInstance, inject } from 'vue'
-  import { KEY_PROCESS_DATA } from '../../config/keys'
-
   const props = defineProps({
     config: {
       // 传入的流程配置数据
       type: Object,
-      default: {}
+      default: () => {}
     }
   })
-
-  const { proxy } = getCurrentInstance()
-
-  // 获取流程数据
-  const processData = inject(KEY_PROCESS_DATA)
 </script>
 
 <style lang="scss" scoped></style>

+ 2 - 7
src/components/business/EasyProcess/node/start/startNode.vue

@@ -4,8 +4,8 @@
 </template>
 
 <script setup name="StartNode">
-  import { getCurrentInstance, inject } from 'vue'
-  import { KEY_PROCESS_DATA, KEY_VALIDATOR } from '../../config/keys'
+  import { inject } from 'vue'
+  import { KEY_VALIDATOR } from '../../config/keys'
 
   const props = defineProps({
     tempNodeId: {
@@ -18,11 +18,6 @@
       default: {}
     }
   })
-
-  const { proxy } = getCurrentInstance()
-
-  // 获取流程数据
-  const processData = inject(KEY_PROCESS_DATA)
   // 获取流程验证器实例
   const validator = inject(KEY_VALIDATOR)
 

+ 1 - 4
src/components/icon/load-svg.ts

@@ -37,10 +37,7 @@ function parseSvg(svgData: string): IconifyIcon {
  * <Icon icon="svg:avatar"></Icon>
  */
 async function loadSvgIcons() {
-  const svgEagers = import.meta.glob('./svg/**', {
-    eager: true,
-    query: '?raw'
-  })
+  const svgEagers = import.meta.glob('./svg/**', { eager: true, query: '?raw' })
 
   await Promise.all(
     Object.entries(svgEagers).map((svg) => {

+ 0 - 1
src/utils/constants/index.ts

@@ -2,5 +2,4 @@
  * 常量定义相关工具函数统一导出
  */
 
-export * from './links'
 export * from './iconfont'

+ 0 - 22
src/utils/constants/links.ts

@@ -1,22 +0,0 @@
-export const WEB_LINKS = {
-  // Github 主页
-  GITHUB_HOME: 'https://gitee.com/mldong',
-
-  // 项目 Github 主页
-  GITHUB: 'https://gitee.com/mldong/mldong-art-design',
-
-  // 个人博客
-  BLOG: 'https://www.mldong.com',
-
-  // 项目文档
-  DOCS: 'https://doc.mldong.com/art-design/',
-
-  // 项目社区
-  COMMUNITY: 'https://www.mldong.com/',
-
-  // 个人 Bilibili 主页
-  BILIBILI: 'https://space.bilibili.com/1395438398',
-
-  // 项目介绍
-  INTRODUCE: 'https://doc.mldong.com/art-design/'
-}

+ 6 - 6
src/views/auth/login/index.vue

@@ -81,15 +81,15 @@
                   handlerBg="var(--art-main-bg-color)"
                 />
               </div>
-              <p class="error-text" :class="{ 'show-error-text': !isPassing && isClickPass }">{{
-                $t('login.placeholder[2]')
-              }}</p>
+              <p class="error-text" :class="{ 'show-error-text': !isPassing && isClickPass }">
+                {{ $t('login.placeholder[2]') }}
+              </p>
             </div>
 
             <div class="forget-password">
-              <ElCheckbox v-model="formData.rememberPassword">{{
-                $t('login.rememberPwd')
-              }}</ElCheckbox>
+              <ElCheckbox v-model="formData.rememberPassword">
+                {{ $t('login.rememberPwd') }}
+              </ElCheckbox>
               <RouterLink :to="RoutesAlias.ForgetPassword">{{ $t('login.forgetPwd') }}</RouterLink>
             </div>
 

+ 0 - 139
src/views/dashboard/console/widget/AboutProject.vue

@@ -1,139 +0,0 @@
-<template>
-  <div class="card about-project art-custom-card">
-    <div>
-      <h2 class="box-title">关于项目</h2>
-      <p>{{ systemName }} 是一款专注于用户体验和视觉设计的后台管理系统模版</p>
-      <p>使用了 Vue3、TypeScript、Vite、Element Plus 等前沿技术</p>
-
-      <div class="button-wrap">
-        <div class="btn art-custom-card" @click="goPage(WEB_LINKS.DOCS)">
-          <span>项目官网</span>
-          <i class="iconfont-sys">&#xe703;</i>
-        </div>
-        <div class="btn art-custom-card" @click="goPage(WEB_LINKS.INTRODUCE)">
-          <span>文档</span>
-          <i class="iconfont-sys">&#xe703;</i>
-        </div>
-        <div class="btn art-custom-card" @click="goPage(WEB_LINKS.GITHUB_HOME)">
-          <span>Github</span>
-          <i class="iconfont-sys">&#xe703;</i>
-        </div>
-        <div class="btn art-custom-card" @click="goPage(WEB_LINKS.BLOG)">
-          <span>博客</span>
-          <i class="iconfont-sys">&#xe703;</i>
-        </div>
-      </div>
-    </div>
-    <img class="right-img" src="@imgs/draw/draw1.png" alt="draw1" />
-  </div>
-</template>
-
-<script setup lang="ts">
-  import AppConfig from '@/config'
-  import { WEB_LINKS } from '@/utils/constants'
-
-  const systemName = AppConfig.systemInfo.name
-
-  const goPage = (url: string) => {
-    window.open(url)
-  }
-</script>
-
-<style lang="scss" scoped>
-  .about-project {
-    box-sizing: border-box;
-    display: flex;
-    justify-content: space-between;
-    height: 300px;
-    padding: 20px;
-
-    h2 {
-      margin-top: 10px;
-      font-size: 20px;
-      font-weight: 500;
-      color: var(--art-gray-900) !important;
-    }
-
-    p {
-      margin-top: 5px;
-      font-size: 14px;
-      color: var(--art-gray-600);
-    }
-  }
-
-  .button-wrap {
-    display: flex;
-    flex-wrap: wrap;
-    width: 600px;
-    margin-top: 35px;
-  }
-
-  .btn {
-    display: flex;
-    align-items: center;
-    justify-content: space-between;
-    width: 240px;
-    height: 50px;
-    padding: 0 15px;
-    margin: 0 15px 15px 0;
-    font-size: 14px;
-    color: var(--art-gray-800);
-    cursor: pointer;
-    background: var(--art-bg-color);
-    border-radius: calc(var(--custom-radius) / 2 + 2px) !important;
-    transition: all 0.3s;
-
-    &:hover {
-      box-shadow: 0 5px 10px rgb(0 0 0 / 5%);
-      transform: translateY(-4px);
-    }
-  }
-
-  // 响应式设计 - iPad Pro及以下
-  @media screen and (max-width: $device-ipad-pro) {
-    .about-project {
-      height: auto;
-    }
-
-    .button-wrap {
-      width: 470px;
-      margin-top: 20px;
-    }
-
-    .btn {
-      width: 180px;
-    }
-
-    .right-img {
-      width: 300px;
-      height: 230px;
-    }
-  }
-
-  // 响应式设计 - iPad垂直及以下
-  @media screen and (max-width: $device-ipad-vertical) {
-    .button-wrap {
-      width: 100%;
-    }
-
-    .btn {
-      width: 190px;
-    }
-
-    .right-img {
-      display: none;
-    }
-  }
-
-  // 响应式设计 - 手机端
-  @media screen and (max-width: $device-phone) {
-    .about-project {
-      padding: 0 15px;
-    }
-
-    .btn {
-      width: 100%;
-      margin-right: 0;
-    }
-  }
-</style>

+ 1 - 1
src/views/train/monitor/course.vue

@@ -14,7 +14,7 @@
 </template>
 
 <script setup>
-  import ProcessDesigner from '@/components/business/EasyProcess/ProcessDesigner.vue'
+  import ProcessDesigner from '@/components/business/EasyProcess/index.vue'
   import { ElMessageBox } from 'element-plus'
   import { onMounted, ref } from 'vue'
   import mockData from './data/flow.json'