瀏覽代碼

[Wip 0000] 首页及全局部门选择器开发

houzekong 1 月之前
父節點
當前提交
a9ba65dc33

+ 4 - 1
src/components/Form/src/jeecg/components/MineCascader/MineCascader.vue

@@ -13,6 +13,9 @@
     :change-on-select="changeOnSelect"
     @change="handleChange"
   >
+    <template #clearIcon>
+      <slot name="clearIcon"></slot>
+    </template>
     <template #displayRender="{ labels }">
       {{ labels[labels.length - 1] }}
     </template>
@@ -46,7 +49,7 @@
       /** 是否从已存储的信息中初始化组件值 */
       initFromStore: propTypes.bool.def(true),
       /** 是否从将值同步至STORE */
-      syncToStore: propTypes.bool.def(true),
+      syncToStore: propTypes.bool.def(false),
       showSearch: propTypes.bool.def(true),
       allowClear: propTypes.bool.def(true),
       changeOnSelect: propTypes.bool.def(true),

+ 46 - 0
src/hooks/component/useDeptWatcher.ts

@@ -0,0 +1,46 @@
+import { ref, watch, WatchOptions } from 'vue';
+import { useAppStore } from '/@/store/modules/app';
+import { useMineDepartmentStore } from '/@/store/modules/mine';
+import { useRoute } from 'vue-router';
+
+/** 监听全局的部门变化 */
+export function useDeptWatch(cb: (id: string) => void, opt: WatchOptions = {}) {
+  //   const appStore = useAppStore();
+  const mineStore = useMineDepartmentStore();
+  const route = useRoute();
+  const deptId = ref<string>((route?.query?.deptId as string) || '');
+
+  watch(
+    () => mineStore.getDepartId,
+    (v) => {
+      if (!v) return;
+      deptId.value = v;
+      cb(v);
+    },
+    {
+      immediate: true,
+      ...opt,
+    }
+  );
+
+  return {
+    deptId,
+  };
+}
+
+export function useDeptSetter() {
+  const appStore = useAppStore();
+  const mineStore = useMineDepartmentStore();
+  const deptId = ref('');
+
+  return {
+    deptId,
+    setGlobDept: (deptId: string) => {
+      mineStore.setDepartById(deptId);
+      appStore.setSimpleMapParams({
+        deptId: mineStore.getDepartId,
+        isLeaf: mineStore.getDepart?.isLeaf,
+      });
+    },
+  };
+}

+ 58 - 29
src/layouts/default/feature/SimpleMap.vue

@@ -13,17 +13,22 @@
   // import { useRoute } from 'vue-router';
   import vjmap from 'vjmap';
   // import type vjmap3d from 'vjmap3d';
-  import { getGeoJSON } from '/@/api/sys/map';
+  import { getGeoJSON, getShanxiGeoJSON } from '/@/api/sys/map';
   import { useMineDepartmentStore } from '/@/store/modules/mine';
-  import { get, last } from 'lodash-es';
+  import { find, get, last } from 'lodash-es';
   // import { env } from '/@/views/system/cadFile/env';
   import { StatusColorEnum } from '/@/enums/jeecgEnum';
   import { generateSimplePopup } from './hooks/popup';
   import { initMap2d, renderGoafMarkers } from '/@/views/system/cadFile/app';
   import { getGoafList } from '/@/views/system/cadFile/cad.api';
   import LeafPopup from './components/LeafPopup.vue';
+  import { useDeptWatch } from '/@/hooks/component/useDeptWatcher';
   // import { useGlobSetting } from '/@/hooks/setting';
 
+  const props = defineProps<{
+    slience: boolean;
+  }>();
+
   const appStore = useAppStore();
   const mineStore = useMineDepartmentStore();
   // const globSetting = useGlobSetting();
@@ -123,6 +128,24 @@
     });
   }
 
+  /** 初始化地图对象,仅负责初始化地图及其瓦片底图,待map加载完成后返回 */
+  async function initMap(HTMLElement) {
+    const map = new vjmap.Map({
+      container: HTMLElement,
+      // 这个zoom配合了getGeoJSON,要改两边都要改
+      maxZoom: 20,
+      minZoom: 1,
+      center: [DEFAULT_NODE.longitude, DEFAULT_NODE.latitude],
+      zoom: DEFAULT_NODE.zoom,
+      trackResize: false,
+      // style: svc.rasterStyle('https://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}'),
+      style: `${window.location.origin}/js/shanxi.map.json`,
+    });
+    await map.onLoad();
+
+    return map;
+  }
+
   /** 标记点点击后,如果不是叶节点那么聚焦到下一级,如果已经是叶节点了则显示该节点的CAD地图 */
   function markerClickHandler() {
     const node: any = last(historyStack.value);
@@ -173,24 +196,6 @@
     });
   }
 
-  /** 初始化地图对象,仅负责初始化地图及其瓦片底图,待map加载完成后返回 */
-  async function initMap(HTMLElement) {
-    const map = new vjmap.Map({
-      container: HTMLElement,
-      // 这个zoom配合了getGeoJSON,要改两边都要改
-      maxZoom: 20,
-      minZoom: 1,
-      center: [DEFAULT_NODE.longitude, DEFAULT_NODE.latitude],
-      zoom: DEFAULT_NODE.zoom,
-      trackResize: false,
-      // style: svc.rasterStyle('https://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}'),
-      style: `${window.location.origin}/js/shanxi.map.json`,
-    });
-    await map.onLoad();
-
-    return map;
-  }
-
   const mapLoading = ref(false);
   let cadOpened: boolean;
   /** 切换CAD地图和瓦片地图的显示,通过重新初始化进行切换,避免出现动画异常和多个DOM节点 */
