From 0108df13340210bebd5ad6c693fc1a6bd1b061ff Mon Sep 17 00:00:00 2001
From: 疯狂的狮子Li <15040126243@163.com>
Date: 星期二, 05 三月 2024 22:57:51 +0800
Subject: [PATCH] !88 合并flowable工作流功能 * merge 合并dev * add 添加抄送查询 * add 添加我的已办 * add 添加抄送 * add 添加附件下载 * update 优化类型 * Merge remote-tracking branch 'origin/future/flowable' into future/flowable * fix 修复 流程设计器打包部署报错问题 * add 添加审批附件上传 * update 修复固定值未在xml显示问题 * update 修复跳转条件回显Object问题 * update 优化面板文件名称 * update 调整key * remove 移除旧设计器,添加xml保存 * update 增加任务面板提示 * update 优化xml预览和svg预览 * update 优化xml预览和svg预览 * update 优化模型设计 * update 优化设计器 * update 优化设计器 * update 优化设计器 * update 删除旧设计器 * update 删除console.log * add 添加模型接口 * update 优化预览xml和svg样式被修改问题 * update 优化属性面板,增加展开动画 * update 去除开发模式 * update 优化任务栏样式 * update 优化图标渲染样式 * update 增加BpmnFactory类型 * update 增加BpmnFactory * update 移除users和group * update 移除无用类型 * update 优化页面类型 * update 去除多余属性 * update 完善流程线 * update 增加复杂网关 * update 完善流程 * update 完善网关 * update 优化网关汉化 * update 优化过期时间选择 * update 支持多实例 * update 增加类容提示 * update 支持选择组 * update 新增角色api * update 优化roleSelect 选中未确定,再次打开还保留选中的问题 * update 优化userSelect 选中未确定,再次打开还保留选中的问题 * update 优化userSelect 选中未确定,再次打开还保留选中的问题 * update 去掉modeler store多余属性 bpmnModel * update 优化属性面板,当面板未选中时默认展示流程面板 * update 优化TaskPanel类型,去掉roles属性 * update 优化用户api * update 优化用户选择器 * update 优化执行监听器 * update 优化任务监听器 * update 优化usePanel方法 * update 选人优化 * update 增加扩展节点信息 * update 增加usePanel默认方法 * update 去除处理事件 * update 扩展flowable  userinfo属性 * update 全局modeler 改为非响应式 * update 增加hooks方法 * update 修改命名 * update 修改面板formData来源 * update 重写用户任务面板选择逻辑 * update 重写用户任务面板选择逻辑 * update 修改用户选择组件获取数据逻辑 * update 修改枚举类型 * update 修改默认配置列 * update 增加修改节点方法 * update 调整预览窗口大小 * update 优化用户选择组件 返回值 * update 优化用户选择组件 * update 新增通过ids 获取用户信息 * update 重写task面板选人 未完成 * update 升级用户选择 支持多选配置 * update 升级bpmnjs依赖版本 * update 增加useDialog类型 * update 调整全局样式 * update 代码高亮设置 * update 优化领用,归还加载 * update 增加选择角色 * update  新增角色选择组件 * update 新增过期时间选择组件 * update 调整任务面板样式 * update  调整全局dialog header 增加分割线 * update 代码高亮设置 * update  调整面板位置 * update 封装用户选择组件 * update 移除所有的节点描述 * update 删除分类 * update  调整面板位置 * update  修改命名,增加自定义渲染 * update  修改命名,增加自定义渲染 * update 增加 Element类型定义 * update 调整样式 * update 移除bpmn panel依赖,升级bpmn.js依赖到最新,修改汉化包 * update 调整类型声明文件 * update 调整类型声明文件 * update 优化面板工具 * update 优化面板工具 * Merge remote-tracking branch 'origin/future/flowable' into future/flowable * update 优化面板工具 * Merge branch 'future/flowable' of https://gitee.com/JavaLionLi/plus-ui… * add 添加修改办理人 * update 优化面板工具 * update 初始化流程数据 * Merge remote-tracking branch 'origin/future/flowable' into future/flowable * add 流程设计面板 * update 调整初始化xml * add 任务面板 * add 新增bpmn.js * update 优化request请求类判断请求头方式 * update 流程定义预览 优化 * update 流程定义预览 优化 * update 去掉console.log * update 优化工作流代码 * fix 修复待办任务 重置查询条件失效问题 * add 增加待办任务 接口类型,优化页面 * add 增加vite 启动预编译css * fix 修复i18n无感刷新问题 * Merge branch 'dev' into future/flowable * update 调整选择请假事件 * Merge branch 'dev' into future/flowable * 同步dev代码 * Merge branch 'dev' into future/flowable * 合并dev * remove 设计器无用代码 调整请假查询 * update 调整请假申请 * update 移动请假表单包结构,调整设计器选择引用表单请求错误 * remove 移除动态表单 * update 调整流程办理 * Merge branch 'dev' into future/flowable * Merge branch 'dev' into future/flowable * Merge branch 'dev' into future/flowable * Merge branch 'dev' into future/flowable * 合并 * update 调整请假申请流程提交 * update 修改业务单据流程提交 * update 调整业务单据流程提交 * 优化代码 * 优化工作流代码缩进 * 项目格式化配置修改 * 调整代码缩进 * Merge branch 'ts' into future/flowable * add 添加动态表单提交流程 * add 添加动态表单单据 * add 新增流程定义与表单关联 * update 调整点击左侧部门查询人员,部门刷新问题 * update 调整按钮图标 * 调整错别字 * update 调整流程定义图片预览 * add 添加流程实例迁移版本 * fix 修复我的单据无法提交问题 * Merge branch 'ts' into future/flowable * remove 还原代码后端解决 * update 流程设计器中分配发起人变量错误,先移除 * fix 修复设计器无法编辑问题 * update 调整设计器请求头 * Merge branch 'ts' into future/flowable * Merge branch 'ts' into future/flowable * add 添加流程定义历史列表 * update 审批记录v2改为v3 * update 调整请假必填项 * add 添加请假申请示例,添加流程定义文件部署 * update 移除流程表单 formConfig 属性,表单配置信息都放一起便于使用。 * add 添加任务加签,减签 * update 调整流程作废 * update 优化流程状态 * add 添加任务驳回 * add 添加查询当前租户所有待办,已办任务 * add 增加审批意见 * add 添加流程办理弹窗确认组件 * add 添加任务作废理由 * update 调整流程实例,流程定义检索 * add 添加我的单据页面 * add 添加任务归还认领 * add 添加流程实例,流程定义分类查询 * add 添加模型分类查询 * add 添加流程分类 * Merge remote-tracking branch 'origin/future/flowable' into future/flowable * add 添加流程表单管理页面 * add 集成vForm动态表单组件 * update xml调整超出滚动 * add 添加已办列表 * add 添加单据状态 * update 优化流程实例删除 * fix 修复流程实例查询挂起状态错误 * update 调整流程实例挂起激活状态 * add 添加流程实例列表 * update 调整流程定义弹窗提示 * add 添加流程定义列表,添加流程图,xml预览,添加简单流程启动,办理 * 调整审批记录悬浮逻辑 * 删除无用代码 * add 添加节点悬浮信息 * 调整流程预览 * 调整流程追踪 * add 添加审批记录 * add 模型设计的types * update 修改排版 * add lang=ts * update 修改ele的废弃api * fix调整审批记录图片不显示问题 * add 添加任务待办,流程图 * 调整设计器关闭 * add 添加待办 * remove 删除无用代码 * update types * 添加模型token验证 * 隐藏设计器验证按钮,隐藏表单,案例,应用程序等 * 添加模型部署 * 添加画图接口token,优化画图接口 * 添加工作流模型新增,修改,查询,删除,画图工具

