Explorar o código

feat: 汇总页面树结构改变封装 & 顶部刷新事件封装

qinlaiqiao %!s(int64=3) %!d(string=hai) anos
pai
achega
6550f6f463

+ 25 - 0
src/composables/useRefresh.ts

@@ -0,0 +1,25 @@
+import { onUnmounted } from 'vue'
+// 回调池
+const cbPool: (() => void)[] = []
+
+// 注册顶部按钮刷新回调(组件销毁时,自动销毁回调, 这是推荐的方式)
+export function registerRefreshCallback(cb: () => void) {
+  cbPool.push(cb)
+  onUnmounted(() => {
+    const targetIndex = cbPool.findIndex(item => item === cb)
+    if (targetIndex !== -1) {
+      cbPool.splice(targetIndex, 1)
+    }
+    console.log('cbPool', cbPool.length)
+  })
+}
+
+// 注册顶部按钮刷新回调(组件销毁时,不会自动销毁回调,慎用)
+export function registerRefreshCallbackForever(cb: () => void) {
+  cbPool.push(cb)
+}
+
+// 调用触发刷新事件回调
+export function invokeAllRefreshCallback() {
+  cbPool.forEach(cb => cb && cb())
+}

+ 22 - 0
src/composables/useStructureRouter.ts

@@ -0,0 +1,22 @@
+import { watch, ref } from 'vue';
+import { useRoute } from 'vue-router'
+import { SubjectStructure } from '@/constants/subject'
+
+// summary 结构类型
+export default function useStructureRouter() {
+  const route = useRoute()
+
+  const currentStructure = route.query.structure === SubjectStructure.ARRANGE ? SubjectStructure.ARRANGE : SubjectStructure.RAW
+  const structure = ref<SubjectStructure>(currentStructure)
+
+  // 监听路由 query structure 参数改变
+  watch(() => route.query.structure, val => {
+    if (val !== SubjectStructure.ARRANGE) {
+      structure.value = SubjectStructure.RAW
+    } else {
+      structure.value = SubjectStructure.ARRANGE
+    }
+  })
+
+  return structure
+}

+ 6 - 1
src/constants/subject.ts

@@ -2,4 +2,9 @@ export enum SubjectTreeNodeType {
     CONSTRUCTION = 'construction',
     SINGLE = 'single',
     UNIT = 'unit'
-}
+}
+
+export enum SubjectStructure {
+    RAW = 'raw',
+    ARRANGE = 'arrange'
+}

+ 6 - 1
src/views/main-frame/MainFrame.vue

@@ -1,14 +1,19 @@
 <script setup lang="ts">
 import { useRoute } from 'vue-router'
+import { invokeAllRefreshCallback } from '@/composables/useRefresh'
 
 const route = useRoute()
+
+const handleRefresh = () => {
+  invokeAllRefreshCallback()
+}
 </script>
 
 <template>
   <article class="main-frame-page">
     <header class="header">
       <img src="@/assets/logo.png" class="logo" alt="logo" />
-      <span class="refresh" title="刷新">
+      <span class="refresh" title="刷新" @click="handleRefresh">
         <iconfont class="icon dsk-undo" />
       </span>
       <ul class="breadcrumb">

+ 24 - 36
src/views/project/Project.vue

@@ -1,13 +1,17 @@
 <script setup lang="ts">
-import {onMounted, ref} from "vue";
-import {useRoute} from 'vue-router'
+import { onMounted, ref } from "vue";
+import { useRoute } from 'vue-router'
 
 const route = useRoute()
 </script>
 
 <template>
   <article class="project-page">
-    <header class="header" id="project-header" :class="{'short-header': route.fullPath.startsWith('/project/summary')}">
+    <header
+      class="header"
+      id="project-header"
+      :class="{ 'short-header': route.fullPath.startsWith('/project/summary') }"
+    >
       <h1 class="name">莲花路电力迁改项目</h1>
       <el-descriptions :column="4" size="mini">
         <el-descriptions-item label="申请单位:">某某建筑公司</el-descriptions-item>
@@ -21,49 +25,33 @@ const route = useRoute()
         <el-descriptions-item label="当前流程:">
           <el-tag size="small" type="success">某某步骤</el-tag>
         </el-descriptions-item>
-        <el-descriptions-item label="工程地址:">
-          珠海市香洲区某某街道某某路100号
-        </el-descriptions-item>
+        <el-descriptions-item label="工程地址:">珠海市香洲区某某街道某某路100号</el-descriptions-item>
       </el-descriptions>
 
       <el-affix :offset="64">
         <ul class="nav">
           <router-link custom to="/project" v-slot="{ navigate, isExactActive }">
             <li
-                class="item overview"
-                @click="navigate"
-                :class="{ 'exact-active': isExactActive }"
-            >
-              项目概况
-            </li>
+              class="item overview"
+              @click="navigate"
+              :class="{ 'exact-active': isExactActive }"
+            >项目概况</li>
           </router-link>
-          <router-link
-              custom
-              to="/project/process"
-              v-slot="{ navigate, isExactActive }"
-          >
+          <router-link custom to="/project/process" v-slot="{ navigate, isExactActive }">
             <li
-                class="item process"
-                @click="navigate"
-                :class="{ 'exact-active': isExactActive }"
-            >
-              项目流程
-            </li>
+              class="item process"
+              @click="navigate"
+              :class="{ 'exact-active': isExactActive }"
+            >项目流程</li>
           </router-link>
