Commit fbfab9c1c3d41760f2dcb8d52749aef7f24cc25f
Merge branch 'ft' into 'main_dev'
fix(src/packages): 图表地图 地图右侧配置回显省份选择城市选择 See merge request yunteng/thingskit-view!112
Showing
19 changed files
with
725 additions
and
66 deletions
... | ... | @@ -46,6 +46,7 @@ export const getPlatformInfo = () => defHttp.get({ url: Api.PLATFORM }) |
46 | 46 | export const getConfigurationList = (params: object) => { |
47 | 47 | return defHttp.get({ url: `${Api.CONFIGURATION}`, params }) |
48 | 48 | } |
49 | + | |
49 | 50 | //组态设置是否公开或私有 |
50 | 51 | export const setConfigurationIsShare = (params: string,isShare:boolean,data:object) => { |
51 | 52 | return defHttp.post({ |
... | ... | @@ -53,3 +54,15 @@ export const setConfigurationIsShare = (params: string,isShare:boolean,data:obje |
53 | 54 | data |
54 | 55 | }) |
55 | 56 | } |
57 | + | |
58 | +// 获取设备状态,在线 or 离线时间 | |
59 | +export const getDeviceActiveTime = (entityId: string) => { | |
60 | + return defHttp.get( | |
61 | + { | |
62 | + url: `/plugins/telemetry/DEVICE/${entityId}/values/attributes?keys=active`, | |
63 | + }, | |
64 | + { | |
65 | + joinPrefix: false, | |
66 | + } | |
67 | + ); | |
68 | +}; | |
\ No newline at end of file | ... | ... |
1 | +import { PublicConfigClass } from '@/packages/public' | |
2 | +import { CreateComponentType } from '@/packages/index.d' | |
3 | +import { OverrideMapAmapConfig } from './index' | |
4 | +import { chartInitConfig } from '@/settings/designSetting' | |
5 | +import cloneDeep from 'lodash/cloneDeep' | |
6 | +import dataJson from './data.json' | |
7 | + | |
8 | +export type dataExtraInfoType = typeof dataJson.markers[number]['extraInfo'] //data.json下的extraInfo类型 | |
9 | + | |
10 | +export type dataJsonType = typeof dataJson //data.json类型 | |
11 | + | |
12 | +export type dataJsonMarkersType = typeof dataJson.markers[number] //data.json markers类型 | |
13 | + | |
14 | +export enum ThemeEnum { | |
15 | + NORMAL = 'normal', | |
16 | + DARK = 'dark', | |
17 | + LIGHT = 'light', | |
18 | + WHITES_MOKE = 'whitesmoke', | |
19 | + FRESH = 'fresh', | |
20 | + GREY = 'grey', | |
21 | + GRAFFITI = 'graffiti', | |
22 | + MACARON = 'macaron', | |
23 | + BLUE = 'blue', | |
24 | + DARKBLUE = 'darkblue', | |
25 | + WINE = 'wine', | |
26 | + WEIXIN = 'tileLayer' | |
27 | +} | |
28 | + | |
29 | +export enum LangEnum { | |
30 | + ZH_CN = 'zh_cn', | |
31 | + EN = 'en', | |
32 | + ZH_EN = 'zh_en' | |
33 | +} | |
34 | + | |
35 | +export enum ViewModeEnum { | |
36 | + PLANE = '2D', | |
37 | + STEREOSCOPIC = '3D' | |
38 | +} | |
39 | + | |
40 | +export enum FeaturesEnum { | |
41 | + BG = 'bg', | |
42 | + POINT = 'point', | |
43 | + ROAD = 'road', | |
44 | + BUILDING = 'building' | |
45 | +} | |
46 | + | |
47 | +export enum MarkerEnum { | |
48 | + // 圆圈 | |
49 | + CIRCLE_MARKER = 'CircleMarker', | |
50 | + // 定位标点 | |
51 | + MARKER = 'Marker', | |
52 | + // 暂无 | |
53 | + NONE = 'none' | |
54 | +} | |
55 | + | |
56 | +export const option = { | |
57 | + dataset: dataJson, | |
58 | + mapOptions: { | |
59 | + pitch: 60, | |
60 | + skyColor: '#53A9DE', | |
61 | + amapKey: 'd5f3e16589dbecae64d05fe90e2ba4f2', | |
62 | + amapStyleKey: ThemeEnum.DARK, | |
63 | + amapStyleKeyCustom: '', | |
64 | + amapLon: 104.108689, | |
65 | + amapLat: 30.66176, | |
66 | + amapZindex: 11, | |
67 | + marker: { | |
68 | + fillColor: '#E98984FF', | |
69 | + fillOpacity: 0.5, | |
70 | + strokeColor: 'white', | |
71 | + strokeWeight: 2, | |
72 | + strokeOpacity: 0.5, | |
73 | + zIndex: 10, | |
74 | + bubble: true, | |
75 | + cursor: 'pointer', | |
76 | + clickable: true | |
77 | + }, | |
78 | + mapMarkerType: MarkerEnum.MARKER, | |
79 | + viewMode: ViewModeEnum.PLANE, | |
80 | + lang: LangEnum.ZH_CN, | |
81 | + features: [FeaturesEnum.BG, FeaturesEnum.POINT, FeaturesEnum.ROAD, FeaturesEnum.BUILDING] | |
82 | + } | |
83 | +} | |
84 | + | |
85 | +export default class Config extends PublicConfigClass implements CreateComponentType { | |
86 | + public key = OverrideMapAmapConfig.key | |
87 | + public attr = { ...chartInitConfig, w: 1000, h: 800, zIndex: -1 } | |
88 | + public chartConfig = cloneDeep(OverrideMapAmapConfig) | |
89 | + public option = cloneDeep(option) | |
90 | +} | ... | ... |
1 | +<template> | |
2 | + <collapse-item name="基础" :expanded="true"> | |
3 | + <setting-item-box name="语言类型" :alone="true"> | |
4 | + <setting-item> | |
5 | + <n-select size="small" v-model:value="optionData.mapOptions.lang" :options="langOptions" /> | |
6 | + </setting-item> | |
7 | + </setting-item-box> | |
8 | + <setting-item-box name="Key" :alone="true"> | |
9 | + <setting-item name="请务必使用自己的高德应用 key"> | |
10 | + <n-input v-model:value="optionData.mapOptions.amapKey" size="small"></n-input> | |
11 | + </setting-item> | |
12 | + </setting-item-box> | |
13 | + <setting-item-box name="自定义地图样式ID" :alone="true"> | |
14 | + <setting-item> | |
15 | + <n-input size="small" v-model:value="optionData.mapOptions.amapStyleKeyCustom" /> | |
16 | + </setting-item> | |
17 | + </setting-item-box> | |
18 | + </collapse-item> | |
19 | + <collapse-item name="地图" :expanded="true"> | |
20 | + <setting-item-box name="主题"> | |
21 | + <setting-item> | |
22 | + <n-select size="small" v-model:value="optionData.mapOptions.amapStyleKey" :options="themeOptions" /> | |
23 | + </setting-item> | |
24 | + </setting-item-box> | |
25 | + <setting-item-box name="内容" :alone="true"> | |
26 | + <n-checkbox-group v-model:value="optionData.mapOptions.features"> | |
27 | + <n-space item-style="display: flex;"> | |
28 | + <n-checkbox :value="item.value" :label="item.label" v-for="(item, index) in featuresOptions" :key="index" /> | |
29 | + </n-space> | |
30 | + </n-checkbox-group> | |
31 | + </setting-item-box> | |
32 | + <setting-item-box name="位置"> | |
33 | + <setting-item name="经度"> | |
34 | + <n-input-number v-model:value="optionData.mapOptions.amapLon" :show-button="false" size="small"> | |
35 | + <template #suffix>°</template> | |
36 | + </n-input-number> | |
37 | + </setting-item> | |
38 | + <setting-item name="纬度"> | |
39 | + <n-input-number v-model:value="optionData.mapOptions.amapLat" :show-button="false" size="small"> | |
40 | + <template #suffix>°</template> | |
41 | + </n-input-number> | |
42 | + </setting-item> | |
43 | + <setting-item name="初始缩放"> | |
44 | + <n-input-number v-model:value="optionData.mapOptions.amapZindex" :min="0" size="small"></n-input-number> | |
45 | + </setting-item> | |
46 | + </setting-item-box> | |
47 | + <setting-item-box name="模式" :alone="true"> | |
48 | + <setting-item> | |
49 | + <n-radio-group v-model:value="optionData.mapOptions.viewMode" name="radiogroup"> | |
50 | + <n-space> | |
51 | + <n-radio v-for="song in viewModeOptions" :key="song.value" :value="song.value"> | |
52 | + {{ song.label }} | |
53 | + </n-radio> | |
54 | + </n-space> | |
55 | + </n-radio-group> | |
56 | + </setting-item> | |
57 | + </setting-item-box> | |
58 | + <template v-if="optionData.mapOptions.viewMode === '3D'"> | |
59 | + <setting-item-box> | |
60 | + <setting-item name="天空色"> | |
61 | + <n-color-picker size="small" :modes="['hex']" v-model:value="optionData.mapOptions.skyColor"></n-color-picker> | |
62 | + </setting-item> | |
63 | + <setting-item name="俯仰角"> | |
64 | + <n-input-number v-model:value="optionData.mapOptions.pitch" :min="0" :max="83" size="small"></n-input-number> | |
65 | + </setting-item> | |
66 | + </setting-item-box> | |
67 | + </template> | |
68 | + </collapse-item> | |
69 | + <collapse-item name="标记" :expanded="true"> | |
70 | + <setting-item-box name="样式"> | |
71 | + <setting-item name="类型"> | |
72 | + <n-select size="small" v-model:value="optionData.mapOptions.mapMarkerType" :options="MarkerOptions" /> | |
73 | + </setting-item> | |
74 | + <setting-item name="颜色"> | |
75 | + <n-color-picker v-model:value="optionData.mapOptions.marker.fillColor" size="small"></n-color-picker> | |
76 | + </setting-item> | |
77 | + </setting-item-box> | |
78 | + </collapse-item> | |
79 | +</template> | |
80 | + | |
81 | +<script setup lang="ts"> | |
82 | +import { PropType } from 'vue' | |
83 | +import { option, MarkerEnum, ThemeEnum, LangEnum, ViewModeEnum, FeaturesEnum } from './config' | |
84 | +import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting' | |
85 | + | |
86 | +defineProps({ | |
87 | + optionData: { | |
88 | + type: Object as PropType<typeof option>, | |
89 | + required: true | |
90 | + } | |
91 | +}) | |
92 | + | |
93 | +const themeOptions = [ | |
94 | + { | |
95 | + value: ThemeEnum.NORMAL, | |
96 | + label: '标准' | |
97 | + }, | |
98 | + { | |
99 | + value: ThemeEnum.DARK, | |
100 | + label: '幻影黑' | |
101 | + }, | |
102 | + { | |
103 | + value: ThemeEnum.LIGHT, | |
104 | + label: '月光银' | |
105 | + }, | |
106 | + { | |
107 | + value: ThemeEnum.WHITES_MOKE, | |
108 | + label: '远山黛' | |
109 | + }, | |
110 | + { | |
111 | + value: ThemeEnum.FRESH, | |
112 | + label: '草色青' | |
113 | + }, | |
114 | + { | |
115 | + value: ThemeEnum.GREY, | |
116 | + label: '雅士灰' | |
117 | + }, | |
118 | + { | |
119 | + value: ThemeEnum.GRAFFITI, | |
120 | + label: '涂鸦' | |
121 | + }, | |
122 | + { | |
123 | + value: ThemeEnum.MACARON, | |
124 | + label: '马卡龙' | |
125 | + }, | |
126 | + { | |
127 | + value: ThemeEnum.BLUE, | |
128 | + label: '靛青蓝' | |
129 | + }, | |
130 | + { | |
131 | + value: ThemeEnum.DARKBLUE, | |
132 | + label: '极夜蓝' | |
133 | + }, | |
134 | + { | |
135 | + value: ThemeEnum.WINE, | |
136 | + label: '酱籽' | |
137 | + }, | |
138 | + { | |
139 | + value: ThemeEnum.WEIXIN, | |
140 | + label: '卫星' | |
141 | + } | |
142 | +] | |
143 | + | |
144 | +const langOptions = [ | |
145 | + { | |
146 | + value: LangEnum.ZH_CN, | |
147 | + label: '中文简体' | |
148 | + }, | |
149 | + { | |
150 | + value: LangEnum.EN, | |
151 | + label: '英文' | |
152 | + }, | |
153 | + { | |
154 | + value: LangEnum.ZH_EN, | |
155 | + label: '中英文对照' | |
156 | + } | |
157 | +] | |
158 | + | |
159 | +const viewModeOptions = [ | |
160 | + { | |
161 | + value: ViewModeEnum.PLANE, | |
162 | + label: '2D' | |
163 | + }, | |
164 | + { | |
165 | + value: ViewModeEnum.STEREOSCOPIC, | |
166 | + label: '3D' | |
167 | + } | |
168 | +] | |
169 | + | |
170 | +const featuresOptions = [ | |
171 | + { | |
172 | + value: FeaturesEnum.BG, | |
173 | + label: '显示地图背景' | |
174 | + }, | |
175 | + { | |
176 | + value: FeaturesEnum.POINT, | |
177 | + label: '显示标识' | |
178 | + }, | |
179 | + { | |
180 | + value: FeaturesEnum.ROAD, | |
181 | + label: '显示道路' | |
182 | + }, | |
183 | + { | |
184 | + value: FeaturesEnum.BUILDING, | |
185 | + label: '显示建筑' | |
186 | + } | |
187 | +] | |
188 | + | |
189 | +const MarkerOptions = [ | |
190 | + { | |
191 | + value: MarkerEnum.CIRCLE_MARKER, | |
192 | + label: '圆形标点' | |
193 | + }, | |
194 | + { | |
195 | + value: MarkerEnum.MARKER, | |
196 | + label: '定位标点' | |
197 | + }, | |
198 | + { | |
199 | + value: MarkerEnum.NONE, | |
200 | + label: '隐藏标点' | |
201 | + } | |
202 | +] | |
203 | +</script> | ... | ... |
1 | +{ | |
2 | + "markers": [ | |
3 | + { | |
4 | + "name": "模拟11111111111", | |
5 | + "value": 20, | |
6 | + "position": [103.856504, 30.687278], | |
7 | + "extraInfo": { | |
8 | + "tbDeviceId": "@xxxxxxxxxxx", | |
9 | + "name": "模拟11111111111", | |
10 | + "alias": "模拟11111111111", | |
11 | + "organizationDTO": { | |
12 | + "name": "模拟11111111111" | |
13 | + }, | |
14 | + "deviceState": "INACTIVE", | |
15 | + "deviceProfile": { | |
16 | + "transportType": "MQTT" | |
17 | + }, | |
18 | + "deviceInfo": { | |
19 | + "address": "四川省", | |
20 | + "longitude": 103.856504, | |
21 | + "latitude": 30.687278 | |
22 | + } | |
23 | + } | |
24 | + }, | |
25 | + { | |
26 | + "name": "模拟22222222222", | |
27 | + "value": 30, | |
28 | + "position": [104.095368, 30.716787], | |
29 | + "extraInfo": { | |
30 | + "tbDeviceId": "@xxxxxxxxxxxxxxx", | |
31 | + "name": "模拟22222222222", | |
32 | + "alias": "模拟22222222222", | |
33 | + "organizationDTO": { | |
34 | + "name": "模拟22222222222" | |
35 | + }, | |
36 | + "deviceState": "INACTIVE", | |
37 | + "deviceProfile": { | |
38 | + "transportType": "TCP" | |
39 | + }, | |
40 | + "deviceInfo": { | |
41 | + "address": "四川省", | |
42 | + "longitude": 104.095368, | |
43 | + "latitude": 30.716787 | |
44 | + } | |
45 | + } | |
46 | + } | |
47 | + ] | |
48 | +} | ... | ... |
851 Bytes
582 Bytes
514 Bytes
1 | +import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d' | |
2 | +import { ChatCategoryEnum, ChatCategoryEnumName } from '@/packages/components/Charts/index.d' | |
3 | +import { useWidgetKey } from '@/packages/external/useWidgetKey' | |
4 | + | |
5 | +const { key, conKey, chartKey } = useWidgetKey('OverrideMapAmap', true) | |
6 | + | |
7 | +export const OverrideMapAmapConfig: ConfigType = { | |
8 | + key, | |
9 | + chartKey, | |
10 | + conKey, | |
11 | + title: '高德地图', | |
12 | + category: ChatCategoryEnum.MAP, | |
13 | + categoryName: ChatCategoryEnumName.MAP, | |
14 | + package: PackagesCategoryEnum.CHARTS, | |
15 | + chartFrame: ChartFrameEnum.COMMON, | |
16 | + image: 'map_amap.png' | |
17 | +} | ... | ... |
1 | +<template> | |
2 | + <div ref="vChartRef"></div> | |
3 | +</template> | |
4 | + | |
5 | +<script setup lang="ts"> | |
6 | +import { ref, PropType, toRefs, watch } from 'vue' | |
7 | +import AMapLoader from '@amap/amap-jsapi-loader' | |
8 | +import { CreateComponentType } from '@/packages/index.d' | |
9 | +import { useChartDataFetch } from '@/hooks' | |
10 | +import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' | |
11 | +import { MarkerEnum, ThemeEnum, dataExtraInfoType, dataJsonType, dataJsonMarkersType } from './config' | |
12 | +import { isArray } from '@/utils' | |
13 | +import djh from './images/djh.png' | |
14 | +import online from './images/online.png' | |
15 | +import lx1 from './images/lx1.png' | |
16 | +import { getDeviceActiveTime } from '@/api/external/common/index' | |
17 | +import dayjs from 'dayjs' | |
18 | + | |
19 | +const props = defineProps({ | |
20 | + chartConfig: { | |
21 | + type: Object as PropType<CreateComponentType>, | |
22 | + required: true | |
23 | + } | |
24 | +}) | |
25 | + | |
26 | +let { | |
27 | + amapKey, | |
28 | + amapStyleKey, | |
29 | + amapLon, | |
30 | + amapLat, | |
31 | + amapZindex, | |
32 | + mapMarkerType, | |
33 | + lang, | |
34 | + amapStyleKeyCustom, | |
35 | + features, | |
36 | + viewMode, | |
37 | + pitch, | |
38 | + skyColor, | |
39 | + marker | |
40 | +} = toRefs(props.chartConfig.option.mapOptions) | |
41 | + | |
42 | +//官方没有高德地图api的ts,所以类型全用的any | |
43 | +let mapIns: any = null | |
44 | +let markers: any = [] | |
45 | +let AMapIns: any = null | |
46 | +const vChartRef = ref<HTMLElement>() | |
47 | + | |
48 | +const initMap = (newData: any) => { | |
49 | + // 初始化 | |
50 | + AMapLoader.load({ | |
51 | + key: amapKey.value, //api服务key--另外需要在public中使用安全密钥!!! | |
52 | + version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15 | |
53 | + plugins: ['AMap.PlaceSearch', 'AMap.AutoComplete'] // 需要使用的的插件列表 | |
54 | + }) | |
55 | + .then(AMap => { | |
56 | + AMapIns = AMap | |
57 | + mapIns = new AMap.Map(vChartRef.value, { | |
58 | + resizeEnable: true, | |
59 | + zoom: amapZindex.value, // 地图显示的缩放级别 | |
60 | + center: [amapLon.value, amapLat.value], | |
61 | + lang: lang.value, | |
62 | + features: features.value, | |
63 | + pitch: pitch.value, // 地图俯仰角度,有效范围 0 度- 83 度 | |
64 | + skyColor: skyColor.value, | |
65 | + viewMode: viewMode.value, // 地图模式 | |
66 | + willReadFrequently: true | |
67 | + }) | |
68 | + dataHandle(props.chartConfig.option.dataset) //处理地图标点 | |
69 | + let satellite = new AMap.TileLayer.Satellite() | |
70 | + let roadNet = new AMap.TileLayer.RoadNet() | |
71 | + if (newData.amapStyleKey === ThemeEnum.WEIXIN) { | |
72 | + mapIns.add([satellite, roadNet]) | |
73 | + } else { | |
74 | + mapIns.remove([satellite, roadNet]) | |
75 | + mapIns.setMapStyle( | |
76 | + `amap://styles/${amapStyleKeyCustom.value !== '' ? amapStyleKeyCustom.value : amapStyleKey.value}` | |
77 | + ) | |
78 | + } | |
79 | + //点击地图任意地方关闭infoWindow窗体 | |
80 | + mapIns.on('click', () => { | |
81 | + mapIns.clearInfoWindow() | |
82 | + }) | |
83 | + }) | |
84 | + .catch(e => { | |
85 | + console.error(e) | |
86 | + }) | |
87 | +} | |
88 | + | |
89 | +//创建信息弹窗 | |
90 | +const createInfoWindow = async (extraInfo: dataExtraInfoType) => { | |
91 | + try { | |
92 | + const { name, alias, organizationDTO, deviceState, deviceProfile, deviceInfo, tbDeviceId } = extraInfo | |
93 | + if (tbDeviceId.startsWith('@')) return //假的模拟数据则终止 | |
94 | + const res = await getDeviceActiveTime(tbDeviceId) //查询设备最后离线时间 | |
95 | + let { lastUpdateTs } = res[0] | |
96 | + const lastUpdateFormatTs = dayjs(lastUpdateTs).format('YYYY-MM-DD HH:mm:ss') | |
97 | + return ` | |
98 | + <div style="width:15vw;height:18vh;background-color:white;"> | |
99 | + <div style="margin:0px 10px"> | |
100 | + <div style="display:flex;justify-content:space-between; margin:20px 0px;"> | |
101 | + <div style="font-size:16px;font-weight:bold">${alias || name}</div> | |
102 | + ${ | |
103 | + deviceState === 'INACTIVE' | |
104 | + ? `<div style="display:flex;align-items:center;"><img style="width:15px;height:15px" src="${djh}" class="mr-1">待激活</div>` | |
105 | + : deviceState === 'ONLINE' | |
106 | + ? `<div style="display:flex;align-items:center; "> | |
107 | + <img style="width:15px;height:15px" src="${online}" class="mr-1">在线</div>` | |
108 | + : `<div style="display:flex;align-items:center;"><img style="width:15px;height:15px" src="${lx1}" class="mr-1">离线</div>` | |
109 | + } | |
110 | + </div> | |
111 | + <div>所属组织:${organizationDTO.name}</div> | |
112 | + <div style="margin-top:6px;">接入协议:${deviceProfile.transportType}</div> | |
113 | + <div style="margin-top:6px;"> | |
114 | + 设备位置:${!deviceInfo.address ? '该设备暂无地理位置' : deviceInfo.address} | |
115 | + </div> | |
116 | + <div style="margin-top:6px;"> | |
117 | + ${ | |
118 | + deviceState === 'ONLINE' ? '在线' : deviceState === 'INACTIVE' ? '创建' : '离线' | |
119 | + }时间:${lastUpdateFormatTs} | |
120 | + </div> | |
121 | + </div> | |
122 | + </div> | |
123 | + ` | |
124 | + } catch (e) { | |
125 | + console.error(e) | |
126 | + } | |
127 | +} | |
128 | + | |
129 | +//地图点击 | |
130 | +const mapClick = (markerInstance: any, markerItem: dataJsonMarkersType) => { | |
131 | + markerInstance.setExtData({ | |
132 | + extraInfo: markerItem.extraInfo | |
133 | + }) | |
134 | + markerInstance.setLabel({ | |
135 | + content: markerItem.extraInfo.alias || markerItem.extraInfo.name | |
136 | + }) | |
137 | + markerInstance.on('click', async (e: any) => { | |
138 | + const { extraInfo } = e.target.getExtData() | |
139 | + let infoWindow = new AMapIns.InfoWindow({ | |
140 | + content: await createInfoWindow(extraInfo), | |
141 | + offset: new AMapIns.Pixel(0, -50) | |
142 | + }) | |
143 | + infoWindow.open(mapIns, e.target.getPosition()) | |
144 | + }) | |
145 | +} | |
146 | + | |
147 | +const dataHandle = (newData: dataJsonType) => { | |
148 | + if (!mapIns && !AMapIns) { | |
149 | + initMap(props.chartConfig.option) | |
150 | + return | |
151 | + } | |
152 | + if (isArray(newData.markers)) { | |
153 | + // 先清除旧标记 | |
154 | + mapIns.remove(markers) | |
155 | + markers = [] | |
156 | + // 记录新标记 | |
157 | + if (mapMarkerType.value === MarkerEnum.MARKER) { | |
158 | + newData.markers.forEach((markerItem: dataJsonMarkersType) => { | |
159 | + const markerInstance = new AMapIns.Marker({ | |
160 | + position: [markerItem.position[0], markerItem.position[1]], | |
161 | + offset: new AMapIns.Pixel(-13, -30) | |
162 | + }) | |
163 | + // markers.push(markerInstance) 原作者这种方式添加,属于JS API 1.4.8版本的 | |
164 | + // markerInstance.setMap(mapIns) | |
165 | + mapIns.add(markerInstance) | |
166 | + mapClick(markerInstance, markerItem) | |
167 | + }) | |
168 | + } else if (mapMarkerType.value === MarkerEnum.CIRCLE_MARKER) { | |
169 | + newData.markers.forEach((markerItem: dataJsonMarkersType) => { | |
170 | + const markerInstance = new AMapIns.CircleMarker({ | |
171 | + center: [ | |
172 | + !markerItem.position[0] ? 0 : markerItem.position[0], | |
173 | + !markerItem.position[1] ? 0 : markerItem.position[1] | |
174 | + ], | |
175 | + radius: markerItem.value, //圆圈半径大小 | |
176 | + ...marker.value | |
177 | + }) | |
178 | + // markers.push(markerInstance) //原作者这种方式添加,属于JS API 1.4.8版本的 | |
179 | + // markerInstance.setMap(mapIns) | |
180 | + mapIns.add(markerInstance) | |
181 | + mapClick(markerInstance, markerItem) | |
182 | + }) | |
183 | + } | |
184 | + } | |
185 | +} | |
186 | + | |
187 | +const stopWatch = watch( | |
188 | + () => props.chartConfig.option.mapOptions, | |
189 | + option => { | |
190 | + initMap(option) | |
191 | + }, | |
192 | + { | |
193 | + immediate: true, | |
194 | + deep: true | |
195 | + } | |
196 | +) | |
197 | + | |
198 | +watch( | |
199 | + () => props.chartConfig.option.dataset, | |
200 | + newData => { | |
201 | + try { | |
202 | + dataHandle(newData) | |
203 | + } catch (error) { | |
204 | + console.log(error) | |
205 | + } | |
206 | + }, | |
207 | + { | |
208 | + deep: false | |
209 | + } | |
210 | +) | |
211 | + | |
212 | +// 预览 | |
213 | +useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => { | |
214 | + stopWatch() | |
215 | + dataHandle(newData) | |
216 | +}) | |
217 | +</script> | ... | ... |
... | ... | @@ -4,9 +4,12 @@ import { getAreaList } from '@/api/external/common/index' |
4 | 4 | import { areaEnum } from '../config' |
5 | 5 | |
6 | 6 | const props = defineProps({ |
7 | - drillingIn:{ | |
8 | - type:Boolean, | |
9 | - default:false | |
7 | + drillingIn: { | |
8 | + type: Boolean, | |
9 | + default: false | |
10 | + }, | |
11 | + optionData: { | |
12 | + type: Object | |
10 | 13 | } |
11 | 14 | }) |
12 | 15 | |
... | ... | @@ -39,6 +42,8 @@ onMounted(async () => { |
39 | 42 | label: '中国', |
40 | 43 | value: 'china' |
41 | 44 | }) |
45 | + onHandleSelectProvince(props.optionData?.mapRegion.saveSelect['provinceValue']) | |
46 | + for (let i in selectValues) Reflect.set(selectValues, i, props.optionData?.mapRegion.saveSelect[i]) | |
42 | 47 | }) |
43 | 48 | |
44 | 49 | const onHandleSelectProvince = async (value: number | string) => { | ... | ... |
... | ... | @@ -39,7 +39,7 @@ |
39 | 39 | ></n-input-number> |
40 | 40 | </SettingItem> |
41 | 41 | </SettingItemBox> |
42 | - <SelectCity :drillingIn="optionData.drillingIn" @submit="onHandleSelectValues" /> | |
42 | + <SelectCity :optionData="optionData" :drillingIn="optionData.drillingIn" @submit="onHandleSelectValues" /> | |
43 | 43 | <SettingItemBox name="区域颜色"> |
44 | 44 | <SettingItem name="0%处颜色"> |
45 | 45 | <n-color-picker |
... | ... | @@ -300,6 +300,7 @@ const mapRegion = computed(() => { |
300 | 300 | |
301 | 301 | const onHandleSelectValues = (values: any) => { |
302 | 302 | const { cityValue, countyValue, provinceValue } = values |
303 | + props.optionData.mapRegion.saveSelect = values | |
303 | 304 | props.optionData.mapRegion.adcode = countyValue |
304 | 305 | ? countyValue |
305 | 306 | : cityValue | ... | ... |
... | ... | @@ -13,7 +13,7 @@ export const option = { |
13 | 13 | // 下拉展示 |
14 | 14 | isPanel: 0, |
15 | 15 | // 默认值 |
16 | - dataset: dayjs().valueOf() as number | number[] | null, | |
16 | + dataset: [new Date().getTime() - 86400000,new Date().getTime()], | |
17 | 17 | // 默认值类型 |
18 | 18 | defaultType: DefaultTypeEnum.STATIC, |
19 | 19 | // 动态默认值偏移单位 | ... | ... |
... | ... | @@ -5,20 +5,21 @@ |
5 | 5 | :panel="!!chartConfig.option.isPanel" |
6 | 6 | :type="chartConfig.option.componentInteractEventKey" |
7 | 7 | :style="`width:${w}px;`" |
8 | - :to="false" | |
8 | + :to="true" | |
9 | 9 | @update:value="onChange" |
10 | + :shortcuts="rangeShortcuts" | |
10 | 11 | /> |
11 | 12 | </template> |
12 | 13 | |
13 | 14 | <script setup lang="ts"> |
14 | -import { PropType, toRefs, shallowReactive, watch ,ref,computed} from 'vue' | |
15 | -import dayjs, {ManipulateType} from 'dayjs' | |
15 | +import { PropType, toRefs, shallowReactive, watch, ref, computed } from 'vue' | |
16 | +import dayjs, { ManipulateType } from 'dayjs' | |
16 | 17 | import { CreateComponentType } from '@/packages/index.d' |
17 | 18 | import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' |
18 | 19 | import { useChartInteract } from '@/hooks/external/useChartDateInteract.hook' |
19 | 20 | import { InteractEventOn } from '@/enums/eventEnum' |
20 | -import {ComponentInteractEventEnum, ComponentInteractParamsEnum, DefaultTypeEnum} from './interact' | |
21 | -import quarterOfYear from 'dayjs/plugin/quarterOfYear'; | |
21 | +import { ComponentInteractEventEnum, ComponentInteractParamsEnum, DefaultTypeEnum } from './interact' | |
22 | +import quarterOfYear from 'dayjs/plugin/quarterOfYear' | |
22 | 23 | |
23 | 24 | const props = defineProps({ |
24 | 25 | chartConfig: { |
... | ... | @@ -28,8 +29,24 @@ const props = defineProps({ |
28 | 29 | }) |
29 | 30 | |
30 | 31 | const { w, h } = toRefs(props.chartConfig.attr) |
32 | + | |
31 | 33 | const rangeDate = ref<number | number[]>() |
32 | 34 | |
35 | +const rangeShortcuts = { | |
36 | + 昨天: () => { | |
37 | + const cur = new Date().getTime() | |
38 | + return [cur - 86400000, cur] as const | |
39 | + }, | |
40 | + 最近7天: () => { | |
41 | + const cur = new Date().getTime() | |
42 | + return [cur - 604800000, cur] as const | |
43 | + }, | |
44 | + 最近30天: () => { | |
45 | + const cur = new Date().getTime() | |
46 | + return [cur - 2592000000, cur] as const | |
47 | + } | |
48 | +} | |
49 | + | |
33 | 50 | const option = shallowReactive({ |
34 | 51 | dataset: props.chartConfig.option.dataset |
35 | 52 | }) |
... | ... | @@ -38,36 +55,35 @@ const isRange = computed(() => { |
38 | 55 | return props.chartConfig.option.componentInteractEventKey.endsWith('range') |
39 | 56 | }) |
40 | 57 | |
41 | - | |
42 | 58 | // 监听事件改变 |
43 | 59 | const onChange = (v: number | number[] | null) => { |
44 | 60 | if (isRange.value) { |
45 | 61 | let dateStart = null |
46 | 62 | let dateEnd = null |
47 | 63 | let daterange = null |
48 | - if(v instanceof Array){ | |
64 | + if (v instanceof Array) { | |
49 | 65 | dateStart = v[0] |
50 | 66 | dateEnd = v[1] |
51 | 67 | daterange = `${v[0]}-${v[1]}` |
52 | 68 | } |
53 | 69 | // 存储到联动数据 |
54 | 70 | useChartInteract( |
55 | - props.chartConfig, | |
56 | - useChartEditStore, | |
57 | - { | |
58 | - [ComponentInteractParamsEnum.DATE_START]: dateStart, | |
59 | - [ComponentInteractParamsEnum.DATE_END]: dateEnd, | |
60 | - [ComponentInteractParamsEnum.DATE_RANGE]: daterange | |
61 | - }, | |
62 | - InteractEventOn.CHANGE | |
71 | + props.chartConfig, | |
72 | + useChartEditStore, | |
73 | + { | |
74 | + [ComponentInteractParamsEnum.DATE_START]: dateStart, | |
75 | + [ComponentInteractParamsEnum.DATE_END]: dateEnd, | |
76 | + [ComponentInteractParamsEnum.DATE_RANGE]: daterange | |
77 | + }, | |
78 | + InteractEventOn.CHANGE | |
63 | 79 | ) |
64 | 80 | } else { |
65 | 81 | // 存储到联动数据 |
66 | 82 | useChartInteract( |
67 | - props.chartConfig, | |
68 | - useChartEditStore, | |
69 | - { [ComponentInteractParamsEnum.DATE]: v }, | |
70 | - InteractEventOn.CHANGE | |
83 | + props.chartConfig, | |
84 | + useChartEditStore, | |
85 | + { [ComponentInteractParamsEnum.DATE]: v }, | |
86 | + InteractEventOn.CHANGE | |
71 | 87 | ) |
72 | 88 | } |
73 | 89 | } |
... | ... | @@ -87,7 +103,7 @@ const getDiffDate = (type: ComponentInteractEventEnum, date: dayjs.Dayjs) => { |
87 | 103 | case ComponentInteractEventEnum.YEAR: |
88 | 104 | case ComponentInteractEventEnum.YEAR_RANGE: |
89 | 105 | date = date.startOf('year') |
90 | - break | |
106 | + break | |
91 | 107 | case ComponentInteractEventEnum.QUARTER: |
92 | 108 | case ComponentInteractEventEnum.QUARTER_RANGE: |
93 | 109 | date = date.startOf('quarter') |
... | ... | @@ -99,48 +115,50 @@ const getDiffDate = (type: ComponentInteractEventEnum, date: dayjs.Dayjs) => { |
99 | 115 | } |
100 | 116 | |
101 | 117 | watch( |
102 | - () => { | |
103 | - return { | |
104 | - type: props.chartConfig.option.componentInteractEventKey as ComponentInteractEventEnum, | |
105 | - defaultType: props.chartConfig.option.defaultType as string, | |
106 | - differValue: props.chartConfig.option.differValue as number[], | |
107 | - differUnit: props.chartConfig.option.differUnit as ManipulateType[], | |
108 | - dataset: props.chartConfig.option.dataset as number | number[] | null, | |
109 | - }; | |
110 | - }, | |
111 | - (newData, oldData) => { | |
112 | - const hasTypeChanged = newData.type !== oldData?.type; | |
113 | - const hasDefaultTypeChanged = newData.defaultType !== oldData?.defaultType; | |
114 | - const hasDifferValueChanged = newData.differValue !== oldData?.differValue; | |
115 | - const hasDifferUnitChanged = newData.differUnit !== oldData?.differUnit; | |
118 | + () => { | |
119 | + return { | |
120 | + type: props.chartConfig.option.componentInteractEventKey as ComponentInteractEventEnum, | |
121 | + defaultType: props.chartConfig.option.defaultType as string, | |
122 | + differValue: props.chartConfig.option.differValue as number[], | |
123 | + differUnit: props.chartConfig.option.differUnit as ManipulateType[], | |
124 | + dataset: props.chartConfig.option.dataset as number | number[] | null | |
125 | + } | |
126 | + }, | |
127 | + (newData, oldData) => { | |
128 | + const hasTypeChanged = newData.type !== oldData?.type | |
129 | + const hasDefaultTypeChanged = newData.defaultType !== oldData?.defaultType | |
130 | + const hasDifferValueChanged = newData.differValue !== oldData?.differValue | |
131 | + const hasDifferUnitChanged = newData.differUnit !== oldData?.differUnit | |
116 | 132 | |
117 | - if (hasTypeChanged || hasDefaultTypeChanged || hasDifferValueChanged || hasDifferUnitChanged) { | |
118 | - if (newData.defaultType === DefaultTypeEnum.NONE) { | |
119 | - props.chartConfig.option.dataset = null; | |
120 | - } else if (newData.defaultType === DefaultTypeEnum.DYNAMIC) { | |
121 | - let date = dayjs(); | |
122 | - if (isRange.value) { | |
123 | - props.chartConfig.option.dataset = [ | |
124 | - getDiffDate(newData.type,date.add(newData.differValue[0], newData.differUnit[0])).valueOf(), | |
125 | - getDiffDate(newData.type,date.add(newData.differValue[1], newData.differUnit[1])).valueOf(), | |
126 | - ]; | |
127 | - } else { | |
128 | - props.chartConfig.option.dataset = getDiffDate(newData.type,date.add(newData.differValue[0], newData.differUnit[0])).valueOf() | |
129 | - } | |
133 | + if (hasTypeChanged || hasDefaultTypeChanged || hasDifferValueChanged || hasDifferUnitChanged) { | |
134 | + if (newData.defaultType === DefaultTypeEnum.NONE) { | |
135 | + props.chartConfig.option.dataset = null | |
136 | + } else if (newData.defaultType === DefaultTypeEnum.DYNAMIC) { | |
137 | + let date = dayjs() | |
138 | + if (isRange.value) { | |
139 | + props.chartConfig.option.dataset = [ | |
140 | + getDiffDate(newData.type, date.add(newData.differValue[0], newData.differUnit[0])).valueOf(), | |
141 | + getDiffDate(newData.type, date.add(newData.differValue[1], newData.differUnit[1])).valueOf() | |
142 | + ] | |
143 | + } else { | |
144 | + props.chartConfig.option.dataset = getDiffDate( | |
145 | + newData.type, | |
146 | + date.add(newData.differValue[0], newData.differUnit[0]) | |
147 | + ).valueOf() | |
130 | 148 | } |
131 | 149 | } |
132 | - option.dataset = props.chartConfig.option.dataset; | |
133 | - onChange(option.dataset); | |
134 | - }, | |
135 | - { | |
136 | - immediate: true, | |
137 | 150 | } |
138 | -); | |
139 | - | |
151 | + option.dataset = props.chartConfig.option.dataset | |
152 | + onChange(option.dataset) | |
153 | + }, | |
154 | + { | |
155 | + immediate: true | |
156 | + } | |
157 | +) | |
140 | 158 | |
141 | 159 | watch( |
142 | 160 | () => props.chartConfig.option.shortcut, |
143 | - (newData) => { | |
161 | + newData => { | |
144 | 162 | if (!newData) return |
145 | 163 | const startTs = Date.now() - newData |
146 | 164 | const endTs = Date.now() |
... | ... | @@ -153,7 +171,6 @@ watch( |
153 | 171 | ) |
154 | 172 | </script> |
155 | 173 | |
156 | - | |
157 | 174 | <style lang="scss" scoped> |
158 | 175 | @include deep() { |
159 | 176 | .n-input { |
... | ... | @@ -162,4 +179,4 @@ watch( |
162 | 179 | align-items: center; |
163 | 180 | } |
164 | 181 | } |
165 | -</style> | |
\ No newline at end of file | ||
182 | +</style> | ... | ... |
... | ... | @@ -21,6 +21,7 @@ import { OverrideLineGradientsConfig } from '@/packages/components/external/Char |
21 | 21 | import { OverrideProcessConfig } from '@/packages/components/external/Charts/Mores/OverrideProcess' |
22 | 22 | import { OverridePieCircleConfig } from '@/packages/components/external/Charts/Pies/OverridePieCircle' |
23 | 23 | import { OverrideMapBaseConfig } from '@/packages/components/external/Charts/Maps/OverrideMapBase' |
24 | +import { OverrideMapAmapConfig } from '@/packages/components/external/Charts/Maps/OverrideMapAmap' | |
24 | 25 | import { OverrideVideoConfig } from '@/packages/components/external/Informations/Mores/OverrideVideo' |
25 | 26 | import { OverrideWaterPoloConfig } from '@/packages/components/external/Charts/Mores/OverrideWaterPolo' |
26 | 27 | import { OverrideDialConfig } from '@/packages/components/external/Charts/Mores/OverrideDial' |
... | ... | @@ -104,6 +105,7 @@ export function useInjectLib(packagesList: EPackagesType) { |
104 | 105 | addWidgetToCategoryByCategoryName(packagesList, PackagesCategoryEnum.CHARTS, OverrideProcessConfig)//重写图表下的native ui |
105 | 106 | addWidgetToCategoryByCategoryName(packagesList, PackagesCategoryEnum.CHARTS, OverridePieCircleConfig)//重写图表下的饼图 |
106 | 107 | addWidgetToCategoryByCategoryName(packagesList, PackagesCategoryEnum.CHARTS, OverrideMapBaseConfig)//重写图表下的地图 |
108 | + addWidgetToCategoryByCategoryName(packagesList, PackagesCategoryEnum.CHARTS, OverrideMapAmapConfig)//重写图表下的高德地图 | |
107 | 109 | addWidgetToCategoryByCategoryName(packagesList, PackagesCategoryEnum.CHARTS, OverrideWaterPoloConfig)//重写图表下的水球图 |
108 | 110 | addWidgetToCategoryByCategoryName(packagesList, PackagesCategoryEnum.CHARTS, OverrideDialConfig)//重写图表下的表盘 |
109 | 111 | // | ... | ... |
... | ... | @@ -16,7 +16,8 @@ export const hideAsideComponentsObj = { |
16 | 16 | 'VPieCircle' //饼图-环形 |
17 | 17 | ], |
18 | 18 | Maps: [ |
19 | - 'VMapBase' //地图(可选省份) | |
19 | + 'VMapBase', //地图(可选省份) | |
20 | + 'VMapAmap', //高德地图 | |
20 | 21 | ], |
21 | 22 | Mores: [ |
22 | 23 | 'VProcess', //NaiveUI-进度 |
... | ... | @@ -45,6 +46,7 @@ export const hideAsideComponentsObj = { |
45 | 46 | 'VLineGradients', //双折线渐变面积图 |
46 | 47 | 'VPieCircle', //饼图-环形 |
47 | 48 | 'VMapBase', //地图(可选省份) |
49 | + 'VMapAmap',//高德地图 | |
48 | 50 | 'VProcess', //NaiveUI-进度 |
49 | 51 | 'VTextGradient', //渐变文字 |
50 | 52 | 'VTextBarrage', //弹幕文字 | ... | ... |
1 | +import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' | |
2 | +import { canvasCut, downloadTextFile, JSONStringify } from '@/utils' | |
3 | +const chartEditStore = useChartEditStore() | |
4 | + | |
5 | +// 导出 | |
6 | +export const exportHandle = () => { | |
7 | + // 取消选中 | |
8 | + chartEditStore.setTargetSelectChart(undefined) | |
9 | + | |
10 | + // 导出数据 | |
11 | + downloadTextFile( | |
12 | + JSONStringify(chartEditStore.getStorageInfo || []), | |
13 | + undefined, | |
14 | + 'json' | |
15 | + ) | |
16 | + | |
17 | + // 导出图片 | |
18 | + const range = document.querySelector('.go-edit-range') as HTMLElement | |
19 | + const watermark = document.getElementById('go-edit-watermark') | |
20 | + // 隐藏边距线 | |
21 | + if (!range || !watermark) { | |
22 | + window['$message'].error('导出失败!') | |
23 | + return | |
24 | + } | |
25 | + | |
26 | + // 记录缩放比例 | |
27 | + const scaleTemp = chartEditStore.getEditCanvas.scale | |
28 | + // 百分百展示页面 | |
29 | + chartEditStore.setScale(1, true) | |
30 | + // 展示水印 | |
31 | + // THINGS_KIT 隐藏水印 | |
32 | + watermark.style.display = 'none' | |
33 | + | |
34 | + //注释导出图片逻辑 | |
35 | + // setTimeout(() => { | |
36 | + // canvasCut(range, () => { | |
37 | + // // 隐藏水印 | |
38 | + // if (watermark) watermark.style.display = 'none' | |
39 | + // // 还原页面大小 | |
40 | + // chartEditStore.setScale(scaleTemp, true) | |
41 | + // }) | |
42 | + // }, 600) | |
43 | +} | ... | ... |
... | ... | @@ -78,7 +78,7 @@ import { EditEnum } from '@/enums/pageEnum' |
78 | 78 | import { StorageEnum } from '@/enums/storageEnum' |
79 | 79 | import { useRoute } from 'vue-router' |
80 | 80 | import { GoSystemSet } from '@/components/GoSystemSet/index' |
81 | -import { exportHandle } from './utils' | |
81 | +import { exportHandle } from './external'// THINGS_KIT 修改引入路径 | |
82 | 82 | import { useFile } from './hooks/useFile.hooks' |
83 | 83 | import { useSyncUpdate } from './hooks/useSyncUpdate.hook' |
84 | 84 | import { BtnListType, TypeEnum } from './index.d' | ... | ... |