---
 src/layout/components/TagsView/index.vue |  377 +++++++++++++++++++++++++++--------------------------
 1 files changed, 194 insertions(+), 183 deletions(-)

diff --git a/src/layout/components/TagsView/index.vue b/src/layout/components/TagsView/index.vue
index cbf0a84..1e12ca4 100644
--- a/src/layout/components/TagsView/index.vue
+++ b/src/layout/components/TagsView/index.vue
@@ -14,232 +14,241 @@
       >
         {{ tag.title }}
         <span v-if="!isAffix(tag)" @click.prevent.stop="closeSelectedTag(tag)">
-          <close class="el-icon-close" style="width: 1em; height: 1em;vertical-align: middle;" />
+          <close class="el-icon-close" style="width: 1em; height: 1em; vertical-align: middle" />
         </span>
       </router-link>
     </scroll-pane>
     <ul v-show="visible" :style="{ left: left + 'px', top: top + 'px' }" class="contextmenu">
-      <li @click="refreshSelectedTag(selectedTag)"><refresh-right style="width: 1em; height: 1em;" /> 鍒锋柊椤甸潰</li>
-      <li v-if="!isAffix(selectedTag)" @click="closeSelectedTag(selectedTag)"><close style="width: 1em; height: 1em;" /> 鍏抽棴褰撳墠</li>
-      <li @click="closeOthersTags"><circle-close style="width: 1em; height: 1em;" /> 鍏抽棴鍏朵粬</li>
-      <li v-if="!isFirstView()" @click="closeLeftTags"><back style="width: 1em; height: 1em;" /> 鍏抽棴宸︿晶</li>
-      <li v-if="!isLastView()" @click="closeRightTags"><right style="width: 1em; height: 1em;" /> 鍏抽棴鍙充晶</li>
-      <li @click="closeAllTags(selectedTag)"><circle-close style="width: 1em; height: 1em;" /> 鍏ㄩ儴鍏抽棴</li>
+      <li @click="refreshSelectedTag(selectedTag)"><refresh-right style="width: 1em; height: 1em" /> 鍒锋柊椤甸潰</li>
+      <li v-if="!isAffix(selectedTag)" @click="closeSelectedTag(selectedTag)"><close style="width: 1em; height: 1em" /> 鍏抽棴褰撳墠</li>
+      <li @click="closeOthersTags"><circle-close style="width: 1em; height: 1em" /> 鍏抽棴鍏朵粬</li>
+      <li v-if="!isFirstView()" @click="closeLeftTags"><back style="width: 1em; height: 1em" /> 鍏抽棴宸︿晶</li>
+      <li v-if="!isLastView()" @click="closeRightTags"><right style="width: 1em; height: 1em" /> 鍏抽棴鍙充晶</li>
+      <li @click="closeAllTags(selectedTag)"><circle-close style="width: 1em; height: 1em" /> 鍏ㄩ儴鍏抽棴</li>
     </ul>
   </div>
 </template>
 
 <script setup lang="ts">