-          <router-link
-              custom
-              to="/project/summary"
-              v-slot="{ navigate, isExactActive }"
-          >
+          <router-link custom to="/project/summary" v-slot="{ navigate, isExactActive }">
             <li
-                class="item summary"
-                @click="navigate"
-                :class="{ 'exact-active': isExactActive }"
-            >
-              项目流汇总
-            </li>
+              class="item summary"
+              @click="navigate"
+              :class="{ 'exact-active': isExactActive }"
+            >项目流汇总</li>
           </router-link>
-         <!--  <router-link
+          <!--  <router-link
               custom
               to="/project/report"
               v-slot="{ navigate, isExactActive }"
@@ -75,7 +63,7 @@ const route = useRoute()
             >
               报表
             </li>
-          </router-link> -->
+          </router-link>-->
         </ul>
       </el-affix>
     </header>

+ 6 - 0
src/views/project/overview/Overview.vue

@@ -1,5 +1,6 @@
 <script setup lang="ts">
 import {onMounted, reactive, ref} from "vue";
+import { registerRefreshCallback } from '@/composables/useRefresh'
 
 import * as echarts from 'echarts';
 
@@ -190,6 +191,11 @@ const appoveList = reactive([
   }
 ])
 
+// 顶部刷新按钮点击事件
+registerRefreshCallback(() => {
+  console.log('overview 顶部刷新按钮被点击了')
+})
+
 </script>
 
 <template>

+ 6 - 0
src/views/project/summary/Summary.vue

@@ -9,6 +9,7 @@ import LibRation from "./components/lib-ration/LibRation.vue";
 import { SubjectTreeNodeType } from '@/constants/subject'
 import { Subject } from "@/types/subject";
 import useSummaryLayout from './scripts/useSummaryLayout'
+import { registerRefreshCallback } from '@/composables/useRefresh'
 
 // 布局相关代码
 const {
@@ -100,6 +101,11 @@ const handleRightVisibleChange = async (needRender: boolean) => {
   }
   mainLayout.value && mainLayout.value.Refresh()
 }
+
+// 顶部刷新按钮点击事件
+registerRefreshCallback(() => {
+  console.log('summary 顶部刷新按钮被点击了')
+})
 </script>
 
 <template>

+ 1 - 0
src/views/project/summary/components/bottom-tabs/style.scss

@@ -13,6 +13,7 @@
     }
 
     .el-tabs__item {
+      @apply select-none;
       height: 36px;
       line-height: 36px;
       color: #515a6e;

+ 24 - 3
src/views/project/summary/components/subject-tree/SubjectTree.vue

@@ -1,7 +1,11 @@
 <script setup lang="ts">
 // import { ContextMenu } from "@/types/components";
 import { Subject } from "@/types/subject";
-import { ref, PropType, toRaw, onMounted } from "vue";
+import { ref, PropType, toRaw, onMounted, watch } from "vue";
+import { useRouter, useRoute } from 'vue-router'
+import { isUndefined } from 'lodash'
+import { SubjectStructure } from '@/constants/subject'
+import useStructureRouter from "@/composables/useStructureRouter";
 
 const props = defineProps({
   treeData: {
@@ -10,6 +14,9 @@ const props = defineProps({
   },
 })
 
+const router = useRouter()
+const route = useRoute()
+
 // 上下文菜单设置
 const menuGroup: ContextMenu.MenuGroup[] = [
   [
@@ -184,13 +191,27 @@ const handleNodeContextmenu = (event: MouseEvent, nodeData: Subject.ISubjectTree
   }
 }
 
+const structure = useStructureRouter()
+// 监听 structure 改变
+watch(structure, val => {
+  console.log('subject tree 结构', val)
+})
+
 </script>
 
 <template>
   <section class="subject-tree-wrap">
     <ul class="tabs">
-      <li class="tab active">原始结构</li>
-      <li class="tab">整理结构</li>
+      <li
+        class="tab"
+        :class="{ active: route.query.structure !== SubjectStructure.ARRANGE }"
+        @click="router.push({ name: 'Summary' })"
+      >原始结构</li>
+      <li
+        class="tab"
+        :class="{ active: route.query.structure === SubjectStructure.ARRANGE }"
+        @click="router.push({ name: 'Summary', query: { structure: 'arrange' } })"
+      >整理结构</li>
     </ul>
     <div class="tree-wrap">
       <context-menu :item-groups="menuGroup" ref="contextMenuRef" auto-size>

+ 1 - 1
src/views/project/summary/components/subject-tree/style.scss

@@ -9,7 +9,7 @@
     height: 35px;
 
     .tab {
-      @apply flex-1 text-center cursor-pointer;
+      @apply flex-1 text-center cursor-pointer select-none;
       height: 100%;
       line-height: 35px;
       font-size: 14px;

+ 8 - 1
src/views/project/summary/components/tool-bar/ToolBar.vue

@@ -1,7 +1,8 @@
 <script setup lang="ts">
-import { onMounted, reactive, ref, computed } from "vue";
+import { onMounted, reactive, ref, computed, watch } from "vue";
 import summaryLayoutStore from '@/store/modules/summaryLayout'
 import { Subject } from "@/types/subject";
+import useStructureRouter from "@/composables/useStructureRouter";
 
 const { setRightStdBillVisible, setRightLibRationVisible } = summaryLayoutStore
 
@@ -48,6 +49,12 @@ const hide = () => {
   rightLibRationVisible.value = false
 }
 
+const structure = useStructureRouter()
+// 监听 structure 改变
+watch(structure, val => {
+  console.log('tool bar 结构', val)
+})
+
 </script>
 
 <template>