zhanghaijun 1 год назад
Родитель
Сommit
7cb0336d36

+ 0 - 19
src/router/routes/modules/base.ts

@@ -10,7 +10,6 @@ export const routes: AppRouteRecord[] = [
       order: 1,
       title: 'menus.dashboard.title',
       icon: ''
-      // roles: ['R_SUPER', 'R_ADMIN'] // 角色权限,前端控制模式(只有拥有这些角色的用户才能访问)
     },
     children: [
       {
@@ -22,24 +21,6 @@ export const routes: AppRouteRecord[] = [
           keepAlive: false,
           fixedTab: true
         }
-      },
-      {
-        path: 'analysis',
-        name: 'Analysis',
-        component: RoutesAlias.Analysis,
-        meta: {
-          title: 'menus.dashboard.analysis',
-          keepAlive: false
-        }
-      },
-      {
-        path: 'ecommerce',
-        name: 'Ecommerce',
-        component: RoutesAlias.Ecommerce,
-        meta: {
-          title: 'menus.dashboard.ecommerce',
-          keepAlive: false
-        }
       }
     ]
   }

+ 4 - 2
src/router/routes/modules/train.ts

@@ -38,7 +38,7 @@ export const routes: AppRouteRecord[] = [
         path: 'detail/:id',
         name: 'course:detail',
         component: '/train/course/detail',
-        meta: { title: '课程详情', hiddenInMenu: true, keepAlive: false }
+        meta: { title: '课程详情', isHide: true, keepAlive: false }
       },
       {
         path: 'evaluate',
@@ -64,7 +64,7 @@ export const routes: AppRouteRecord[] = [
         path: 'detail/:id',
         name: 'plan:detail',
         component: '/train/plan/detail',
-        meta: { title: '计划详情', hiddenInMenu: true, keepAlive: false }
+        meta: { title: '计划详情', isHide: true, keepAlive: false }
       }
     ]
   },
@@ -83,3 +83,5 @@ export const routes: AppRouteRecord[] = [
     ]
   }
 ]
+
+export default routes

+ 12 - 12
src/router/routes/staticRoutes.ts

@@ -23,18 +23,18 @@ export const staticRoutes: AppRouteRecordRaw[] = [
     component: () => import('@views/auth/login/index.vue'),
     meta: { title: 'menus.login.title', isHideTab: true, setTheme: true }
   },