-import ScrollPane from './ScrollPane.vue'
-import { getNormalPath } from '@/utils/ruoyi'
-import useTagsViewStore from "@/store/modules/tagsView";
-import useSettingsStore from '@/store/modules/settings'
-import usePermissionStore from '@/store/modules/permission'
-import { ComponentInternalInstance } from "vue";
-import { RouteOption, TagView, RouteLocationRaw } from "vue-router";
+import ScrollPane from './ScrollPane.vue';
+import { getNormalPath } from '@/utils/ruoyi';
+import useSettingsStore from '@/store/modules/settings';
+import usePermissionStore from '@/store/modules/permission';
+import useTagsViewStore from '@/store/modules/tagsView';
+import { RouteRecordRaw, RouteLocationNormalized } from 'vue-router';
 
 const visible = ref(false);
 const top = ref(0);
 const left = ref(0);
-const selectedTag = ref<TagView>({});
-const affixTags = ref<TagView[]>([]);
-const scrollPaneRef = ref(ScrollPane);
+const selectedTag = ref<RouteLocationNormalized>();
+const affixTags = ref<RouteLocationNormalized[]>([]);
+const scrollPaneRef = ref<InstanceType<typeof ScrollPane>>();
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const route = useRoute();
 const router = useRouter();
 
-const visitedViews = computed(() => useTagsViewStore().visitedViews);
-const routes = computed(() => usePermissionStore().routes);
+const visitedViews = computed(() => useTagsViewStore().getVisitedViews());
+const routes = computed(() => usePermissionStore().getRoutes());
 const theme = computed(() => useSettingsStore().theme);
 
 watch(route, () => {
-    addTags();
-    moveToCurrentTag();
-})
+  addTags();
+  moveToCurrentTag();
+});
 watch(visible, (value) => {
-    if (value) {
-        document.body.addEventListener('click', closeMenu);
-    } else {
-        document.body.removeEventListener('click', closeMenu);
-    }
-})
+  if (value) {
+    document.body.addEventListener('click', closeMenu);
+  } else {
+    document.body.removeEventListener('click', closeMenu);
+  }
+});
 
