From 1b0475068a27cb1742a4a3971dd6c08e77f006b6 Mon Sep 17 00:00:00 2001
From: Cano1997 <1978141412@qq.com>
Date: Wed, 13 Aug 2025 21:29:26 +0800
Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=E5=9C=B0=E5=9B=BE=E6=94=AF?=
=?UTF-8?q?=E6=8C=81=E4=B8=8B=E9=92=BB=E3=80=81=E8=BF=94=E5=9B=9E=E3=80=81?=
=?UTF-8?q?=E9=A1=B9=E6=A0=B7=E5=BC=8F=E3=80=81=E8=A1=8C=E6=94=BF=E7=AD=89?=
=?UTF-8?q?=E7=BA=A7=E3=80=81=E6=BF=80=E6=B4=BB=E6=A8=A1=E5=BC=8F?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/common/map-chart-user/map-chart-user.scss | 9 +-
src/common/map-chart-user/map-chart-user.tsx | 170 ++++++++++++++----
.../map-chart-user/map-chart-user.util.ts | 66 ++++++-
src/common/map-chart-user/map-user-manager.ts | 80 +++++++--
4 files changed, 272 insertions(+), 53 deletions(-)
diff --git a/src/common/map-chart-user/map-chart-user.scss b/src/common/map-chart-user/map-chart-user.scss
index 04a3d4108..f99339e0b 100644
--- a/src/common/map-chart-user/map-chart-user.scss
+++ b/src/common/map-chart-user/map-chart-user.scss
@@ -21,7 +21,14 @@
cursor: pointer;
}
+ @include e(fullscreen) {
+ position: absolute;
+ top: getCssVar(spacing, tight);
+ right: getCssVar(spacing, tight);
+ z-index: 9;
+ }
+
@include e(popper) {
- padding: getCssVar(spacing, base);
+ padding: getCssVar(spacing, tight);
}
}
\ No newline at end of file
diff --git a/src/common/map-chart-user/map-chart-user.tsx b/src/common/map-chart-user/map-chart-user.tsx
index 4145a5751..1296c1e40 100644
--- a/src/common/map-chart-user/map-chart-user.tsx
+++ b/src/common/map-chart-user/map-chart-user.tsx
@@ -1,8 +1,17 @@
/* eslint-disable eqeqeq */
-import { defineComponent, onMounted, PropType, computed } from 'vue';
+import {
+ defineComponent,
+ onMounted,
+ PropType,
+ computed,
+ ref,
+ onBeforeUnmount,
+} from 'vue';
import { isNil, mergeDeepLeft, mergeDeepWithKey } from 'ramda';
import { useNamespace } from '@ibiz-template/vue3-util';
import { IMapData, MapController } from '@ibiz-template/runtime';
+import { listenJSEvent, NOOP } from '@ibiz-template/core';
+import { toNumber } from 'lodash-es';
import {
defaultOpts,
getAreaOption,
@@ -38,6 +47,8 @@ export const IBizMapChartUser = defineComponent({
const ns = useNamespace('map-chart-user');
const c = props.controller;
let option: IData = defaultOpts;
+ const mapRef = ref();
+ const isFull = ref(false);
if (c.controlParams.defaultopts) {
const data = JSON.parse(c.controlParams.defaultopts);
option = mergeDeepLeft(data, option);
@@ -53,57 +64,148 @@ export const IBizMapChartUser = defineComponent({
);
});
- const { chartRef, historyNames, changeMap, getCityInfo, goBack } =
- useMapManager(props.controller, options, mapName => {
- const areaData = props.areaData || [];
- const pointData = props.pointData || [];
+ let cleanup = NOOP;
- const tooltip = getTooltip();
- const visualMap = getVisualMap(options.value);
- const cityInfo = getCityInfo();
- const pointOption = {
- ...getPointStaticOption(options.value),
- ...getPointOption(pointData, areaData),
- };
- const areaOption = {
- ...getAreaStaticOption(options.value),
- ...getAreaOption(mapName, pointData, areaData, cityInfo),
- };
+ const {
+ chartRef,
+ historyNames,
+ processing,
+ areaLevelMap,
+ changeMap,
+ getCityInfo,
+ goBack,
+ } = useMapManager(props.controller, options, mapName => {
+ const areaData = props.areaData || [];
+ const pointData = props.pointData || [];
- const result: IData = {
- geo: {
- map: mapName,
- },
- tooltip,
- visualMap,
- series: [
- // 地图区块序列
- areaOption,
- // 地图散点序列
- pointOption,
- ],
- };
- return result;
- });
+ const tooltip = getTooltip();
+ const visualMap = getVisualMap(options.value);
+ const cityInfo = getCityInfo();
+ const pointOption = {
+ ...getPointStaticOption(options.value),
+ ...getPointOption(pointData, areaData),
+ };
+ const { top, bottom } = options.value;
+ const areaOption = {
+ top,
+ bottom,
+ ...getAreaStaticOption(options.value),
+ ...getAreaOption(mapName, pointData, areaData, cityInfo),
+ };
+
+ const result: IData = {
+ geo: {
+ map: mapName,
+ top,
+ bottom,
+ },
+ tooltip,
+ visualMap,
+ series: [
+ // 地图区块序列
+ areaOption,
+ // 地图散点序列
+ pointOption,
+ ],
+ };
+ return result;
+ });
onMounted(() => {
const name = options.value.defaultAreaCode;
const areaCode = c.state.strAreaCode ? `${name}` : Number(name);
c.state.areaCode = areaCode;
changeMap(name, areaCode, true);
+
+ c.evt.on('onDrillDown', async (args: IData) => {
+ if (!processing.value) {
+ const { data } = args;
+ const code = data.areaCode;
+ const curAreaCode = c.state.strAreaCode ? `${code}` : Number(code);
+ const areaLevel = areaLevelMap.get(toNumber(curAreaCode)) || '';
+ c.state.areaCode = curAreaCode;
+ c.state.areaLevel = areaLevel;
+ await changeMap(code, code);
+ }
+ });
+ c.evt.on('onBackClick', () => {
+ if (!processing.value) {
+ goBack();
+ }
+ });
+
+ cleanup = listenJSEvent(window, 'resize', () => {
+ if (isFull.value) {
+ isFull.value = ibiz.fullscreenUtil.isFullScreen;
+ }
+ });
+ });
+
+ // 组件销毁前销毁监听
+ onBeforeUnmount(() => {
+ if (cleanup !== NOOP) {
+ cleanup();
+ }
});
- return { ns, chartRef, historyNames, goBack };
+ const onBack = async () => {
+ processing.value = true;
+ await c.evt.emit('onBackClick', undefined);
+ goBack();
+ processing.value = false;
+ };
+
+ /**
+ * @description 切换全屏
+ */
+ const toggleFullScreen = () => {
+ if (mapRef.value) {
+ if (isFull.value) {
+ ibiz.fullscreenUtil.closeElementFullscreen();
+ } else {
+ ibiz.fullscreenUtil.openElementFullscreen(mapRef.value);
+ }
+ isFull.value = !isFull.value;
+ }
+ };
+
+ return {
+ ns,
+ c,
+ mapRef,
+ chartRef,
+ historyNames,
+ isFull,
+ onBack,
+ toggleFullScreen,
+ };
},
render() {
+ const { enabledFullScreen } = this.c.state;
return (
-
+
+ {enabledFullScreen ? (
+
+
+
+ ) : null}
{this.historyNames.length > 1 && (
{
- this.goBack();
+ this.onBack();
}}
>
{ibiz.i18n.t('app.return')}
diff --git a/src/common/map-chart-user/map-chart-user.util.ts b/src/common/map-chart-user/map-chart-user.util.ts
index becc662ba..33eef61ce 100644
--- a/src/common/map-chart-user/map-chart-user.util.ts
+++ b/src/common/map-chart-user/map-chart-user.util.ts
@@ -43,10 +43,39 @@ export const defaultOpts = {
jsonBaseUrl: `${ibiz.env.assetsUrl}/json/map`,
/** 默认打开的区域编码 */
defaultAreaCode: 100000 as string | number,
+ // 距离底部距离
+ bottom: 20,
+ // 距离顶部距离
+ top: 20,
};
export type MapOptions = typeof defaultOpts;
+/**
+ * @description 获取项样式
+ * @param {IData} item
+ * @returns {*} {string}
+ */
+const getItemStyle = (item: IData): string => {
+ const itemStyle = [];
+ if (item._color) {
+ itemStyle.push(`color:${item._color}`);
+ }
+ if (item._bgcolor) {
+ itemStyle.push(`background:${item._bgcolor}`);
+ }
+ if (item._borderColor) {
+ itemStyle.push(`border-color:${item._borderColor}`);
+ }
+ if (item._borderWidth) {
+ itemStyle.push(`border-width:${item._borderWidth}px`);
+ }
+ if (item._borderWidth && item._borderColor) {
+ itemStyle.push(`border-style:solid`);
+ }
+ return itemStyle.join(';');
+};
+
export const findData = (
id: string,
type: 'area' | 'point',
@@ -119,9 +148,21 @@ export const getPointOption = (
return;
}
const find = findData(params.data._id, 'point', pointData, areaData)!;
- return `
${find?._tooltip}
`;
+ if (!find) {
+ return;
+ }
+ const { _deData: data } = find;
+ let text = data.srfmajortext;
+ if (find._value) {
+ text = `${data.srfmajortext}: ${find._value}`;
+ }
+ if (find._tooltip) {
+ text = find._tooltip;
+ }
+ const style = getItemStyle(find);
+ return `
${text}
`;
},
padding: 0,
};
@@ -189,9 +230,22 @@ export const getAreaOption = (
return;
}
const find = findData(params.data._id, 'area', pointData, areaData)!;
- return `
${find?._tooltip}
`;
+ if (!find || (!find._tooltip && !find._value)) {
+ return;
+ }
+ const { _deData: data } = find;
+ let text = data.srfmajortext;
+ if (find._value) {
+ text = `${data.srfmajortext}: ${find._value}`;
+ }
+ if (find._tooltip) {
+ text = find._tooltip;
+ }
+ // 项样式作为弹框样式,弹框默认内容为主信息+值,可配置提示属性实体处理逻辑来调整提示框内容
+ const style = getItemStyle(find);
+ return `
${text}
`;
},
padding: 0,
};
diff --git a/src/common/map-chart-user/map-user-manager.ts b/src/common/map-chart-user/map-user-manager.ts
index 76cb9e17c..c9212a066 100644
--- a/src/common/map-chart-user/map-user-manager.ts
+++ b/src/common/map-chart-user/map-user-manager.ts
@@ -3,6 +3,7 @@ import { registerMap as register, EChartsType, init } from 'echarts';
import { ComputedRef, onMounted, onUnmounted, ref } from 'vue';
import { IMapData, MapController } from '@ibiz-template/runtime';
import { listenJSEvent } from '@ibiz-template/core';
+import { toNumber } from 'lodash-es';
import { findData, MapOptions, getJsonUrl } from './map-chart-user.util';
/**
@@ -26,6 +27,10 @@ export function useMapManager(
const historyNames = ref
([]);
+ const areaLevelMap = new Map();
+
+ const processing = ref(false);
+
let chart: EChartsType;
const chartRef = ref();
@@ -38,8 +43,9 @@ export function useMapManager(
noChild: json.features.length === 1,
};
json.features.forEach((item: IData) => {
- const { adcode, name } = item.properties;
+ const { adcode, name, level } = item.properties;
info.cityNames[adcode] = name;
+ areaLevelMap.set(adcode, level);
});
return info;
};
@@ -76,16 +82,19 @@ export function useMapManager(
areaCode: string | number,
isInit: boolean = false,
) => {
- if (!isInit) {
- controller.onMapChange(areaCode);
- }
const strName = `${name}`;
-
if (!mapInfos.has(strName)) {
await registerMap(strName);
}
- controller.state.mapInfo = getCityInfo()!;
+ if (!isInit) {
+ controller.onMapChange(areaCode);
+ } else {
+ // 初次加载设置默认行政等级
+ const areaLevel = areaLevelMap.get(toNumber(areaCode)) || '';
+ controller.state.areaLevel = areaLevel;
+ }
currentName.value = strName;
+ controller.state.mapInfo = getCityInfo()!;
historyNames.value.push(strName);
refresh();
};
@@ -96,8 +105,9 @@ export function useMapManager(
historyNames.value.pop(); // 先删除当前地图的name
const name = historyNames.value.pop(); // 获取上一个地图的name
const areaCode = opts.value.strAreaCode ? `${name}` : Number(name);
+ const areaLevel = areaLevelMap.get(toNumber(areaCode)) || '';
controller.state.areaCode = areaCode;
- await controller.evt.emit('onBackClick', undefined);
+ controller.state.areaLevel = areaLevel;
changeMap(name!, areaCode);
}
};
@@ -118,36 +128,80 @@ export function useMapManager(
resizeObserver.observe(chartRef.value);
}
chart.on('click', (params: IData) => {
- // 散点点击事件
if (params.componentType === 'series') {
+ // 散点点击事件
if (params.seriesType === 'scatter') {
if (!params.data) {
return;
}
+ processing.value = true;
const { pointData, areaData } = controller.state;
const data = findData(params.data._id, 'point', pointData, areaData);
if (data) {
controller.onPointClick(data as IMapData);
}
+ processing.value = false;
return;
}
+ // 区域点击事件
if (params.seriesType === 'map') {
+ processing.value = true;
const areaCode = opts.value.strAreaCode
? `${params.name}`
: Number(params.name);
- controller.state.areaCode = areaCode;
- const { pointData, areaData, enabledDrillDown } = controller.state;
+ const areaLevel = areaLevelMap.get(toNumber(areaCode)) || '';
+ const { pointData, areaData, enabledDrillDown, mdctrlActiveMode } =
+ controller.state;
if (params.data) {
const data = findData(params.data._id, 'area', pointData, areaData);
if (data) {
- controller.onAreaClick(data as IMapData);
+ controller.onAreaClick(data as IMapData, areaCode, areaLevel);
}
}
// 禁止切换同一个地图,到最下级的时候会出现这种情况
- if (params.name !== currentName.value && enabledDrillDown) {
+ if (
+ params.name !== currentName.value &&
+ enabledDrillDown &&
+ mdctrlActiveMode !== 2
+ ) {
+ // 行政编码大于当前编码即下钻
+ if (toNumber(areaCode) > toNumber(controller.state.areaCode)) {
+ controller.evt.emit('onDrillDown', { data: { areaCode } });
+ }
+ controller.state.areaCode = areaCode;
+ controller.state.areaLevel = areaLevel || '';
changeMap(params.name, areaCode);
}
+ processing.value = false;
+ }
+ }
+ });
+ chart.on('dblclick', (params: IData) => {
+ // 区域点击事件
+ const { enabledDrillDown, mdctrlActiveMode } = controller.state;
+ if (
+ params.componentType === 'series' &&
+ params.seriesType === 'map' &&
+ mdctrlActiveMode === 2 &&
+ enabledDrillDown
+ ) {
+ processing.value = true;
+ const areaCode = opts.value.strAreaCode
+ ? `${params.name}`
+ : Number(params.name);
+ const areaLevel = areaLevelMap.get(toNumber(areaCode)) || '';
+ // 行政编码大于当前编码即下钻
+ if (toNumber(areaCode) > toNumber(controller.state.areaCode)) {
+ controller.evt.emit('onDrillDown', { data: { areaCode } });
+ }
+ controller.state.areaCode = areaCode;
+ controller.state.areaLevel = areaLevel;
+
+ // 禁止切换同一个地图,到最下级的时候会出现这种情况
+ if (params.name !== currentName.value) {
+ changeMap(params.name, areaCode);
}
+ processing.value = false;
}
});
@@ -193,6 +247,8 @@ export function useMapManager(
chartRef,
historyNames,
currentName,
+ processing,
+ areaLevelMap,
changeMap,
getCityInfo,
goBack,
--
Gitee
From 3382a537bb917fc846edadf54a5ffce28e3d6c28 Mon Sep 17 00:00:00 2001
From: Cano1997 <1978141412@qq.com>
Date: Wed, 13 Aug 2025 21:30:17 +0800
Subject: [PATCH 2/2] =?UTF-8?q?feat:=20=E5=9C=B0=E5=9B=BE=E5=86=85?=
=?UTF-8?q?=E7=BD=AE=E5=AF=BC=E8=88=AA=E5=8C=BA=E5=9F=9F=E5=AF=BC=E8=88=AA?=
=?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=A1=8C=E6=94=BF=E7=BC=96=E7=A0=81=E4=B8=8E?=
=?UTF-8?q?=E8=A1=8C=E6=94=BF=E7=AD=89=E7=BA=A7=E5=8F=82=E6=95=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
CHANGELOG.md | 2 ++
.../provider/map-navigation.provider.ts | 31 +++++++++++++++++--
2 files changed, 30 insertions(+), 3 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d1ad7e994..60773bcc4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,8 @@
- 新增甘特图滑块的链接线绘制,新增部件参数linkdatasourcetype(链接数据获取模式)、linkappdataentityname(链接数据集应用实体名称)、linkappdedatasetname(链接应用实体结果集名称)、linknodedataname(链接节点数据属性名称)、fromdataitemname(链接起始数据项属性名称)、todataitemname(链接结束数据项属性名称)
- 新增树节点数据拖拽状态属性
- 异步导出下载识别文件名属性
+- 地图支持下钻、返回、项样式、行政等级、激活模式
+- 地图内置导航区域导航添加行政编码与行政等级参数
### Changed
diff --git a/src/common/control-navigation/provider/map-navigation.provider.ts b/src/common/control-navigation/provider/map-navigation.provider.ts
index 2387a1c59..58319ba14 100644
--- a/src/common/control-navigation/provider/map-navigation.provider.ts
+++ b/src/common/control-navigation/provider/map-navigation.provider.ts
@@ -1,4 +1,9 @@
-import { IMapData, INavViewMsg, MapController } from '@ibiz-template/runtime';
+import {
+ IMapData,
+ IMapEvent,
+ INavViewMsg,
+ MapController,
+} from '@ibiz-template/runtime';
import { ISysMap } from '@ibiz/model-core';
import { NavgationBaseProvider } from './navigation-base.provider';
@@ -16,6 +21,20 @@ export class MapNavigationProvider extends NavgationBaseProvider {
declare model: ISysMap;
+ /**
+ * @description 导航数据变化
+ * @param {IMapEvent['onNavDataChange']['event']} event
+ * @memberof MapNavigationProvider
+ */
+ onNavDataChange(event: IMapEvent['onNavDataChange']['event']): void {
+ const { navData } = event;
+ // 数据变更才重新导航
+ if (this.navViewMsg.value?.key !== navData._id) {
+ this.navStack.unshift(navData[this.keyName]);
+ this.navViewMsg.value = this.getNavViewMsg(navData as IMapData);
+ }
+ }
+
onNavDataByStack(): void {
const { items } = this.controller.state;
const navData =
@@ -30,16 +49,22 @@ export class MapNavigationProvider extends NavgationBaseProvider {
}
}
- getNavViewMsg(item: IMapData): INavViewMsg {
+ getNavViewMsg(item: IData): INavViewMsg {
const { sysMapItems } = this.model;
+ const { areaCode, areaLevel } = item;
const itemModel = sysMapItems?.find(_item => _item.id === item._mapItemId);
if (itemModel) {
const { context, params } = this.prepareParams(
itemModel,
- item._deData,
+ { ...item._deData, areaCode, areaLevel },
this.controller.context,
this.controller.params,
);
+ // 区域导航视图添加行政编码与行政等级
+ if (itemModel.itemStyle?.startsWith('REGION')) {
+ params.srfareacode = areaCode;
+ params.srfarealevel = areaLevel;
+ }
return {
params,
context,
--
Gitee