-  {
-    path: RoutesAlias.Register,
-    name: 'Register',
-    component: () => import('@views/auth/register/index.vue'),
-    meta: { title: 'menus.register.title', isHideTab: true, noLogin: true, setTheme: true }
-  },
-  {
-    path: RoutesAlias.ForgetPassword,
-    name: 'ForgetPassword',
-    component: () => import('@views/auth/forget-password/index.vue'),
-    meta: { title: 'menus.forgetPassword.title', isHideTab: true, noLogin: true, setTheme: true }
-  },
+  // {
+  //   path: RoutesAlias.Register,
+  //   name: 'Register',
+  //   component: () => import('@views/auth/register/index.vue'),
+  //   meta: { title: 'menus.register.title', isHideTab: true, noLogin: true, setTheme: true }
+  // },
+  // {
+  //   path: RoutesAlias.ForgetPassword,
+  //   name: 'ForgetPassword',
+  //   component: () => import('@views/auth/forget-password/index.vue'),
+  //   meta: { title: 'menus.forgetPassword.title', isHideTab: true, noLogin: true, setTheme: true }
+  // },
   {
     path: '/403',
     name: 'Exception403',

+ 0 - 3
src/views/dashboard/console/index.vue

@@ -22,8 +22,6 @@
         <TodoList />
       </el-col>
     </el-row>
-
-    <AboutProject />
   </div>
 </template>
 
@@ -34,7 +32,6 @@
   import NewUser from './widget/NewUser.vue'
   import Dynamic from './widget/Dynamic.vue'
   import TodoList from './widget/TodoList.vue'
-  import AboutProject from './widget/AboutProject.vue'
   import { useCommon } from '@/composables/useCommon'
 
   defineOptions({ name: 'Console' })

+ 14 - 0
src/views/train/manager/schemas/user.api.ts

@@ -0,0 +1,14 @@
+import request from '@/utils/http'
+
+export class UserService {
+  // 分页查询用户
+  static page = (params: any) => request.post({ url: '/sys/user/page', params })
+  // 添加用户
+  static save = (params: any) => request.post({ url: '/sys/user/save', params })
+  // 修改用户
+  static update = (params: any) => request.post({ url: '/sys/user/update', params })
+  // 删除用户
+  static remove = (params: any) => request.post({ url: '/sys/user/remove', params })
+  // 用户详情
+  static detail = (params: any) => request.post({ url: '/sys/user/detail', params })
+}

+ 382 - 0
src/views/train/manager/schemas/user.tsx

@@ -0,0 +1,382 @@
+import { CrudSchema } from '@/components/crud'
+import { UserService } from './user.api'
+
+// crud配置
+export const crudSchema: CrudSchema = {
+  // 接口地址
+  api: UserService.page,
+  dialogTitle: '用户',
+  crudApi: {
+    // 新增接口
+    add: UserService.save,
+    // 修改接口
+    edit: UserService.update,
+    // 删除接口
+    remove: UserService.remove,
+    // 详情接口
+    view: UserService.detail
+  },
+  // 使用crud
+  useCrud: true,
+  // 是否有新增
+  hasAdd: true,
+  // 是否有删除
+  hasRemove: true,
+  // 是否有修改
+  hasEdit: true,
+  // 是否有详情
+  hasView: true,
+  // 新增权限码
+  addAuth: 'sys:user:save',
+  // 删除权限码
+  removeAuth: 'sys:user:remove',
+  // 修改权限码
+  editAuth: 'sys:user:update',
+  // 详情权限码
+  viewAuth: 'sys:user:detail',
+  // 表格列定义
+  columns: [
+    { type: 'selection' },
+    { prop: 'userName', label: '用户名' },
+    { prop: 'realName', label: '姓名' },
+    {
+      prop: 'isLocked',
+      label: '是否锁定',
+      component: 'ApiDict',
+      componentProps: {
+        code: 'yes_no',
+        typeMap: {
+          1: 'success',
+          0: 'danger'
+        },
+        useColorList: false
+      }
+    },
+    {
+      prop: 'roleIds',
+      label: '所属角色',
+      component: 'ApiSelect',
+      componentProps: { api: '/sys/role/select' }
+    },
+    { prop: 'mobilePhone', label: '手机号码' }
+  ],
+  // 搜索表单定义
+  searchFormSchema: {
+    schema: [
+      {
+        prop: 'm_LIKE_userName',
+        label: '用户名',
+        component: 'Input',
+        componentProps: { clearable: true, placeholder: '请输入用户名' },
+        colSpan: 6
+      },
+      {
+        prop: 'm_LIKE_realName',
+        label: '姓名',
+        component: 'Input',
+        componentProps: { clearable: true, placeholder: '请输入姓名' },
+        colSpan: 6
+      },
+      {
+        prop: 'm_LIKE_mobilePhone',
+        label: '手机号码',
+        component: 'Input',
+        componentProps: { clearable: true, placeholder: '请输入手机号码' },
+        colSpan: 6
+      },
+      {
+        prop: 'm_EQ_isLocked',
+        label: '是否锁定',
+        component: 'ApiDict',
+        componentProps: { clearable: true, code: 'yes_no', placeholder: '请选择是否锁定' },
+        colSpan: 6
+      }
+    ]
+  },
+  // 内置弹窗配置
+  dialogProps: {
+    dialogType: 'drawer'
+  },
+  // crud表单配置
+  formSchema: {
+    showDefaultActions: false,
+    labelWidth: '100px',
+    schema: [
+      // 用户ID(隐藏字段)
+      {
+        label: '用户ID',
+        prop: 'id',
+        component: 'Input',
+        colSpan: 12,
+        show: false,
+        ifDetail: false
+      },
+
+      // 基础信息分隔符
+      {
+        prop: 'baseinfo',
+        label: '',
+        labelWidth: '0px',
+        component: 'Divider',
+        colSpan: 24,
+        componentProps: {
+          title: '基础信息'
+        }
+      },
+
+      // 用户名
+      {
+        label: '用户名',
+        prop: 'userName',
+        component: 'Input',
+        colSpan: 12,
+        rules: [
+          {
+            required: true,
+            message: '请输入用户名'
+          }
+        ],
+        componentProps: {
+          placeholder: '请输入用户名',
+          clearable: true
+        }
+      },
+
+      // 姓名
+      {
+        label: '姓名',
+        prop: 'realName',
+        component: 'Input',
+        colSpan: 12,
+        rules: [
+          {
+            required: true,
+            message: '请输入姓名'
+          }
+        ],
+        componentProps: {
+          placeholder: '请输入姓名',
+          clearable: true
+        }
+      },
+
+      // 密码
+      {
+        label: '密码',
+        prop: 'password',
+        component: 'Input',
+        colSpan: 12,
+        ifShow(values) {
+          // 不存在id,则为新增,显示密码
+          return !values.id
+        },
+        ifDetail: false,
+        helpMessage: ['5-18位数字、字母、特殊字符组成。'],
+        rules: [
+          {
+            required: true,
+            message: '请输入密码'
+          },
+          {
+            pattern: /[\w!@#$%^&*]{5,18}/,
+            message: '密码由5-18位数字、字母、特殊字符组成。'
+          }
+        ],
+        componentProps: {
+          placeholder: '请输入密码',
+          clearable: true,
+          type: 'password'
+        }
+      },
+
+      // 确认密码
+      {
+        label: '确认密码',
+        prop: 'confirmPassword',
+        component: 'Input',
+        colSpan: 12,
+        ifShow(values) {
+          // 不存在id,则为新增,显示确认密码
+          return !values.id
+        },
+        ifDetail: false,
+        rules: [
+          {
+            required: true,
+            message: '请输入确认密码'
+          }
+        ],
+        componentProps: {
+          placeholder: '请输入确认密码',
+          clearable: true,
+          type: 'password'
+        }
+      },
+
+      // 昵称
+      {
+        label: '昵称',
+        prop: 'nickName',
+        component: 'Input',
+        colSpan: 12,
+        componentProps: {
+          placeholder: '请输入昵称',
+          clearable: true
+        }
+      },
+
+      // 性别
+      {
+        label: '性别',
+        prop: 'sex',
+        component: 'ApiDict',
+        defaultValue: 3,
+        colSpan: 12,
+        componentProps: {
+          placeholder: '请选择性别',
+          code: 'sex',
+          renderType: 'RadioGroup',
+          isBtn: true
+        }
+      },
+
+      // 邮箱
+      {
+        label: '邮箱',
+        prop: 'email',
+        component: 'Input',
+        colSpan: 12,
+        componentProps: {
+          placeholder: '请输入邮箱',
+          clearable: true
+        }
+      },
+
+      // 手机号码
+      {
+        label: '手机号码',
+        prop: 'mobilePhone',
+        component: 'Input',
+        colSpan: 12,
+        rules: [
+          {
+            required: true,
+            message: '请输入手机号码'
+          }
+        ],
+        componentProps: {
+          placeholder: '请输入手机号码',
+          clearable: true
+        }
+      },
+
+      // 其他信息分隔符
+      {
+        prop: 'otherinfo',
+        label: '',
+        labelWidth: '0px',
+        component: 'Divider',
+        colSpan: 24,
+        componentProps: {
+          title: '其他信息'
+        }
+      },
+
+      // 所属部门
+      {
+        label: '所属部门',
+        prop: 'deptId',
+        component: 'ApiTreeSelect',
+        colSpan: 12,
+        rules: [
+          {
+            required: true,
+            message: '请选择所属部门'
+          }
+        ],
+        componentProps: {
+          placeholder: '请选择所属部门',
+          clearable: true,
+          api: '/sys/dept/tree',
+          labelField: 'name',
+          valueField: 'id'
+        }
+      },
+
+      // 所属岗位
+      {
+        label: '所属岗位',
+        prop: 'postId',
+        component: 'ApiSelect',
+        colSpan: 12,
+        rules: [
+          {
+            required: true,
+            message: '请选择所属岗位'
+          }
+        ],
+        componentProps: {
+          placeholder: '请选择所属岗位',
+          clearable: true,
+          api: '/sys/post/select'
+        }
+      },
+
+      // 所属角色
+      {
+        label: '所属角色',
+        prop: 'roleIds',
+        component: 'ApiSelect',
+        colSpan: 24,
+        rules: [
+          {
+            required: true,
+            message: '请选择所属角色'
+          }
+        ],
+        ifShow: false,
+        ifDetail: true,
+        componentProps: {
+          placeholder: '请选择所属角色',
+          clearable: true,
+          api: '/sys/role/select',
+          multiple: true
+        }
+      },
+
+      // 联系电话
+      {
+        label: '联系电话',
+        prop: 'tel',
+        component: 'Input',
+        colSpan: 24,
+        componentProps: {
+          placeholder: '请输入联系电话',
+          clearable: true
+        }
+      },
+
+      // 头像
+      {
+        label: '头像',
+        prop: 'avatar',
+        component: 'Avatar',
+        colSpan: 24,
+        componentProps: {}
+      },
+
+      // 备注
+      {
+        label: '备注',
+        prop: 'remark',
+        component: 'Input',
+        colSpan: 24,
+        componentProps: {
+          type: 'textarea',
+          rows: 4,
+          placeholder: '请输入备注'
+        }
+      }
+    ]
+  }
+}

+ 39 - 8
src/views/train/manager/user.vue

@@ -2,16 +2,47 @@
 @description: 用户列表
 @creationTime: 2025-09-23
 -->
-
 <template>
-  <view>用户列表</view>
+  <div class="w-full art-full-height">
+    <BasicCrud @reset="handleReset" />
+  </div>
 </template>
+<script setup lang="tsx">
+  import { useCrud } from '@/components/crud'
+  import { crudSchema } from './schemas/user'
+  const grantRoleRef = ref()
+  const deptIdList = ref([])
 
-<script lang="ts" setup>
-  defineOptions({ name: '用户列表' })
-  /* ------------------------ 导入 与 引用 ----------------------------------- */
-  /* ------------------------ 函数 与 方法 ----------------------------------- */
-  /* ------------------------- 生命周期 -------------------------------------- */
+  const [BasicCrud, crudApi] = useCrud({
+    ...crudSchema,
+    beforeFetch: (params: any) => {
+      return { ...params, m_IN_deptId: deptIdList.value }
+    },
+    // hasAdd: true,
+    // 左侧工具栏
+    toolbarActions: [],
+    // 左侧栏工具-下拉菜单
+    dropDownToolbarActions: [],
+    // 表格行操作
+    tableActions: [],
+    // 表格行操作-下拉菜单
+    dropDownActions: [
+      {
+        label: '授权角色',
+        icon: 'ant-design:team-outlined',
+        type: 'primary',
+        link: true,
+        dialogRef: grantRoleRef,
+        dialogParams() {
+          return {
+            getCrudApi: () => crudApi
+          }
+        }
+      }
+    ]
+  })
+  const handleReset = () => {
+    deptIdList.value = []
+  }
 </script>
-
 <style lang="scss" scoped></style>

+ 64 - 8
src/views/train/monitor/course.vue

@@ -2,16 +2,72 @@
 @description: 课程监控
 @creationTime: 2025-09-23
 -->
-
 <template>
-  <div>课程监控</div>
+  <div class="app-container w-full art-full-height">
+    <div class="header">
+      <el-button type="primary" @click="publish" round>发布</el-button>
+    </div>
+    <div class="body flex-1">
+      <ProcessDesigner ref="processRef" :data="processData" />
+    </div>
+  </div>
 </template>
 
-<script lang="ts" setup>
-  defineOptions({ name: '课程监控' })
-  /* ------------------------ 导入 与 引用 ----------------------------------- */
-  /* ------------------------ 函数 与 方法 ----------------------------------- */
-  /* ------------------------- 生命周期 -------------------------------------- */
+<script setup>
+  import ProcessDesigner from '@/components/business/EasyProcess/ProcessDesigner.vue'
+  import { ElMessageBox } from 'element-plus'
+  import { onMounted, ref } from 'vue'
+  import mockData from './data/flow.json'
+
+  // 定义 ProcessDesigner 的实例类型
+  // type ProcessDesignerInstance = InstanceType<typeof ProcessDesigner>
+  // 审批数据
+  // const processData = ref<Record<string, any>>({})
+  // 组件实例 ref
+  // const processRef = ref<ProcessDesignerInstance | null>(null)
+
+  const processData = ref({})
+  const processRef = ref(null)
+
+  onMounted(() => {
+    processData.value = mockData
+  })
+
+  /**
+   * 发布流程
+   */
+  const publish = () => {
+    if (!processRef.value) return
+    processRef.value.validate((valid, messages) => {
+      if (valid) {
+        const result = processRef.value?.getResult()
+        console.info('发布流程:', result)
+        ElMessageBox.alert(JSON.stringify(result, null, 2), '结果')
+      } else {
+        ElMessageBox.alert(messages, '结果')
+      }
+    })
+  }
 </script>
 
-<style lang="scss" scoped></style>
+<style lang="scss" scoped>
+  .app-container {
+    display: flex;
+    flex-direction: column;
+    width: 100%;
+    overflow: hidden;
+    border: 1px solid #e8e8e8;
+
+    .header {
+      display: flex;
+      align-items: center;
+      justify-content: flex-end;
+      padding: 3px 50px;
+    }
+
+    .body {
+      flex: 1;
+      overflow: auto;
+    }
+  }
+</style>

Разница между файлами не показана из-за своего большого размера
+ 1 - 0
src/views/train/monitor/data/data.json


+ 75 - 0
src/views/train/monitor/data/flow.json

@@ -0,0 +1,75 @@
+{
+  "processId": "10001",
+  "processName": "请假审批11",
+  "nodeConfig": {
+    "nodeName": "发起人",
+    "nodeType": "start",
+    "config": {
+      "name": null
+    },
+    "childNode": {
+      "nodeName": "审批人",
+      "nodeType": "approver",
+      "config": {
+        "name": null
+      },
+      "childNode": {
+        "nodeName": "路由",
+        "nodeType": "router",
+        "conditionNodes": [
+          {
+            "nodeName": "条件",
+            "nodeType": "condition",
+            "isLastCondition": false,
+            "config": {
+              "days": 1
+            },
+            "childNode": {
+              "nodeName": "审批人",
+              "nodeType": "approver",
+              "config": {
+                "name": "赵六"
+              }
+            }
+          },
+          {
+            "nodeName": "条件",
+            "nodeType": "condition",
+            "isLastCondition": false,
+            "config": {
+              "days": 3
+            },
+            "childNode": {
+              "nodeName": "审批人",
+              "nodeType": "approver",
+              "config": {
+                "name": "老王"
+              }
+            }
+          },
+          {
+            "nodeName": "条件",
+            "nodeType": "condition",
+            "isLastCondition": true,
+            "config": {},
+            "childNode": {}
+          }
+        ],
+        "childNode": {
+          "nodeName": "审批人",
+          "nodeType": "approver",
+          "config": {
+            "name": "李四"
+          },
+          "childNode": {
+            "nodeName": "抄送人",
+            "nodeType": "notify",
+            "config": {
+              "name": "王五"
+            }
+          }
+        }
+      }
+    }
+  }
+}