-const isActive = (r: TagView): boolean => {
-    return r.path === route.path;
-}
-const activeStyle = (tag: TagView) => {
-    if (!isActive(tag)) return {};
-    return {
-        "background-color": theme.value,
-        "border-color": theme.value
-    };
-}
-const isAffix = (tag: TagView) => {
-    return tag.meta && tag.meta.affix;
-}
+const isActive = (r: RouteLocationNormalized): boolean => {
+  return r.path === route.path;
+};
+const activeStyle = (tag: RouteLocationNormalized) => {
+  if (!isActive(tag)) return {};
+  return {
+    'background-color': theme.value,
+    'border-color': theme.value
+  };
+};
+const isAffix = (tag: RouteLocationNormalized) => {
+  return tag?.meta && tag?.meta?.affix;
+};
 const isFirstView = () => {
-    try {
-        return selectedTag.value.fullPath === '/index' || selectedTag.value.fullPath === visitedViews.value[1].fullPath;
-    } catch (err) {
-        return false;
-    }
-}
+  try {
+    return selectedTag.value.fullPath === '/index' || selectedTag.value.fullPath === visitedViews.value[1].fullPath;
+  } catch (err) {
+    return false;
+  }
+};
 const isLastView = () => {
-    try {
-        return selectedTag.value.fullPath === visitedViews.value[visitedViews.value.length - 1].fullPath;
-    } catch (err) {
-        return false;
+  try {
+    return selectedTag.value.fullPath === visitedViews.value[visitedViews.value.length - 1].fullPath;
+  } catch (err) {
+    return false;
+  }
+};
+const filterAffixTags = (routes: RouteRecordRaw[], basePath = '') => {
+  let tags: RouteLocationNormalized[] = [];
+
+  routes.forEach((route) => {
+    if (route.meta && route.meta.affix) {
+      const tagPath = getNormalPath(basePath + '/' + route.path);
+      tags.push({
+        hash: '',
+        matched: [],
+        params: undefined,
+        query: undefined,
+        redirectedFrom: undefined,
+        fullPath: tagPath,
+        path: tagPath,
+        name: route.name as string,
+        meta: { ...route.meta }
+      });
     }
-}
-const filterAffixTags = (routes:RouteOption [], basePath = '') => {
-    let tags:TagView[] = []
-    routes.forEach(route => {
-        if (route.meta && route.meta.affix) {
-            const tagPath = getNormalPath(basePath + '/' + route.path);
-            tags.push({
-                fullPath: tagPath,
-                path: tagPath,
-                name: route.name,
-                meta: { ...route.meta }
-            })
-        }
-        if (route.children) {
-            const tempTags = filterAffixTags(route.children, route.path);
-            if (tempTags.length >= 1) {
-                tags = [...tags, ...tempTags];
-            }
-        }
-    })
-    return tags
-}
+    if (route.children) {
+      const tempTags = filterAffixTags(route.children, route.path);
+      if (tempTags.length >= 1) {
+        tags = [...tags, ...tempTags];
+      }
+    }
+  });
+  return tags;
+};
 const initTags = () => {
-    const res = filterAffixTags(routes.value);
-    affixTags.value = res;
-    for (const tag of res) {
-        // Must have tag name
-        if (tag.name) {
-            useTagsViewStore().addVisitedView(tag);
-        }
+  const res = filterAffixTags(routes.value);
+  affixTags.value = res;
+  for (const tag of res) {
+    // Must have tag name
+    if (tag.name) {
+      useTagsViewStore().addVisitedView(tag);
     }
-}
+  }
+};
 const addTags = () => {
-    const { name } = route;
-    if (name) {
-        useTagsViewStore().addView(route);
-        if (route.meta.link) {
-            useTagsViewStore().addIframeView(route);
-        }
-    }
-    return false
-}
-const moveToCurrentTag = () => {
-    nextTick(() => {
-        for (const r of visitedViews.value) {
-            if (r.path === route.path) {
-                scrollPaneRef.value.moveToTarget(r);
-                // when query is different then update
-                if (r.fullPath !== route.fullPath) {
-                    useTagsViewStore().updateVisitedView(route);
-                }
-            }
-        }
-    })
-}
-const refreshSelectedTag = (view: TagView) => {
-    proxy?.$tab.refreshPage(view);
+  const { name } = route;
+  if (route.query.title) {
+    route.meta.title = route.query.title as string;
+  }
+  if (name) {
+    useTagsViewStore().addView(route as any);
     if (route.meta.link) {
-        useTagsViewStore().delIframeView(route);
+      useTagsViewStore().addIframeView(route as any);
     }
-}
-const closeSelectedTag = (view: TagView) => {
-    proxy?.$tab.closePage(view).then(({ visitedViews }: any) => {
-        if (isActive(view)) {
-            toLastView(visitedViews, view);
+  }
+  return false;
+};
+const moveToCurrentTag = () => {
+  nextTick(() => {
+    for (const r of visitedViews.value) {
+      if (r.path === route.path) {
+        scrollPaneRef.value?.moveToTarget(r);
+        // when query is different then update
+        if (r.fullPath !== route.fullPath) {
+          useTagsViewStore().updateVisitedView(route);
         }
-    })
-}
+      }
+    }
+  });
+};
+const refreshSelectedTag = (view: RouteLocationNormalized) => {
+  proxy?.$tab.refreshPage(view);
+  if (route.meta.link) {
+    useTagsViewStore().delIframeView(route);
+  }
+};
+const closeSelectedTag = (view: RouteLocationNormalized) => {
+  proxy?.$tab.closePage(view).then(({ visitedViews }: any) => {
+    if (isActive(view)) {
+      toLastView(visitedViews, view);
+    }
+  });
+};
 const closeRightTags = () => {
-    proxy?.$tab.closeRightPage(selectedTag.value).then(visitedViews => {
-        if (!visitedViews.find(i => i.fullPath === route.fullPath)) {
-            toLastView(visitedViews);
-        }
-    })
-}
+  proxy?.$tab.closeRightPage(selectedTag.value).then((visitedViews: RouteLocationNormalized[]) => {
+    if (!visitedViews.find((i: RouteLocationNormalized) => i.fullPath === route.fullPath)) {
+      toLastView(visitedViews);
+    }
+  });
+};
 const closeLeftTags = () => {
-    proxy?.$tab.closeLeftPage(selectedTag.value).then(visitedViews => {
-        if (!visitedViews.find(i => i.fullPath === route.fullPath)) {
-            toLastView(visitedViews);
-        }
-    })
-}
+  proxy?.$tab.closeLeftPage(selectedTag.value).then((visitedViews: RouteLocationNormalized[]) => {
+    if (!visitedViews.find((i: RouteLocationNormalized) => i.fullPath === route.fullPath)) {
+      toLastView(visitedViews);
+    }
+  });
+};
 const closeOthersTags = () => {
-    router.push(selectedTag.value as RouteLocationRaw).catch(() => { });
-    proxy?.$tab.closeOtherPage(selectedTag.value).then(() => {
-        moveToCurrentTag();
-    })
-}
-const closeAllTags = (view: TagView) => {
-    proxy?.$tab.closeAllPage().then(({ visitedViews }) => {
-        if (affixTags.value.some(tag => tag.path === route.path)) {
-            return;
-        }
-        toLastView(visitedViews, view);
-    })
-}
-const toLastView = (visitedViews:TagView[], view?: TagView) => {
-    const latestView = visitedViews.slice(-1)[0];
-    if (latestView) {
-        router.push(latestView.fullPath as string);
-    } else {
-        // now the default is to redirect to the home page if there is no tags-view,
-        // you can adjust it according to your needs.
-        if (view?.name === 'Dashboard') {
-            // to reload home page
-            router.replace({ path: '/redirect' + view?.fullPath });
-        } else {
-            router.push('/');
-        }
+  router.push(selectedTag.value).catch(() => {});
+  proxy?.$tab.closeOtherPage(selectedTag.value).then(() => {
+    moveToCurrentTag();
+  });
+};
+const closeAllTags = (view: RouteLocationNormalized) => {
+  proxy?.$tab.closeAllPage().then(({ visitedViews }) => {
+    if (affixTags.value.some((tag) => tag.path === route.path)) {
+      return;
     }
-}
-const openMenu = (tag: TagView, e: MouseEvent) => {
-    const menuMinWidth = 105;
-    const offsetLeft = proxy?.$el.getBoundingClientRect().left; // container margin left
-    const offsetWidth = proxy?.$el.offsetWidth; // container width
-    const maxLeft = offsetWidth - menuMinWidth; // left boundary
-    const l = e.clientX - offsetLeft + 15; // 15: margin right
-
-    if (l > maxLeft) {
-        left.value = maxLeft;
+    toLastView(visitedViews, view);
+  });
+};
+const toLastView = (visitedViews: RouteLocationNormalized[], view?: RouteLocationNormalized) => {
+  const latestView = visitedViews.slice(-1)[0];
+  if (latestView) {
+    router.push(latestView.fullPath as string);
+  } else {
+    // now the default is to redirect to the home page if there is no tags-view,
+    // you can adjust it according to your needs.
+    if (view?.name === 'Dashboard') {
+      // to reload home page
+      router.replace({ path: '/redirect' + view?.fullPath });
     } else {
-        left.value = l;
+      router.push('/');
     }
+  }
+};
+const openMenu = (tag: RouteLocationNormalized, e: MouseEvent) => {
+  const menuMinWidth = 105;
+  const offsetLeft = proxy?.$el.getBoundingClientRect().left; // container margin left
+  const offsetWidth = proxy?.$el.offsetWidth; // container width
+  const maxLeft = offsetWidth - menuMinWidth; // left boundary
+  const l = e.clientX - offsetLeft + 15; // 15: margin right
 
-    top.value = e.clientY
-    visible.value = true;
-    selectedTag.value = tag;
-}
+  if (l > maxLeft) {
+    left.value = maxLeft;
+  } else {
+    left.value = l;
+  }
+
+  top.value = e.clientY;
+  visible.value = true;
+  selectedTag.value = tag;
+};
 const closeMenu = () => {
-    visible.value = false;
-}
+  visible.value = false;
+};
 const handleScroll = () => {
-    closeMenu();
-}
-
+  closeMenu();
+};
 
 onMounted(() => {
-    initTags();
-    addTags();
-})
+  initTags();
+  addTags();
+});
 </script>
 
 <style lang="scss" scoped>
 .tags-view-container {
   height: 34px;
   width: 100%;
-  background: #fff;
-  border-bottom: 1px solid #d8dce5;
-  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 3px 0 rgba(0, 0, 0, 0.04);
+  background-color: var(--el-bg-color);
+  border: 1px solid var(--el-border-color-light);
+  box-shadow:
+    0 1px 3px 0 rgba(0, 0, 0, 0.12),
+    0 0 3px 0 rgba(0, 0, 0, 0.04);
   .tags-view-wrapper {
     .tags-view-item {
       display: inline-block;
@@ -247,13 +256,16 @@
       cursor: pointer;
       height: 26px;
       line-height: 23px;
-      border: 1px solid #d8dce5;
+      background-color: var(--el-bg-color);
+      border: 1px solid var(--el-border-color-light);
       color: #495060;
-      background: #fff;
       padding: 0 8px;
       font-size: 12px;
       margin-left: 5px;
       margin-top: 4px;
+      &:hover {
+        color: var(--el-color-primary);
+      }
       &:first-of-type {
         margin-left: 15px;
       }
@@ -265,21 +277,21 @@
         color: #fff;
         border-color: #42b983;
         &::before {
-          content: "";
+          content: '';
           background: #fff;
           display: inline-block;
           width: 8px;
           height: 8px;
           border-radius: 50%;
           position: relative;
-          margin-right: 2px;
+          margin-right: 5px;
         }
       }
     }
   }
   .contextmenu {
     margin: 0;
-    background: #fff;
+    background: var(--el-bg-color);
     z-index: 3000;
     position: absolute;
     list-style-type: none;
@@ -287,7 +299,6 @@
     border-radius: 4px;
     font-size: 12px;
     font-weight: 400;
-    color: #333;
     box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, 0.3);
     li {
       margin: 0;

--
Gitblit v1.9.3