@@ -209,10 +214,12 @@
             // fileUrl: `${globSetting.apiUrl}/sys/common/static/webfile/hongliulin_default.dwg`,
             style: { backcolor: 0xe6f3ff },
           }),
-          getGoafList({
-            mineCode: data ? data.mineCode : mineStore.getRoot?.fax,
-            deptId: data ? data.id : mineStore.getRootId,
-          }),
+          props.slience
+            ? Promise.resolve([])
+            : getGoafList({
+                mineCode: data ? data.mineCode : mineStore.getRoot?.fax,
+                deptId: data ? data.id : mineStore.getRootId,
+              }),
         ]);
         map = m;
 
@@ -221,10 +228,12 @@
         // const hide = message.loading('地图加载中...', 0);
         const [m, res] = await Promise.all([
           initMap(mapContainer.value!),
-          getGeoJSON({
-            deptId: mineStore.getRootId,
-            pageSize: 9999,
-          }),
+          props.slience
+            ? getShanxiGeoJSON().then((r) => [r, {}, []])
+            : getGeoJSON({
+                deptId: mineStore.getRootId,
+                pageSize: 9999,
+              }),
         ]);
         const [geojson, __, markers] = res;
         // hide();
@@ -238,8 +247,23 @@
     }
   }
 
+  function initDeptWatcher() {
+    useDeptWatch((id) => {
+      const { source } = map.getLayer(CIRCLE_LAYER_ID) as any;
+      const { features } = map.getSourceData(source);
+      const element = find(features, (e) => e.id === id)?.properties;
+
+      if (!element) return;
+      historyStack.value.push(element);
+      markerClickHandler();
+    });
+  }
+
   onMounted(() => {
-    toggleCADMap(mineStore.getRoot?.isLeaf || false);
+    toggleCADMap(mineStore.getRoot?.isLeaf || false).then(() => {
+      if (props.slience) return;
+      initDeptWatcher();
+    });
   });
 
   onUnmounted(() => {
@@ -258,6 +282,11 @@
     left: 0;
     z-index: @simple-map-z-index;
     // filter: grayscale(80%) invert(0%) sepia(10%) hue-rotate(150deg) saturate(200%) brightness(100%) contrast(100%);
+
+    canvas {
+      width: 100% !important;
+      height: 100% !important;
+    }
   }
 
   .cad-container {

+ 26 - 0
src/layouts/default/header/index.less

@@ -102,6 +102,32 @@
     min-width: 0;
     flex: 1;
     align-items: center;
+    padding: 0 5%;
+
+    .ant-cascader {
+      width: 300px;
+
+      .ant-select-selector {
+        color: @white;
+        padding: 0 20px;
+        border-radius: 20px;
+        border-color: transparent;
+        background-color: #ffffff22 !important;
+        .ant-select-selection-placeholder {
+          color: @white;
+        }
+
+        .ant-select-selection-item {
+          color: @white !important;
+        }
+      }
+
+      .ant-select {
+        .ant-select-clear {
+          background: gray;
+        }
+      }
+    }
   }
 
   &-action {

+ 13 - 0
src/layouts/default/header/index.vue

@@ -8,6 +8,11 @@
     <!-- left end -->
 
     <!-- menu start -->
+    <div :class="`${prefixCls}-menu`">
+      <MineCascader v-model:value="deptId" :changeOnSelect="true" :initFromStore="true" @change="setGlobDept">
+        <template #clearIcon>X</template>
+      </MineCascader>
+    </div>
     <!-- menu-end -->
 
     <!-- action  -->
@@ -61,6 +66,9 @@
   import LoginSelect from '/@/views/sys/login/LoginSelect.vue';
   import { useUserStore } from '/@/store/modules/user';
   import { useI18n } from '/@/hooks/web/useI18n';
+  import MineCascader from '/@/components/Form/src/jeecg/components/MineCascader/MineCascader.vue';
+  import { useDeptSetter } from '/@/hooks/component/useDeptWatcher';
+
   const { t } = useI18n();
 
   export default defineComponent({
@@ -76,6 +84,7 @@
       ErrorAction,
       LockScreen,
       LoginSelect,
+      MineCascader,
       SettingDrawer: createAsyncComponent(() => import('/@/layouts/default/setting/index.vue'), {
         loading: true,
       }),
@@ -157,6 +166,8 @@
         showLoginSelect();
       });
 
+      const { deptId, setGlobDept } = useDeptSetter();
+
       return {
         prefixCls,
         getHeaderClass,
@@ -176,6 +187,8 @@
         loginSelectRef,
         title,
         t,
+        deptId,
+        setGlobDept,
       };
     },
   });

+ 1 - 1
src/layouts/default/index.vue

@@ -4,7 +4,7 @@
     <LayoutFeatures />
     <LayoutHeader />
     <!-- <SystemSelect /> -->
-    <SimpleMap />
+    <SimpleMap :slience="true" />
     <Layout :class="[layoutClass]">
       <LayoutSideBar />
       <Layout :class="`${prefixCls}-main`">

+ 1 - 1
src/layouts/default/plain.vue

@@ -3,7 +3,7 @@
   <Layout :class="prefixCls" v-bind="lockEvents">
     <LayoutFeatures />
     <LayoutHeader />
-    <SimpleMap />
+    <SimpleMap :slience="false" />
     <LayoutContent />
   </Layout>
 </template>