| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { onMounted, onUnmounted } from 'vue'; |
| | | import { createMap, map, destroyMap } from '@/utils/map/index'; |
| | | import { onMounted, onUnmounted } from 'vue' |
| | | import { onMapMounted, createMap, satellite, map, destroyMap } from '@/utils/map/index' |
| | | const props = defineProps({ |
| | | showSatellite: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | }) |
| | | onMounted(() => { |
| | | // é«å¾·å°å¾åå§å |
| | | setTimeout(() => { |
| | | createMap('container'); |
| | | }, 1000); |
| | | }); |
| | | createMap('container') |
| | | onMapMounted(() => { |
| | | if (props.showSatellite) { |
| | | satellite.show() |
| | | } else { |
| | | satellite.hide() |
| | | } |
| | | }) |
| | | }, 1000) |
| | | }) |
| | | onUnmounted(() => { |
| | | destroyMap(); |
| | | }); |
| | | destroyMap() |
| | | }) |
| | | </script> |
| | | <style> |
| | | #container { |
| | |
| | | name: 'çæµé¢è¦', |
| | | }, |
| | | { |
| | | icon: 'solar:structure-line-duotone', |
| | | name: 'æ°æ®ç®¡ç', |
| | | children: [ |
| | | { |
| | | path: '/index/monitor/data-analysis-all', |
| | | icon: 'solar:presentation-graph-line-duotone', |
| | | name: 'æ°æ®åæ', |
| | | }, |
| | | { |
| | | path: '/index/monitor/data-history', |
| | | icon: 'solar:graph-new-line-duotone', |
| | | name: 'å岿°æ®', |
| | | }, |
| | | ], |
| | | }, |
| | | |
| | | // { |
| | | // icon: 'solar:presentation-graph-line-duotone', |
| | | // name: 'æ°æ®åæ', |
| | |
| | | // }, |
| | | // ], |
| | | // }, |
| | | { |
| | | path: '/index/monitor/data-history', |
| | | icon: 'solar:graph-new-line-duotone', |
| | | name: 'å岿°æ®', |
| | | }, |
| | | ], |
| | | }, |
| | | { |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | function generateTestShops() { |
| | | // æå®çåºéºåç§° |
| | | const specifiedShops = [ |
| | | 'ä»å°å§å¨æé½', |
| | | 'åå»èç', |
| | | 'å®¶å¨å¡å¦', |
| | | 'ç¼æ¥äº', |
| | | 'ä¹å¯æææ¸¸åº', |
| | | '馨è¿ç¾é£å°éï¼åå°¼ç¾é£å¹¿åºï¼', |
| | | 'æ£çº¦ç¿°', |
| | | 'å¼å åªé', |
| | | 'æ¨è®°é½é½åå°ç¤è', |
| | | '䏿µ·ç¨ä¼ é¤é¥®ç®¡çæéå
¬å¸ï¼äººçä¸ä¸²ï¼', |
| | | 'ç¼å®¶', |
| | | 'æ³çé¤é¥®ï¼ä¸æµ·ï¼æéå
¬å¸ï¼é£å
¶å®¶ï¼', |
| | | '丰èç¤ä¸²', |
| | | '䏿µ·æ³°ç
é¤é¥®ç®¡çæéå
¬å¸ï¼æ³°ç
鸡ï¼', |
| | | '徿±åºè¾°çé¤é¦(å°éå串ç§å±
é
å±)', |
| | | ] |
| | | |
| | | // éæºåºéºåç§°åç¼ååç¼ |
| | | const namePrefixes = [ |
| | | 'é£å³', |
| | | 'ç¹è²', |
| | | 'æ£å®', |
| | | 'ä¼ ç»', |
| | | 'ç»å
¸', |
| | | 'åæ', |
| | | 'æ¶å°', |
| | | 'ä¼é²', |
| | | 'ç²¾è´', |
| | | 'å°é', |
| | | ] |
| | | const nameSuffixes = [ |
| | | 'é¤å
', |
| | | 'é¥åº', |
| | | 'é
楼', |
| | | 'èé¦', |
| | | 'å°å', |
| | | 'é£å ', |
| | | 'ç¾é£', |
| | | '饮é£', |
| | | 'é¤é¥®', |
| | | 'é¥åº', |
| | | ] |
| | | const cuisines = [ |
| | | 'å·è', |
| | | '粤è', |
| | | 'é²è', |
| | | 'æ·®æ¬è', |
| | | 'é½è', |
| | | 'æ¹è', |
| | | 'å¾½è', |
| | | 'æµè', |
| | | 'ä¸åè', |
| | | '西åè', |
| | | '西é¤', |
| | | 'æ¥æ', |
| | | '驿', |
| | | 'ä¸åäºè', |
| | | ] |
| | | |
| | | // ç¯ä¿¡ç ç级 |
| | | const ringCodeLevels = [0, 1, 2] |
| | | |
| | | // çææµè¯æ°æ® |
| | | const shops = [] |
| | | |
| | | // å
æ·»å æå®çåºéº |
| | | specifiedShops.forEach((name, index) => { |
| | | shops.push({ |
| | | shop: { |
| | | name: name, |
| | | address: `䏿µ·å¸å¾æ±åº${index + 1}å·`, |
| | | latitude: 31.17 + Math.random() * 0.1, |
| | | longitude: 121.45 + Math.random() * 0.1, |
| | | ringCodeLevel: ringCodeLevels[Math.floor(Math.random() * ringCodeLevels.length)], |
| | | ringCodePublishTime: '2023-03-16 10:00:00', |
| | | }, |
| | | recentData: generateRecentData(), |
| | | }) |
| | | }) |
| | | |
| | | // çæå©ä½çéæºåºéº |
| | | for (let i = specifiedShops.length; i < 100; i++) { |
| | | const prefix = namePrefixes[Math.floor(Math.random() * namePrefixes.length)] |
| | | const cuisine = cuisines[Math.floor(Math.random() * cuisines.length)] |
| | | const suffix = nameSuffixes[Math.floor(Math.random() * nameSuffixes.length)] |
| | | const randomName = `${prefix}${cuisine}${suffix}${i}` |
| | | |
| | | shops.push({ |
| | | shop: { |
| | | name: randomName, |
| | | address: `䏿µ·å¸å¾æ±åº${i + 1}å·`, |
| | | latitude: 31.19 + Math.random() * 0.1, |
| | | longitude: 121.41 + Math.random() * 0.1, |
| | | ringCodeLevel: ringCodeLevels[Math.floor(Math.random() * ringCodeLevels.length)], |
| | | ringCodePublishTime: '2023-03-16 10:00:00', |
| | | }, |
| | | recentData: generateRecentData(), |
| | | }) |
| | | } |
| | | |
| | | return shops |
| | | } |
| | | function generateRecentData() { |
| | | // çæè¿1å°æ¶ççæµæ°æ®ï¼æ¯10åé䏿¡ |
| | | const data = [] |
| | | const now = new Date() |
| | | now.setFullYear(2023) |
| | | |
| | | for (let i = 5; i >= 0; i--) { |
| | | const time = new Date(now.getTime() - i * 10 * 60 * 1000) |
| | | data.push({ |
| | | sampleTime: time.toISOString().slice(0, 19).replace('T', ' '), |
| | | oilSmokeConcentration: (Math.random() * 5).toFixed(2), |
| | | purifierCurrent: (Math.random() * 10).toFixed(2), |
| | | fanCurrent: (Math.random() * 15).toFixed(2), |
| | | }) |
| | | } |
| | | |
| | | return data |
| | | } |
| | | |
| | | export { generateTestShops } |
| | |
| | | component: () => import('@/views/inspection/task/TaskManage.vue'), |
| | | }, |
| | | { |
| | | name: 'monitorObjEdit', |
| | | path: 'monitorObjEdit', |
| | | component: () => import('@/views/inspection/task/MonitorObjEdit.vue'), |
| | | }, |
| | | { |
| | | name: 'monitorPlanEdit', |
| | | path: 'monitorPlanEdit', |
| | | component: () => import('@/views/inspection/task/MonitorPlanEdit.vue'), |
| | | }, |
| | | { |
| | | name: 'scene-info', |
| | | path: 'scene-info', |
| | | component: () => import('@/views/inspection/scenenew/UserInfo.vue'), |
| | |
| | | var activeDistrict = undefined |
| | | export default { |
| | | // ç»å¶åºå¿è¾¹ç |
| | | drawDistrict(districtName, isNew) { |
| | | drawDistrictMask(districtName, isNew) { |
| | | if (!districtName) return |
| | | onMapMounted(() => { |
| | | if (!isNew && districtPolygonMap.has(districtName)) { |
| | |
| | | } |
| | | }) |
| | | }, |
| | | // ç»å¶åºå¿è¾¹ç |
| | | drawDistrict(districtName, isNew) { |
| | | if (!districtName) return |
| | | onMapMounted(() => { |
| | | if (!isNew && districtPolygonMap.has(districtName)) { |
| | | const districtPolygon = districtPolygonMap.get(districtName) |
| | | map.add(districtPolygon) |
| | | map.setFitView(districtPolygon) |
| | | activeDistrict = districtPolygon |
| | | } else { |
| | | var district = new AMap.DistrictSearch({ |
| | | extensions: 'all', //è¿åè¡æ¿åºè¾¹çåæ çå
·ä½ä¿¡æ¯ |
| | | level: 'district', //设置æ¥è¯¢è¡æ¿åºçº§å«ä¸ºåº |
| | | }) |
| | | district.search(districtName, function (status, result) { |
| | | var bounds = result.districtList[0].boundaries //è·åè¾¹çä¿¡æ¯ |
| | | if (bounds) { |
| | | for (var i = 0; i < bounds.length; i++) { |
| | | //çæè¡æ¿åºå polygon |
| | | const districtPolygon = new AMap.Polygon({ |
| | | map: map, //æ¾ç¤ºè¯¥è¦çç©çå°å¾å¯¹è±¡ |
| | | strokeWeight: 1, //è½®å»çº¿å®½åº¦ |
| | | path: bounds[i], //å¤è¾¹å½¢è½®å»çº¿çèç¹åæ æ°ç» |
| | | fillOpacity: 0.4, //å¤è¾¹å½¢å¡«å
éæåº¦ |
| | | fillColor: '#0077ff', |
| | | strokeColor: '#CC66CC', //线æ¡é¢è² |
| | | }) |
| | | |
| | | districtPolygonMap.set(districtName, districtPolygon) |
| | | activeDistrict = districtPolygon |
| | | map.setFitView(districtPolygon, true) |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | }) |
| | | }, |
| | | removeDistrict() { |
| | | onMapMounted(() => { |
| | | if (activeDistrict) { |
| | |
| | | map = new AMap.Map(elementId, { |
| | | // mapStyle: 'amap://styles/e1e78509de64ddcd2efb4cb34c6fae2a', |
| | | features: ['bg', 'road'], |
| | | pitch: 30, // å°å¾ä¿¯ä»°è§åº¦ï¼ææèå´ 0 度- 83 度 |
| | | pitch: 0, // å°å¾ä¿¯ä»°è§åº¦ï¼ææèå´ 0 度- 83 度 |
| | | viewMode: '3D', // å°å¾æ¨¡å¼ |
| | | resizeEnable: true, |
| | | center: [121.6039283, 31.25295567], |
| | | zooms: [2, 26], |
| | | zoom: 14, |
| | | zoom: 11, |
| | | }) |
| | | // map = new AMap.Map(elementId); |
| | | |
| | | // æ·»å 嫿å°å¾ |
| | | satellite = new AMap.TileLayer.Satellite() |
| | | const roadNet = new AMap.TileLayer.RoadNet() |
| | | // satellite.hide() |
| | | map.add([satellite, roadNet]) |
| | | // const roadNet = new AMap.TileLayer.RoadNet() |
| | | satellite.hide() |
| | | map.add([satellite]) |
| | | |
| | | // _initMouseTool(); |
| | | // _init3DLayer(); |
| | |
| | | }) |
| | | } |
| | | |
| | | export { createMap, destroyMap, onMapMounted, map, AMap, mouseTool, object3Dlayer, isDragging } |
| | | export { |
| | | createMap, |
| | | destroyMap, |
| | | onMapMounted, |
| | | map, |
| | | AMap, |
| | | satellite, |
| | | mouseTool, |
| | | object3Dlayer, |
| | | isDragging, |
| | | } |
| | |
| | | * é«å¾·å°å¾ç¹æ è®°ç»å¶ç¸å
³ |
| | | */ |
| | | |
| | | import { map, AMap } from './index'; |
| | | import { useToolboxStore } from '@/stores/toolbox'; |
| | | import { map, AMap } from './index' |
| | | import { useToolboxStore } from '@/stores/toolbox' |
| | | import util from './util' |
| | | import * as echarts from 'echarts' |
| | | |
| | | const toolboxStore = useToolboxStore(); |
| | | const toolboxStore = useToolboxStore() |
| | | |
| | | var _massMarks = undefined; |
| | | var _massMarks = undefined |
| | | |
| | | export default { |
| | | // ç¯ä¿¡ç ç级å对åºé¢è² |
| | | const ringCodeLevelColors = [ |
| | | '#52c41a', // ç»¿è² |
| | | '#faad14', // é»è² |
| | | '#f5222d', // çº¢è² |
| | | ] |
| | | |
| | | /** |
| | | * ç»å¶æµ·éç¹æ è®° |
| | | * @param fDatas 宿´çæµæ°æ® |
| | | * @param _factor å½åå±ç¤ºççæµå å对象 |
| | | * @param {Array} shops åºéºå¯¹è±¡æ°ç» |
| | | * @param {Object} shops[].shop åºéºåºæ¬ä¿¡æ¯ |
| | | * @param {string} shops[].shop.name åºéºåç§° |
| | | * @param {string} shops[].shop.address åºéºå°å |
| | | * @param {number} shops[].shop.latitude 纬度 |
| | | * @param {number} shops[].shop.longitude ç»åº¦ |
| | | * @param {string} shops[].shop.ringCodeLevel ææ°ç¯ä¿¡ç ç级 |
| | | * @param {string} shops[].shop.ringCodePublishTime ææ°ç¯ä¿¡ç å叿¶é´ |
| | | * @param {Array} shops[].recentData è¿1å°æ¶ççæµæ°æ® |
| | | * @param {string} shops[].recentData[].sampleTime æ°æ®éæ ·æ¶é´ |
| | | * @param {number} shops[].recentData[].oilSmokeConcentration æ²¹çæµåº¦ |
| | | * @param {number} shops[].recentData[].purifierCurrent ååå¨çµæµ |
| | | * @param {number} shops[].recentData[].fanCurrent 飿ºçµæµ |
| | | */ |
| | | drawMassMarks(fDatas, _factor, onClick) { |
| | | if (!toolboxStore.dataMarkerStatus) { |
| | | return; |
| | | function drawMassMarks(shops) { |
| | | // é
ç½®æ ·å¼ |
| | | const massMarksStyle = ringCodeLevelColors.map((color, index) => ({ |
| | | url: createCustomMarker(color), |
| | | size: new AMap.Size(20, 20), |
| | | anchor: new AMap.Pixel(10, 10), |
| | | })) |
| | | // å夿µ·éç¹æ°æ® |
| | | const massMarksData = shops.map((shop, index) => { |
| | | // æ ¹æ®ç¯ä¿¡ç ç级è·åé¢è² |
| | | const color = getColorByRingCodeLevel(shop.shop.ringCodeLevel) |
| | | |
| | | return { |
| | | id: index, |
| | | name: shop.shop.name, |
| | | lnglat: [shop.shop.longitude, shop.shop.latitude], |
| | | style: shop.shop.ringCodeLevel, // æ ·å¼ç´¢å¼ï¼å¯¹åº massMarksStyle |
| | | extData: shop, // åå¨å®æ´çåºéºä¿¡æ¯ |
| | | } |
| | | this.clearMassMarks(); |
| | | const lnglats = fDatas.lnglats_GD; |
| | | var data = []; |
| | | for (let i = 0; i < lnglats.length; i++) { |
| | | data.push({ |
| | | lnglat: lnglats[i], //ç¹æ è®°ä½ç½® |
| | | name: `${fDatas.times[i]}<br/>${_factor.factorName}: ${_factor.datas[i].factorData} μg/m³`, |
| | | id: i |
| | | }); |
| | | }) |
| | | |
| | | // æ¸
é¤ç°æçæµ·éç¹æ è®° |
| | | if (window.massMarks) { |
| | | window.massMarks.clear() |
| | | } |
| | | |
| | | // åå»ºæ ·å¼å¯¹è±¡ |
| | | var styleObject = { |
| | | url: 'https://a.amap.com/jsapi_demos/static/images/mass1.png', |
| | | // url: './asset/mipmap/ic_up_white.png', // 徿 å°å |
| | | // å建æ°çæµ·éç¹æ è®° |
| | | window.massMarks = new AMap.MassMarks(massMarksData, { |
| | | zIndex: 111, |
| | | cursor: 'pointer', |
| | | style: massMarksStyle, |
| | | }) |
| | | |
| | | size: new AMap.Size(11, 11), // 徿 å¤§å° |
| | | |
| | | anchor: new AMap.Pixel(5, 5) // 徿 æ¾ç¤ºä½ç½®åç§»éï¼åºåç¹ä¸ºå¾æ å·¦ä¸è§ |
| | | }; |
| | | |
| | | var massMarks = new AMap.MassMarks(data, { |
| | | zIndex: 5, // æµ·éç¹å¾å±å å çé¡ºåº |
| | | zooms: [15, 18], // 卿å®å°å¾ç¼©æ¾çº§å«èå´å
å±ç¤ºæµ·éç¹å¾å± |
| | | style: styleObject // è®¾ç½®æ ·å¼å¯¹è±¡ |
| | | }); |
| | | massMarks.on('click', (event) => { |
| | | const i = event.data.id; |
| | | // 3. èªå®ä¹ç¹å»äºä»¶ |
| | | onClick(i); |
| | | }); |
| | | // æ·»å ç¹å»äºä»¶ |
| | | window.massMarks.on('click', function (e) { |
| | | const shop = e.data.extData |
| | | showShopInfoWindow(shop) |
| | | }) |
| | | |
| | | var marker = new AMap.Marker({ |
| | | content: ' ', |
| | | map: map, |
| | | offset: new AMap.Pixel(13, 12), |
| | | }) |
| | | |
| | | offset: new AMap.Pixel(13, 12) |
| | | }); |
| | | var timeout; |
| | | massMarks.on('mouseover', (e) => { |
| | | var timeout |
| | | window.massMarks.on('mouseover', (e) => { |
| | | if (timeout) { |
| | | clearTimeout(timeout); |
| | | clearTimeout(timeout) |
| | | } |
| | | marker.setPosition(e.data.lnglat); |
| | | marker.setLabel({ content: e.data.name }); |
| | | map.add(marker); |
| | | marker.setPosition(e.data.lnglat) |
| | | marker.setLabel({ content: e.data.name }) |
| | | map.add(marker) |
| | | timeout = setTimeout(() => { |
| | | map.remove(marker); |
| | | }, 2000); |
| | | }); |
| | | _massMarks = massMarks; |
| | | map.add(massMarks); |
| | | }, |
| | | clearMassMarks() { |
| | | if (_massMarks) { |
| | | map.remove(_massMarks); |
| | | _massMarks = undefined; |
| | | map.remove(marker) |
| | | }, 2000) |
| | | }) |
| | | |
| | | // æ·»å å°å°å¾ |
| | | window.massMarks.setMap(map) |
| | | util.setBound(massMarksData.map((item) => item.lnglat)) |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®ç¯ä¿¡ç ç级è·åé¢è² |
| | | * @param {string} level ç¯ä¿¡ç ç级 |
| | | * @returns {string} é¢è²å¼ |
| | | */ |
| | | function getColorByRingCodeLevel(level) { |
| | | switch (level + '') { |
| | | case '0': |
| | | return '#52c41a' // ç»¿è² |
| | | case '1': |
| | | return '#faad14' // é»è² |
| | | case '2': |
| | | return '#f5222d' // çº¢è² |
| | | default: |
| | | return '#8c8c8c' // ç°è² |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®ç¯ä¿¡ç ç级è·å䏿 |
| | | * @param {string} level ç¯ä¿¡ç ç级 |
| | | * @returns {string} ä¸æè¡¨ç¤º |
| | | */ |
| | | function getRingCodeLevelText(level) { |
| | | switch (level + '') { |
| | | case '0': |
| | | return '绿è²' |
| | | case '1': |
| | | return 'é»è²' |
| | | case '2': |
| | | return '红è²' |
| | | default: |
| | | return 'æªç¥' |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å建èªå®ä¹æ è®° |
| | | * @param {string} color æ è®°é¢è² |
| | | * @returns {string} æ è®°çSVG URL |
| | | */ |
| | | function createCustomMarker(color) { |
| | | const svg = ` |
| | | <svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> |
| | | <circle cx="10" cy="10" r="8" fill="${color}" stroke="white" stroke-width="2"/> |
| | | <circle cx="10" cy="10" r="3" fill="white"/> |
| | | </svg> |
| | | ` |
| | | return 'data:image/svg+xml;base64,' + btoa(unescape(encodeURIComponent(svg))) |
| | | } |
| | | |
| | | /** |
| | | * æ¾ç¤ºåºéºä¿¡æ¯çªå£ |
| | | * @param {Object} shop åºéºå¯¹è±¡ |
| | | */ |
| | | function showShopInfoWindow(shop) { |
| | | // åå¤ä¿¡æ¯çªå£å
容 |
| | | // const content = ` |
| | | // <div style="padding: 10px; max-width: 300px;"> |
| | | // <h3 style="margin: 0 0 10px 0; color: #333;">${shop.shop.name}</h3> |
| | | // <div style="font-size: 14px; line-height: 1.5;"> |
| | | // <p><strong>å°åï¼</strong>${shop.shop.address}</p> |
| | | // <p><strong>ç¯ä¿¡ç ç级ï¼</strong><span style="color: ${getColorByRingCodeLevel(shop.shop.ringCodeLevel)}">${shop.shop.ringCodeLevel}</span></p> |
| | | // <p><strong>ç¯ä¿¡ç å叿¶é´ï¼</strong>${shop.shop.ringCodePublishTime}</p> |
| | | // <h4 style="margin: 10px 0 5px 0; color: #666;">è¿1å°æ¶çæµæ°æ®</h4> |
| | | // <div style="max-height: 150px; overflow-y: auto;"> |
| | | // ${shop.recentData |
| | | // .map( |
| | | // (item) => ` |
| | | // <div style="padding: 5px; border-bottom: 1px solid #f0f0f0;"> |
| | | // <p><strong>éæ ·æ¶é´ï¼</strong>${item.sampleTime}</p> |
| | | // <p><strong>æ²¹çæµåº¦ï¼</strong>${item.oilSmokeConcentration} mg/m³</p> |
| | | // <p><strong>ååå¨çµæµï¼</strong>${item.purifierCurrent} A</p> |
| | | // <p><strong>飿ºçµæµï¼</strong>${item.fanCurrent} A</p> |
| | | // </div> |
| | | // `, |
| | | // ) |
| | | // .join('')} |
| | | // </div> |
| | | // </div> |
| | | // </div> |
| | | // ` |
| | | const content = ` |
| | | <div style="padding: 10px; width: 400px;"> |
| | | <h3 style="margin: 0 0 10px 0; color: #333;">${shop.shop.name}</h3> |
| | | <div style="font-size: 14px; line-height: 1.5;"> |
| | | <p><strong>å°åï¼</strong>${shop.shop.address}</p> |
| | | <p><strong>ç¯ä¿¡ç ç级ï¼</strong><span style="color: ${getColorByRingCodeLevel(shop.shop.ringCodeLevel)}">${getRingCodeLevelText(shop.shop.ringCodeLevel)}</span></p> |
| | | <p><strong>ç¯ä¿¡ç å叿¶é´ï¼</strong>${shop.shop.ringCodePublishTime}</p> |
| | | <h4 style="margin: 10px 0 5px 0; color: #666;">è¿1å°æ¶çæµæ°æ®</h4> |
| | | <div id="infowindowChartContainer" style="width: 100%; height: 250px;"></div> |
| | | </div> |
| | | </div> |
| | | ` |
| | | |
| | | // æ¸
é¤ç°æçä¿¡æ¯çªå£ |
| | | if (window.infoWindow) { |
| | | window.infoWindow.close() |
| | | } |
| | | |
| | | // å建æ°çä¿¡æ¯çªå£ |
| | | window.infoWindow = new AMap.InfoWindow({ |
| | | content: content, |
| | | size: new AMap.Size(400, 400), |
| | | offset: new AMap.Pixel(-24, -80), |
| | | }) |
| | | |
| | | // æå¼ä¿¡æ¯çªå£ |
| | | window.infoWindow.open(map, [shop.shop.longitude, shop.shop.latitude]) |
| | | |
| | | // çå¾
ä¿¡æ¯çªå£å è½½å®æååå§åå¾è¡¨ |
| | | setTimeout(() => { |
| | | const chartdom = document.getElementById('infowindowChartContainer') |
| | | if (chartdom) { |
| | | initChart(chartdom, shop.recentData) |
| | | } |
| | | }, 100) |
| | | } |
| | | |
| | | /** |
| | | * åå§åçæµæ°æ®å¾è¡¨ |
| | | * @param {Array} data çæµæ°æ® |
| | | */ |
| | | function initChart(chartdom, data) { |
| | | // åå¤å¾è¡¨æ°æ® |
| | | const times = data.map((item) => item.sampleTime) |
| | | const oilSmokeData = data.map((item) => item.oilSmokeConcentration) |
| | | const purifierData = data.map((item) => item.purifierCurrent) |
| | | const fanData = data.map((item) => item.fanCurrent) |
| | | |
| | | // åå§åå¾è¡¨ |
| | | const chart = echarts.init(chartdom) |
| | | |
| | | // å¾è¡¨é
ç½® |
| | | const option = { |
| | | tooltip: { |
| | | trigger: 'axis', |
| | | axisPointer: { |
| | | type: 'cross', |
| | | label: { |
| | | backgroundColor: '#6a7985', |
| | | }, |
| | | }, |
| | | }, |
| | | legend: { |
| | | data: ['æ²¹çæµåº¦', 'ååå¨çµæµ', '飿ºçµæµ'], |
| | | top: 0, |
| | | }, |
| | | grid: { |
| | | left: '3%', |
| | | right: '4%', |
| | | bottom: '3%', |
| | | containLabel: true, |
| | | }, |
| | | xAxis: [ |
| | | { |
| | | type: 'category', |
| | | boundaryGap: false, |
| | | data: times.map((time) => time.split(' ')[1]), |
| | | axisLabel: { |
| | | rotate: 0, |
| | | fontSize: 10, |
| | | }, |
| | | }, |
| | | ], |
| | | yAxis: [ |
| | | { |
| | | type: 'value', |
| | | name: 'æ²¹çæµåº¦ (mg/m³)', |
| | | position: 'left', |
| | | left: '30%', |
| | | }, |
| | | { |
| | | type: 'value', |
| | | name: 'çµæµ (A)', |
| | | position: 'right', |
| | | }, |
| | | ], |
| | | series: [ |
| | | { |
| | | name: 'æ²¹çæµåº¦', |
| | | type: 'line', |
| | | data: oilSmokeData, |
| | | yAxisIndex: 0, |
| | | smooth: true, |
| | | }, |
| | | { |
| | | name: 'ååå¨çµæµ', |
| | | type: 'line', |
| | | data: purifierData, |
| | | yAxisIndex: 1, |
| | | smooth: true, |
| | | }, |
| | | { |
| | | name: '飿ºçµæµ', |
| | | type: 'line', |
| | | data: fanData, |
| | | yAxisIndex: 1, |
| | | smooth: true, |
| | | }, |
| | | ], |
| | | } |
| | | |
| | | // åºç¨é
ç½® |
| | | chart.setOption(option) |
| | | |
| | | // ååºå¼å¤ç |
| | | window.addEventListener('resize', function () { |
| | | chart.resize() |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * æ¸
餿µ·éç¹æ è®° |
| | | */ |
| | | function clearMassMarks() { |
| | | if (window.massMarks) { |
| | | window.massMarks.clear() |
| | | window.massMarks.setMap(null) |
| | | window.massMarks = null |
| | | } |
| | | |
| | | if (window.infoWindow) { |
| | | window.infoWindow.close() |
| | | window.infoWindow = null |
| | | } |
| | | } |
| | | |
| | | export default { |
| | | drawMassMarks, |
| | | clearMassMarks, |
| | | // /** |
| | | // * ç»å¶æµ·éç¹æ è®° |
| | | // * @param fDatas 宿´çæµæ°æ® |
| | | // * @param _factor å½åå±ç¤ºççæµå å对象 |
| | | // */ |
| | | // drawMassMarks(fDatas, _factor, onClick) { |
| | | // if (!toolboxStore.dataMarkerStatus) { |
| | | // return; |
| | | // } |
| | | // this.clearMassMarks(); |
| | | // const lnglats = fDatas.lnglats_GD; |
| | | // var data = []; |
| | | // for (let i = 0; i < lnglats.length; i++) { |
| | | // data.push({ |
| | | // lnglat: lnglats[i], //ç¹æ è®°ä½ç½® |
| | | // name: `${fDatas.times[i]}<br/>${_factor.factorName}: ${_factor.datas[i].factorData} μg/m³`, |
| | | // id: i |
| | | // }); |
| | | // } |
| | | |
| | | // // åå»ºæ ·å¼å¯¹è±¡ |
| | | // var styleObject = { |
| | | // url: 'https://a.amap.com/jsapi_demos/static/images/mass1.png', |
| | | // // url: './asset/mipmap/ic_up_white.png', // 徿 å°å |
| | | |
| | | // size: new AMap.Size(11, 11), // 徿 å¤§å° |
| | | |
| | | // anchor: new AMap.Pixel(5, 5) // 徿 æ¾ç¤ºä½ç½®åç§»éï¼åºåç¹ä¸ºå¾æ å·¦ä¸è§ |
| | | // }; |
| | | |
| | | // var massMarks = new AMap.MassMarks(data, { |
| | | // zIndex: 5, // æµ·éç¹å¾å±å å çé¡ºåº |
| | | // zooms: [15, 18], // 卿å®å°å¾ç¼©æ¾çº§å«èå´å
å±ç¤ºæµ·éç¹å¾å± |
| | | // style: styleObject // è®¾ç½®æ ·å¼å¯¹è±¡ |
| | | // }); |
| | | // massMarks.on('click', (event) => { |
| | | // const i = event.data.id; |
| | | // // 3. èªå®ä¹ç¹å»äºä»¶ |
| | | // onClick(i); |
| | | // }); |
| | | |
| | | // var marker = new AMap.Marker({ |
| | | // content: ' ', |
| | | // map: map, |
| | | |
| | | // offset: new AMap.Pixel(13, 12) |
| | | // }); |
| | | // var timeout; |
| | | // massMarks.on('mouseover', (e) => { |
| | | // if (timeout) { |
| | | // clearTimeout(timeout); |
| | | // } |
| | | // marker.setPosition(e.data.lnglat); |
| | | // marker.setLabel({ content: e.data.name }); |
| | | // map.add(marker); |
| | | // timeout = setTimeout(() => { |
| | | // map.remove(marker); |
| | | // }, 2000); |
| | | // }); |
| | | // _massMarks = massMarks; |
| | | // map.add(massMarks); |
| | | // }, |
| | | // clearMassMarks() { |
| | | // if (_massMarks) { |
| | | // map.remove(_massMarks) |
| | | // _massMarks = undefined |
| | | // } |
| | | // }, |
| | | |
| | | /** |
| | | * å建æ è®°ç¹ |
| | |
| | | // å¼å¯æ 注é¿è®©ï¼é»è®¤ä¸ºå¼å¯ï¼v1.4.15 æ°å¢å±æ§ |
| | | collision: collision, |
| | | // å¼å¯æ 注淡å
¥å¨ç»ï¼é»è®¤ä¸ºå¼å¯ï¼v1.4.15 æ°å¢å±æ§ |
| | | animation: true |
| | | }); |
| | | animation: true, |
| | | }) |
| | | |
| | | map.add(layer); |
| | | map.add(layer) |
| | | |
| | | // var markers = []; |
| | | for (var i = 0; i < dataList.length; i++) { |
| | | const data = dataList[i]; |
| | | const data = dataList[i] |
| | | var curData = { |
| | | name: data.name, |
| | | position: [data.longitude, data.latitude], |
| | |
| | | size: [30, 30], |
| | | anchor: 'bottom-center', |
| | | angel: 0, |
| | | retina: true |
| | | retina: true, |
| | | }, |
| | | text: { |
| | | content: showTxt ? data.name : '', |
| | |
| | | fillColor: '#fff', |
| | | strokeColor: '#333', |
| | | strokeWidth: 0, |
| | | backgroundColor: '#122b54a9' |
| | | backgroundColor: '#122b54a9', |
| | | }, |
| | | }, |
| | | } |
| | | } |
| | | }; |
| | | curData.extData = { |
| | | index: i |
| | | }; |
| | | index: i, |
| | | } |
| | | |
| | | var labelMarker = new AMap.LabelMarker(curData); |
| | | var labelMarker = new AMap.LabelMarker(curData) |
| | | |
| | | // markers.push(labelMarker); |
| | | |
| | | layer.add(labelMarker); |
| | | layer.add(labelMarker) |
| | | } |
| | | |
| | | return layer; |
| | | return layer |
| | | }, |
| | | |
| | | createMarker({ position, img, title, content, label = '', extData }) { |
| | |
| | | size: new AMap.Size(30, 30), //徿 尺寸 |
| | | image: img, //Icon çå¾å |
| | | // imageOffset: new AMap.Pixel(-9, -3), //å¾åç¸å¯¹å±ç¤ºåºåçåç§»éï¼éäºéªç¢§å¾ç |
| | | imageSize: new AMap.Size(30, 30) //æ ¹æ®æè®¾ç½®ç大尿伏æå缩å¾ç |
| | | }); |
| | | imageSize: new AMap.Size(30, 30), //æ ¹æ®æè®¾ç½®ç大尿伏æå缩å¾ç |
| | | }) |
| | | const marker = new AMap.Marker({ |
| | | position: position, |
| | | // offset: new AMap.Pixel(-13, -30), |
| | |
| | | title: title, |
| | | label: { |
| | | content: label, |
| | | direction: 'bottom' |
| | | direction: 'bottom', |
| | | }, |
| | | extData |
| | | }); |
| | | extData, |
| | | }) |
| | | // map.add(marker); |
| | | return marker; |
| | | return marker |
| | | }, |
| | | } |
| | | }; |
| | |
| | | import { map, AMap, isDragging } from '@/utils/map/index'; |
| | | import marks from '@/utils/map/marks'; |
| | | import { map, AMap, isDragging } from '@/utils/map/index' |
| | | import marks from '@/utils/map/marks' |
| | | |
| | | /** |
| | | * åæ éåçæè¥¿åè§åæä¸åè§ |
| | |
| | | * list æ¯æ¥å£è·åçç¹ çæ°ç» |
| | | */ |
| | | const getBound = (list) => { |
| | | const offset = 0.005; |
| | | let south = null; |
| | | let west = null; |
| | | let north = null; |
| | | let east = null; |
| | | const offset = 0.05 |
| | | let south = null |
| | | let west = null |
| | | let north = null |
| | | let east = null |
| | | for (let item of list) { |
| | | // æé¤æ æç»çº¬åº¦ |
| | | if (item[0] == 0 && item[1] == 0) { |
| | | continue; |
| | | continue |
| | | } |
| | | if ((west && item[0] < west) || !west) { |
| | | west = item[0] - offset; |
| | | west = item[0] - offset |
| | | } |
| | | if ((south && item[1] < south) || !south) { |
| | | south = item[1] - offset; |
| | | south = item[1] - offset |
| | | } |
| | | if ((east && item[0] > east) || !east) { |
| | | east = item[0] + offset; |
| | | east = item[0] + offset |
| | | } |
| | | if ((north && item[1] > north) || !north) { |
| | | north = item[1] + offset; |
| | | north = item[1] + offset |
| | | } |
| | | } |
| | | if (!south || !west || !north || !east) { |
| | | return { sw: null, ne: null }; |
| | | return { sw: null, ne: null } |
| | | } else { |
| | | return { sw: [west, south], ne: [east, north] }; |
| | | return { sw: [west, south], ne: [east, north] } |
| | | } |
| | | }; |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®ä¸å¿ç¹åºåçåå¾ï¼å¾å°åéçå°å¾ç¼©æ¾ç³»æ° |
| | |
| | | */ |
| | | const distanceToZoom = (d) => { |
| | | let baseDis = 250, |
| | | z = 0; |
| | | z = 0 |
| | | while (baseDis < d) { |
| | | baseDis *= 2; |
| | | z++; |
| | | baseDis *= 2 |
| | | z++ |
| | | } |
| | | |
| | | // å¤ä½çå°å¾ç¼©æ¾ç³»æ° |
| | | const x = (baseDis - d) / (baseDis / 2); |
| | | z -= x; |
| | | z = z < 0 ? 0 : z; |
| | | const x = (baseDis - d) / (baseDis / 2) |
| | | z -= x |
| | | z = z < 0 ? 0 : z |
| | | |
| | | z = 18 - z; |
| | | z = z < 3 ? 3 : z; |
| | | return z; |
| | | }; |
| | | z = 18 - z |
| | | z = z < 3 ? 3 : z |
| | | return z |
| | | } |
| | | |
| | | export default { |
| | | setCenter(lnglat, ignore = false) { |
| | | if (!ignore && isDragging) { |
| | | return; |
| | | return |
| | | } |
| | | var now = new Date(); |
| | | if ( |
| | | this.lasttime == undefined || |
| | | now.getTime() - this.lasttime.getTime() >= 200 |
| | | ) { |
| | | map.setCenter(lnglat); |
| | | this.lasttime = now; |
| | | var now = new Date() |
| | | if (this.lasttime == undefined || now.getTime() - this.lasttime.getTime() >= 200) { |
| | | map.setCenter(lnglat) |
| | | this.lasttime = now |
| | | } |
| | | }, |
| | | addViews(view) { |
| | | map.add(view); |
| | | map.add(view) |
| | | }, |
| | | removeViews(view) { |
| | | map.remove(view); |
| | | map.remove(view) |
| | | }, |
| | | clearMap() { |
| | | marks.clearMassMarks(); |
| | | map.clearMap(); |
| | | marks.clearMassMarks() |
| | | map.clearMap() |
| | | }, |
| | | setFitView(views) { |
| | | if (views) { |
| | | map.setFitView(views); |
| | | map.setFitView(views) |
| | | } else { |
| | | map.setFitView(); |
| | | map.setFitView() |
| | | } |
| | | }, |
| | | setFitSector({ p, r }) { |
| | | this.setCenter(p); |
| | | const z = distanceToZoom(r); |
| | | map.setZoom(z); |
| | | this.setCenter(p) |
| | | const z = distanceToZoom(r) |
| | | map.setZoom(z) |
| | | }, |
| | | setBound(lnglats_GD) { |
| | | const { sw, ne } = getBound(lnglats_GD); |
| | | const { sw, ne } = getBound(lnglats_GD) |
| | | if (!sw || !ne) { |
| | | return; |
| | | return |
| | | } |
| | | var mybounds = new AMap.Bounds(sw, ne); // sw, ne > [xxx,xxx], [xxx,xxx] |
| | | map.setBounds(mybounds); |
| | | var mybounds = new AMap.Bounds(sw, ne) // sw, ne > [xxx,xxx], [xxx,xxx] |
| | | map.setBounds(mybounds) |
| | | }, |
| | | } |
| | | }; |
| | |
| | | class="dialog-wrapper" |
| | | v-loading="loading" |
| | | > |
| | | <el-scrollbar |
| | | ref="scrollbarRef" |
| | | height="50vh" |
| | | v-loading="loading" |
| | | :always="true" |
| | | > |
| | | <el-scrollbar ref="scrollbarRef" height="50vh" v-loading="loading" :always="true"> |
| | | <el-checkbox-group v-model="checkList"> |
| | | <el-space |
| | | direction="vertical" |
| | | alignment="flex-start" |
| | | fill |
| | | style="width: 90%" |
| | | > |
| | | <el-space direction="vertical" alignment="flex-start" fill style="width: 90%"> |
| | | <el-checkbox |
| | | v-for="(item, index) in sceneInfoList" |
| | | :key="item.scense.guid" |
| | |
| | | :class="(item.invalid ? 'checkbox-invalid' : '') + ' checkbox'" |
| | | > |
| | | <div> |
| | | <el-text size="large" truncated style="width: 600px">{{ |
| | | item.scense.name |
| | | }}</el-text> |
| | | <el-text size="large" truncated style="width: 600px">{{ item.scense.name }}</el-text> |
| | | </div> |
| | | <div class="m-t-4"> |
| | | <el-text size="small">{{ |
| | | 'å°åï¼' + item.scense.location |
| | | }}</el-text> |
| | | <el-text size="small">{{ 'å°åï¼' + item.scense.location }}</el-text> |
| | | </div> |
| | | <el-row justify="space-between"> |
| | | <el-space class="m-t-4"> |
| | | <el-tag> |
| | | {{ |
| | | item.scense.cityname + |
| | | item.scense.districtname + |
| | | item.scense.townname |
| | | }} |
| | | {{ item.scense.cityname + item.scense.districtname + item.scense.townname }} |
| | | </el-tag> |
| | | <el-tag>{{ item.scense.type }}</el-tag> |
| | | </el-space> |
| | |
| | | :loading="item._loading" |
| | | :disabled="item._isFirstInspect" |
| | | inline-prompt |
| | | style=" |
| | | --el-switch-on-color: #13ce66; |
| | | --el-switch-off-color: #c75000; |
| | | " |
| | | style="--el-switch-on-color: #13ce66; --el-switch-off-color: #c75000" |
| | | active-text="详ç" |
| | | inactive-text="ç®ç" |
| | | /> |
| | |
| | | type="default" |
| | | size="small" |
| | | class="m-t-4" |
| | | icon="IconPrinter" |
| | | :disabled="!item._valid" |
| | | @click="handlePreview(item)" |
| | | > |
| | | <el-icon> |
| | | <Icon icon="solar:printer-minimalistic-line-duotone" /> |
| | | </el-icon> |
| | | </el-button> |
| | | </el-space> |
| | | </el-row> |
| | |
| | | </el-scrollbar> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="danger" @click="cancel" icon="CloseBold" |
| | | >åæ¶</el-button |
| | | > |
| | | <el-button type="danger" @click="cancel" icon="CloseBold">åæ¶</el-button> |
| | | <el-button |
| | | type="primary" |
| | | :loading="docLoading" |
| | |
| | | :loading="docLoading" |
| | | :disabled="checkList.length == 0" |
| | | @click="handlePreview()" |
| | | icon="IconPrinter" |
| | | > |
| | | <el-icon class="el-icon--left"> |
| | | <Icon icon="solar:printer-minimalistic-line-duotone" /> |
| | | </el-icon> |
| | | æå°æé |
| | | </el-button> |
| | | </div> |
| | |
| | | <el-dialog v-model="previewVisible" :show-close="false" fullscreen> |
| | | <template #header="{ close, titleId, titleClass }"> |
| | | <el-row justify="end" style="background-color: white"> |
| | | <el-button type="danger" @click="close" icon="CircleCloseFilled"> |
| | | å
³é |
| | | </el-button> |
| | | <el-button |
| | | type="primary" |
| | | @click="handelPrint(refWord)" |
| | | icon="IconPrinter" |
| | | > |
| | | <el-button type="danger" @click="close" icon="CircleCloseFilled"> å
³é </el-button> |
| | | <el-button type="primary" @click="handelPrint(refWord)" icon="IconPrinter"> |
| | | æå° |
| | | </el-button> |
| | | </el-row> |
| | | </template> |
| | | <div ref="refWord"> |
| | | <div |
| | | :id="`word-preview-${i}`" |
| | | v-for="(item, i) in previewList" |
| | | :key="item" |
| | | ></div> |
| | | <div :id="`word-preview-${i}`" v-for="(item, i) in previewList" :key="item"></div> |
| | | </div> |
| | | <!-- <iframe ref="pdfPreview" width="100%" height="100vh" style="height: calc(100vh - 60px);"></iframe> --> |
| | | </el-dialog> |
| | |
| | | /** |
| | | * åºæ¯å·¡æ¥åæ®èªå¨ä¸è½½ |
| | | */ |
| | | import { ref, watch } from 'vue'; |
| | | import { useRouter } from 'vue-router'; |
| | | import { Icon } from '@iconify/vue' |
| | | import { ref, watch } from 'vue' |
| | | import { useRouter } from 'vue-router' |
| | | import { |
| | | exportDocx, |
| | | prepareDocxBlob, |
| | | preparePdf, |
| | | previewDocx, |
| | | downloadDocx, |
| | | print |
| | | } from '@/utils/doc'; |
| | | import sceneApi from '@/api/fysp/sceneApi'; |
| | | import subtaskApi from '@/api/fysp/subtaskApi'; |
| | | print, |
| | | } from '@/utils/doc' |
| | | import sceneApi from '@/api/fysp/sceneApi' |
| | | import subtaskApi from '@/api/fysp/subtaskApi' |
| | | |
| | | // 2025.12.22ï¼æå·¡æ¥åæ®æ¨¡æ¿çåºæ¯ç±»åï¼[1:å·¥å°, 5:é¤é¥®] |
| | | const validSceneType = [1, 5]; |
| | | const validSceneType = [1, 5] |
| | | |
| | | const props = defineProps({ |
| | | // å¯¹è¯æ¡å¼å
³ |
| | | modelValue: Boolean, |
| | | // åºæ¯åºç¡ä¿¡æ¯æ°ç» |
| | | value: Array, |
| | | previewElement: String |
| | | }); |
| | | previewElement: String, |
| | | }) |
| | | |
| | | const emits = defineEmits(['update:modelValue']); |
| | | const emits = defineEmits(['update:modelValue']) |
| | | |
| | | const router = useRouter(); |
| | | const router = useRouter() |
| | | |
| | | const refWord = ref(null); |
| | | const pdfPreview = ref(null); |
| | | const refWord = ref(null) |
| | | const pdfPreview = ref(null) |
| | | |
| | | const loading = ref(false); |
| | | const scrollbarRef = ref(); |
| | | const sceneInfoList = ref([]); |
| | | const checkList = ref([]); |
| | | const docLoading = ref(false); |
| | | const loading = ref(false) |
| | | const scrollbarRef = ref() |
| | | const sceneInfoList = ref([]) |
| | | const checkList = ref([]) |
| | | const docLoading = ref(false) |
| | | |
| | | // é¢è§å¯¹è¯æ¡å¼å
³ |
| | | const previewVisible = ref(false); |
| | | const previewVisible = ref(false) |
| | | // é¢è§çææ¡£ |
| | | const previewList = ref([]); |
| | | const previewList = ref([]) |
| | | |
| | | watch( |
| | | () => [props.modelValue, props.value], |
| | | (nV, oV) => { |
| | | if (nV[0] && nV[1] && nV[1] != oV[1]) { |
| | | fetchSceneInfo(nV[1]); |
| | | fetchSceneInfo(nV[1]) |
| | | } |
| | | } |
| | | ); |
| | | }, |
| | | ) |
| | | |
| | | function fetchSceneInfo(sceneIdList) { |
| | | loading.value = true; |
| | | sceneInfoList.value = []; |
| | | checkList.value = []; |
| | | loading.value = true |
| | | sceneInfoList.value = [] |
| | | checkList.value = [] |
| | | sceneIdList.forEach((sid) => { |
| | | sceneApi |
| | | .getSceneDetail(sid) |
| | | .then((res) => { |
| | | sceneInfoList.value.push(res.data); |
| | | sceneInfoList.value.push(res.data) |
| | | if (validSceneType.indexOf(res.data?.scense?.typeid) != -1) { |
| | | checkList.value.push(sceneInfoList.value.length - 1); |
| | | checkList.value.push(sceneInfoList.value.length - 1) |
| | | |
| | | // todo _valid çé»è¾æé误 |
| | | const lastScene = sceneInfoList.value[sceneInfoList.value.length - 1]; |
| | | lastScene._valid = true; |
| | | lastScene._loading = true; |
| | | const lastScene = sceneInfoList.value[sceneInfoList.value.length - 1] |
| | | lastScene._valid = true |
| | | lastScene._loading = true |
| | | subtaskApi |
| | | .findByDate(sid) |
| | | .then((res) => { |
| | | if (res.length == 0) { |
| | | lastScene._isFirstInspect = true; |
| | | lastScene._isDetail = true; |
| | | lastScene._isFirstInspect = true |
| | | lastScene._isDetail = true |
| | | } |
| | | }) |
| | | .finally(() => { |
| | | lastScene._loading = false; |
| | | }); |
| | | lastScene._loading = false |
| | | }) |
| | | } |
| | | }) |
| | | .finally(() => { |
| | | loading.value = false; |
| | | scrollbarRef.value.setScrollTop(0); |
| | | }); |
| | | }); |
| | | loading.value = false |
| | | scrollbarRef.value.setScrollTop(0) |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | function handleDialogChange(value) { |
| | | emits('update:modelValue', value); |
| | | emits('update:modelValue', value) |
| | | } |
| | | |
| | | function setParam(value, length) { |
| | | const _value = value ? value : ''; |
| | | const offset = length - _value.length; |
| | | const _value = value ? value : '' |
| | | const offset = length - _value.length |
| | | if (offset > 0) { |
| | | let str = _value; |
| | | let str = _value |
| | | for (let i = 0; i < offset; i++) { |
| | | str += ' '; |
| | | str += ' ' |
| | | } |
| | | return str; |
| | | return str |
| | | } else { |
| | | return _value; |
| | | return _value |
| | | } |
| | | } |
| | | |
| | |
| | | const selected = item |
| | | ? [item] |
| | | : sceneInfoList.value.filter((v, i) => { |
| | | return checkList.value.indexOf(i) != -1; |
| | | }); |
| | | return checkList.value.indexOf(i) != -1 |
| | | }) |
| | | const param = selected.map((v) => { |
| | | switch (v.scense.typeid) { |
| | | // å·¥å° |
| | |
| | | district: v.scense?.districtname ?? '', |
| | | name: setParam(v.scense?.name ?? '', 0), |
| | | employerUnit: setParam(v.subScene?.csEmployerUnit ?? '', 0), |
| | | constructionUnit: setParam( |
| | | v.subScene ? v.subScene.csConstructionUnit : '', |
| | | 0 |
| | | ), |
| | | constructionUnit: setParam(v.subScene ? v.subScene.csConstructionUnit : '', 0), |
| | | timeRange: setParam( |
| | | v.subScene && v.subScene.csStartTime |
| | | ? `${v.subScene.csStartTime}è³${v.subScene.csEndTime}` |
| | | : '', |
| | | 0 |
| | | 0, |
| | | ), |
| | | stage: setParam(v.subScene ? v.subScene.siExtension1 : '', 0), |
| | | contacts: setParam(v.scense?.contacts ?? '', 0), |
| | | contactsTel: setParam(v.scense?.contactst ?? '', 0), |
| | | location: setParam(v.scense?.location ?? '', 0) |
| | | location: setParam(v.scense?.location ?? '', 0), |
| | | }, |
| | | } |
| | | }; |
| | | // é¤é¥® |
| | | case 5: |
| | | return { |
| | |
| | | location: setParam(v.scense.location, 63), |
| | | name: setParam(v.scense.name, 64), |
| | | contacts: setParam(v.scense.contacts, 67), |
| | | contactsTel: setParam(v.scense.contactst, 62) |
| | | contactsTel: setParam(v.scense.contactst, 62), |
| | | }, |
| | | } |
| | | }; |
| | | // default: |
| | | // v.invalid = true; |
| | | // return undefined; |
| | | } |
| | | }); |
| | | }) |
| | | |
| | | return param; |
| | | return param |
| | | } |
| | | |
| | | // æ ¹æ®åºæ¯ç±»åï¼çæå¯¹åºçwordææ¡£ |
| | | function generateDoc(param, callback) { |
| | | param.map((p, index) => { |
| | | let template, _param; |
| | | let template, _param |
| | | switch (p.type) { |
| | | // å·¥å° |
| | | case 1: |
| | | template = p._isDetail |
| | | ? '/å·¥å°å·¡æ¥åæ®æ¨¡æ¿-详ç.docx' |
| | | : '/å·¥å°å·¡æ¥åæ®æ¨¡æ¿-ç®ç.docx'; |
| | | _param = p.params; |
| | | break; |
| | | template = p._isDetail ? '/å·¥å°å·¡æ¥åæ®æ¨¡æ¿-详ç.docx' : '/å·¥å°å·¡æ¥åæ®æ¨¡æ¿-ç®ç.docx' |
| | | _param = p.params |
| | | break |
| | | // é¤é¥® |
| | | case 5: |
| | | template = '/é¤é¥®å·¡æ¥åæ®æ¨¡æ¿.docx'; |
| | | _param = p.params; |
| | | break; |
| | | template = '/é¤é¥®å·¡æ¥åæ®æ¨¡æ¿.docx' |
| | | _param = p.params |
| | | break |
| | | default: |
| | | break; |
| | | break |
| | | } |
| | | prepareDocxBlob(template, _param).then((blob) => { |
| | | callback(blob, `${_param.name}å·¡æ¥åæ®.docx`, index); |
| | | }); |
| | | }); |
| | | callback(blob, `${_param.name}å·¡æ¥åæ®.docx`, index) |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | function filePrepare(callback) { |
| | | const param = parseParam(); |
| | | const param = parseParam() |
| | | if (param) { |
| | | return generateDoc(param, callback); |
| | | return generateDoc(param, callback) |
| | | } |
| | | } |
| | | |
| | | // ç¹å»ä¸è½½æé®æä½, ä¸è½½wordææ¡£ |
| | | function handelDownload() { |
| | | filePrepare((blob, name) => { |
| | | downloadDocx(blob, name); |
| | | }); |
| | | downloadDocx(blob, name) |
| | | }) |
| | | } |
| | | |
| | | // ç¹å»æå°æé®æä½ |
| | |
| | | justify-content: space-between; |
| | | align-items: flex-end; |
| | | } |
| | | ` |
| | | }); |
| | | `, |
| | | }) |
| | | } |
| | | } |
| | | |
| | | function handlePreview(item) { |
| | | // é¢è§çææ¡£ï¼åºååç¬æå°åæå°å
¨é¨ |
| | | previewList.value = item ? ['0'] : checkList.value; |
| | | const param = item ? parseParam(item) : parseParam(); |
| | | previewList.value = item ? ['0'] : checkList.value |
| | | const param = item ? parseParam(item) : parseParam() |
| | | if (param) { |
| | | generateDoc(param, (blob, name, index) => { |
| | | previewVisible.value = true; |
| | | previewVisible.value = true |
| | | setTimeout(() => { |
| | | previewDocx(blob, document.getElementById(`word-preview-${index}`)); |
| | | }, 200); |
| | | }); |
| | | previewDocx(blob, document.getElementById(`word-preview-${index}`)) |
| | | }, 200) |
| | | }) |
| | | } |
| | | } |
| | | |
| | | // åæ¶æä½ |
| | | function cancel() { |
| | | // å
³éå¯¹è¯æ¡ |
| | | handleDialogChange(false); |
| | | handleDialogChange(false) |
| | | } |
| | | </script> |
| | | <style scoped> |
| | |
| | | data: r, |
| | | } |
| | | }) |
| | | this.tasks = list |
| | | this.tasks = list.filter((e) => { |
| | | return ( |
| | | e.data.districtname == '徿±åº' && dayjs(e.data.starttime).isBefore(dayjs('2023-12-31')) |
| | | ) |
| | | }) |
| | | if (list.length == 0) { |
| | | this.sideLoading = false |
| | | this.mainLoading = false |
| | |
| | | taskApi |
| | | .fetchMonitorObjectVersion(task.data.tguid) |
| | | .then((res) => { |
| | | this.curMonitorObjList = res |
| | | this.curMonitorObjList = res.filter((item) => { |
| | | return item.scene.type == 'é¤é¥®' |
| | | }) |
| | | }) |
| | | .finally(() => { |
| | | this.mainLoading = false |
| | |
| | | <template> |
| | | <el-row gutter="20"> |
| | | <el-col |
| | | :span="16" |
| | | style="border-right: 1px solid var(--el-color-info-light-7)" |
| | | > |
| | | <el-col :span="16" style="border-right: 1px solid var(--el-color-info-light-7)"> |
| | | <div> |
| | | <el-text>å·²éåºæ¯</el-text> |
| | | <el-text type="info" size="small">{{ statisticText }}</el-text> |
| | |
| | | <template #default="{ row }"> |
| | | <ItemScene :item="row"> |
| | | <el-button-group> |
| | | <el-button |
| | | size="small" |
| | | type="primary" |
| | | @click="openInsertDialog(row)" |
| | | >æå
¥</el-button |
| | | > |
| | | <el-button |
| | | size="small" |
| | | type="primary" |
| | | @click="openAddDialog(row)" |
| | | >æ°å¢</el-button |
| | | > |
| | | <el-button size="small" type="primary" @click="openInsertDialog(row)">æå
¥</el-button> |
| | | <el-button size="small" type="primary" @click="openAddDialog(row)">æ°å¢</el-button> |
| | | </el-button-group> |
| | | </ItemScene> |
| | | </template> |
| | |
| | | <div v-if="valibleIndex.length > 0">以ä¸ä¸ºå¯éç空ä½ç¼å·</div> |
| | | <div v-else>æ å¯éç空ä½ç¼å·</div> |
| | | <el-radio-group v-model="selectedIndex" size="default"> |
| | | <el-radio-button |
| | | v-for="item in valibleIndex" |
| | | :key="item" |
| | | :label="item" |
| | | :value="item" |
| | | /> |
| | | <el-radio-button v-for="item in valibleIndex" :key="item" :label="item" :value="item" /> |
| | | </el-radio-group> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button @click="insertDialog = false">åæ¶</el-button> |
| | | <el-button :disabled="!selectedIndex" type="primary" @click="insertMov"> |
| | | 确认 |
| | | </el-button> |
| | | <el-button :disabled="!selectedIndex" type="primary" @click="insertMov"> 确认 </el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import { useCloned } from '@vueuse/core'; |
| | | import CompMonitorObj from './CompMonitorObj.vue'; |
| | | import taskApi from '@/api/fysp/taskApi'; |
| | | import sceneApi from '@/api/fysp/sceneApi'; |
| | | import { ElMessage, ElNotification, ElMessageBox } from 'element-plus'; |
| | | import { useCloned } from '@vueuse/core' |
| | | import CompMonitorObj from './CompMonitorObj.vue' |
| | | import taskApi from '@/api/fysp/taskApi' |
| | | import sceneApi from '@/api/fysp/sceneApi' |
| | | import { ElMessage, ElNotification, ElMessageBox } from 'element-plus' |
| | | |
| | | const MODE_CREATE = 'create'; |
| | | const MODE_UPDATE = 'update'; |
| | | const MODE_CREATE = 'create' |
| | | const MODE_UPDATE = 'update' |
| | | |
| | | export default { |
| | | components: { CompMonitorObj }, |
| | |
| | | // ç¼è¾æ¨¡å¼ï¼æ°å¢createææ´æ°update |
| | | mode: { |
| | | type: String, |
| | | default: MODE_CREATE |
| | | default: MODE_CREATE, |
| | | }, |
| | | create: Boolean, |
| | | // å·¡æ¥æ»ä»»å¡ |
| | | task: { |
| | | type: Object, |
| | | default: () => { |
| | | return {}; |
| | | } |
| | | return {} |
| | | }, |
| | | }, |
| | | // çç®¡åºæ¯éå |
| | | objList: Array |
| | | objList: Array, |
| | | }, |
| | | data() { |
| | | return { |
| | |
| | | // å é¤ççç®¡åºæ¯ |
| | | deleteObj: [], |
| | | // æ´æ°çåºæ¯åºæ¬ä¿¡æ¯ï¼æ´æ°åºæ¯çç¼å·ï¼ |
| | | updateScene: [] |
| | | }; |
| | | updateScene: [], |
| | | } |
| | | }, |
| | | emits: ['uploadSuccess', 'uploadFail'], |
| | | watch: { |
| | | objList: { |
| | | handler(nV, oV) { |
| | | if (nV != oV) { |
| | | this.curMonitorObjList = useCloned(nV).cloned.value; |
| | | this.curMonitorObjList = useCloned(nV).cloned.value |
| | | } |
| | | }, |
| | | immediate: true |
| | | } |
| | | immediate: true, |
| | | }, |
| | | // task: { |
| | | // handler(nV, oV) { |
| | | // if (nV != oV) { |
| | |
| | | districtname: this.task.districtname, |
| | | towncode: this.task.towncode, |
| | | townname: this.task.townname, |
| | | online: true |
| | | }; |
| | | online: true, |
| | | scensetypeid: '5', |
| | | } |
| | | }, |
| | | // å½ååºæ¯ç±»åä¸çå±ç¤ºåºæ¯ |
| | | showSceneList() { |
| | | return this.sceneList.filter((v) => { |
| | | const index = this.curMonitorObjList.findIndex((o) => { |
| | | return o.sguid == v.guid; |
| | | }); |
| | | return index == -1 && v.type == this.curSceneType; |
| | | }); |
| | | return o.sguid == v.guid |
| | | }) |
| | | return index == -1 && v.type == this.curSceneType |
| | | }) |
| | | }, |
| | | sceneTypeOptions() { |
| | | const list = []; |
| | | const list = [] |
| | | this.sceneList.forEach((d) => { |
| | | if (list.indexOf(d.type) == -1) list.push(d.type); |
| | | }); |
| | | return list; |
| | | if (list.indexOf(d.type) == -1) list.push(d.type) |
| | | }) |
| | | return list |
| | | }, |
| | | // å½ååºæ¯ç±»åä¸ç坿å
¥ç¼å· |
| | | valibleIndex() { |
| | | // ååè¡¨å·²ç»æç
§ç¼å·é¡ºåºæå |
| | | let index = 1; |
| | | const indexList = []; |
| | | let index = 1 |
| | | const indexList = [] |
| | | this.showMonitorObjList.forEach((l) => { |
| | | while (l.displayid > index) { |
| | | indexList.push(index); |
| | | index++; |
| | | indexList.push(index) |
| | | index++ |
| | | } |
| | | index++; |
| | | }); |
| | | index++ |
| | | }) |
| | | if (this.showMonitorObjList.length == 0 && indexList.length == 0) { |
| | | indexList.push(1); |
| | | indexList.push(1) |
| | | } |
| | | return indexList; |
| | | return indexList |
| | | }, |
| | | lastIndex() { |
| | | const len = this.showMonitorObjList.length; |
| | | const len = this.showMonitorObjList.length |
| | | if (len > 0) { |
| | | return this.showMonitorObjList[len - 1].displayid + 1; |
| | | return this.showMonitorObjList[len - 1].displayid + 1 |
| | | } else { |
| | | return 1; |
| | | return 1 |
| | | } |
| | | }, |
| | | isEdit() { |
| | | // æ°å»ºç管æ»ä»»å¡æ¨¡å¼ |
| | | if (this.create) { |
| | | return this.curMonitorObjList.length > 0; |
| | | return this.curMonitorObjList.length > 0 |
| | | } |
| | | // æ´æ°ç管æ»ä»»å¡æ¨¡å¼ |
| | | else { |
| | | return ( |
| | | this.insertObj.length > 0 || |
| | | this.deleteObj.length > 0 || |
| | | this.updateObj.length > 0 |
| | | ); |
| | | return this.insertObj.length > 0 || this.deleteObj.length > 0 || this.updateObj.length > 0 |
| | | } |
| | | }, |
| | | statisticText() { |
| | | const total = this.curMonitorObjList.length; |
| | | const map = new Map(); |
| | | const total = this.curMonitorObjList.length |
| | | const map = new Map() |
| | | this.curMonitorObjList.forEach((e) => { |
| | | const d = e.scene; |
| | | const d = e.scene |
| | | if (!map.has(d.type)) { |
| | | map.set(d.type, { num: 0 }); |
| | | map.set(d.type, { num: 0 }) |
| | | } |
| | | map.get(d.type).num++; |
| | | }); |
| | | map.get(d.type).num++ |
| | | }) |
| | | |
| | | let res = `ï¼æ»è®¡${total}个`; |
| | | let res = `ï¼æ»è®¡${total}个` |
| | | for (const [key, value] of map) { |
| | | res += `ï¼${key}${value.num}个`; |
| | | res += `ï¼${key}${value.num}个` |
| | | } |
| | | res += 'ï¼'; |
| | | return res; |
| | | } |
| | | res += 'ï¼' |
| | | return res |
| | | }, |
| | | }, |
| | | methods: { |
| | | // æ¥è¯¢ |
| | | searchScene({ text, page, pageSize }) { |
| | | this.area.sceneName = text; |
| | | this.area.sceneName = text |
| | | return sceneApi.searchScene(this.area, 1, 10000).then((res) => { |
| | | if (res.success) { |
| | | // æ¥è¯¢ç»æ |
| | | this.sceneList = res.data; |
| | | this.sceneList = res.data |
| | | // æ»æ°æ®é |
| | | this.total = res.head.totalCount; |
| | | this.total = res.head.totalCount |
| | | } |
| | | }); |
| | | }) |
| | | }, |
| | | deleteMov(item) { |
| | | if ( |
| | | !( |
| | | item.extension1 == null || |
| | | item.extension1 == undefined || |
| | | item.extension1 == '0' |
| | | ) |
| | | ) { |
| | | if (!(item.extension1 == null || item.extension1 == undefined || item.extension1 == '0')) { |
| | | ElMessage({ |
| | | message: 'å·²çç®¡åºæ¯æ æ³ç§»é¤', |
| | | type: 'error' |
| | | }); |
| | | return; |
| | | type: 'error', |
| | | }) |
| | | return |
| | | } |
| | | const i = this.curMonitorObjList.indexOf(item); |
| | | this.curMonitorObjList.splice(i, 1); |
| | | const i1 = this.insertObj.indexOf(item); |
| | | this.insertObj.splice(i1, 1); |
| | | const i2 = this.updateObj.indexOf(item); |
| | | this.updateObj.splice(i2, 1); |
| | | const i = this.curMonitorObjList.indexOf(item) |
| | | this.curMonitorObjList.splice(i, 1) |
| | | const i1 = this.insertObj.indexOf(item) |
| | | this.insertObj.splice(i1, 1) |
| | | const i2 = this.updateObj.indexOf(item) |
| | | this.updateObj.splice(i2, 1) |
| | | const i3 = this.updateScene.findIndex((s) => { |
| | | return s.guid == item.sguid; |
| | | }); |
| | | this.updateScene.splice(i3, 1); |
| | | return s.guid == item.sguid |
| | | }) |
| | | this.updateScene.splice(i3, 1) |
| | | |
| | | this.deleteObj.push(item); |
| | | this.deleteObj.push(item) |
| | | }, |
| | | openInsertDialog(item) { |
| | | this.insertDialog = true; |
| | | this.selectedScene = item; |
| | | this.monitorTimes = 1; |
| | | this.insertDialog = true |
| | | this.selectedScene = item |
| | | this.monitorTimes = 1 |
| | | }, |
| | | openAddDialog(item) { |
| | | this.addDialog = true; |
| | | this.selectedScene = item; |
| | | this.monitorTimes = 1; |
| | | this.addDialog = true |
| | | this.selectedScene = item |
| | | this.monitorTimes = 1 |
| | | }, |
| | | insertMov() { |
| | | // 1. å建æ°åºæ¯ |
| | | let mov = this.createMov(this.selectedIndex, this.selectedScene); |
| | | let mov = this.createMov(this.selectedIndex, this.selectedScene) |
| | | // 2. æ¥æ¾ç¬¬ä¸ä¸ªç¼å·å¤§äºæå
¥ç¼å·çå¼ï¼å°æ°ç管对象æå
¥å
¶ä¹å |
| | | const insertAtIndex = this.curMonitorObjList.findIndex((v) => { |
| | | return v.displayid > this.selectedIndex; |
| | | }); |
| | | this.curMonitorObjList.splice(insertAtIndex, 0, mov); |
| | | this.selectedIndex = undefined; |
| | | this.insertDialog = false; |
| | | return v.displayid > this.selectedIndex |
| | | }) |
| | | this.curMonitorObjList.splice(insertAtIndex, 0, mov) |
| | | this.selectedIndex = undefined |
| | | this.insertDialog = false |
| | | }, |
| | | addMov() { |
| | | // 1. å建æ°åºæ¯ |
| | | let mov = this.createMov(this.lastIndex, this.selectedScene); |
| | | let mov = this.createMov(this.lastIndex, this.selectedScene) |
| | | // 2. æ·»å è³æ«å°¾ |
| | | this.curMonitorObjList.push(mov); |
| | | this.addDialog = false; |
| | | this.curMonitorObjList.push(mov) |
| | | this.addDialog = false |
| | | }, |
| | | // å建ä¸ä¸ªæ°çç管对象 |
| | | createMov(displayid, scene) { |
| | | // 1. æ¥æ¾è¯¥åºæ¯æ¯å¦ä¹å已被å é¤ |
| | | const index = this.deleteObj.findIndex((v) => { |
| | | return v.sguid == scene.guid; |
| | | }); |
| | | let mov; |
| | | return v.sguid == scene.guid |
| | | }) |
| | | let mov |
| | | // 2. è¥æ¯å
¨æ°çåºæ¯ï¼åæ°çæä¸ä¸ªç管对象ï¼å¦ååªæ´æ°ç¼å· |
| | | if (index == -1) { |
| | | mov = { |
| | |
| | | monitornum: this.monitorTimes, |
| | | displayid: displayid, |
| | | sceneTypeId: scene.typeid, |
| | | sceneType: scene.type |
| | | }; |
| | | this.insertObj.push(mov); |
| | | sceneType: scene.type, |
| | | } |
| | | this.insertObj.push(mov) |
| | | } else { |
| | | mov = this.deleteObj[index]; |
| | | mov.displayid = displayid; |
| | | this.updateObj.push(mov); |
| | | this.deleteObj.splice(index, 1); |
| | | mov = this.deleteObj[index] |
| | | mov.displayid = displayid |
| | | this.updateObj.push(mov) |
| | | this.deleteObj.splice(index, 1) |
| | | } |
| | | // 3. åæ¥æ´æ°åºæ¯åºæ¬ä¿¡æ¯ä¸çç¼å· |
| | | scene._index = displayid; |
| | | this.updateScene.push(scene); |
| | | scene._index = displayid |
| | | this.updateScene.push(scene) |
| | | |
| | | return mov; |
| | | return mov |
| | | }, |
| | | // ä¿åä¿®æ¹ |
| | | saveEdit() { |
| | | if (this.create) { |
| | | this.createTask(); |
| | | this.createTask() |
| | | } else { |
| | | this.updateTask(); |
| | | this.updateTask() |
| | | } |
| | | }, |
| | | createTask() { |
| | |
| | | title: `å·¡æ¥æ»ä»»å¡åå»ºå®æ`, |
| | | message: `æ°å¢åºæ¯${res}个`, |
| | | type: 'success', |
| | | position: 'bottom-left' |
| | | }); |
| | | this.$emit('uploadSuccess'); |
| | | position: 'bottom-left', |
| | | }) |
| | | .catch((err) => this.$emit('uploadFail', err)); |
| | | this.$emit('uploadSuccess') |
| | | }) |
| | | .catch((err) => this.$emit('uploadFail', err)) |
| | | } |
| | | this.updateSceneList(); |
| | | this.updateSceneList() |
| | | }, |
| | | updateTask() { |
| | | // new Promise((resolve, reject)=>{ |
| | |
| | | title: `å·¡æ¥ä»»å¡æ°å¢å®æ`, |
| | | message: `æ°å¢åºæ¯${res}个`, |
| | | type: 'success', |
| | | position: 'bottom-left' |
| | | }); |
| | | this.insertObj = []; |
| | | }); |
| | | position: 'bottom-left', |
| | | }) |
| | | this.insertObj = [] |
| | | }) |
| | | } |
| | | if (this.updateObj.length > 0) { |
| | | const p2 = taskApi.updateMonitorObject(this.updateObj).then((res) => { |
| | |
| | | title: `å·¡æ¥ä»»å¡æ´æ°å®æ`, |
| | | message: `æ´æ°åºæ¯${res}个`, |
| | | type: 'success', |
| | | position: 'bottom-left' |
| | | }); |
| | | this.updateObj = []; |
| | | }); |
| | | position: 'bottom-left', |
| | | }) |
| | | this.updateObj = [] |
| | | }) |
| | | } |
| | | if (this.deleteObj.length > 0) { |
| | | const p3 = taskApi.deleteMonitorObject(this.deleteObj).then((res) => { |
| | |
| | | title: `å·¡æ¥ä»»å¡å é¤å®æ`, |
| | | message: `å é¤åºæ¯${res}个`, |
| | | type: 'success', |
| | | position: 'bottom-left' |
| | | }); |
| | | this.deleteObj = []; |
| | | }); |
| | | position: 'bottom-left', |
| | | }) |
| | | this.deleteObj = [] |
| | | }) |
| | | } |
| | | this.updateSceneList(); |
| | | this.updateSceneList() |
| | | // return Promise.all([p1, p2, p3]).finally(() => { |
| | | // this.saveLoading = false; |
| | | // }); |
| | |
| | | updateSceneList() { |
| | | if (this.updateScene.length > 0) { |
| | | this.updateScene.forEach((s) => { |
| | | s.index = s._index; |
| | | }); |
| | | s.index = s._index |
| | | }) |
| | | sceneApi.updateSceneList(this.updateScene).then((res) => { |
| | | ElNotification({ |
| | | title: `åºæ¯ç¼å·æ´æ°å®æ`, |
| | | message: `æ´æ°åºæ¯${res}个`, |
| | | type: 'success', |
| | | position: 'bottom-left' |
| | | }); |
| | | this.updateScene = []; |
| | | }); |
| | | position: 'bottom-left', |
| | | }) |
| | | this.updateScene = [] |
| | | }) |
| | | } |
| | | } |
| | | }, |
| | | }, |
| | | mounted() { |
| | | setTimeout(() => { |
| | | this.searchScene({ text: '' }); |
| | | }, 1000); |
| | | this.searchScene({ text: '' }) |
| | | }, 1000) |
| | | }, |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped> |
| | |
| | | <el-text>{{ dateStr }}计å</el-text> |
| | | </el-space> |
| | | <div v-show="create && data && data.length > 0"> |
| | | <el-button |
| | | icon="IconPrinter" |
| | | type="success" |
| | | size="small" |
| | | plain |
| | | @click="handleInspectFileDownload" |
| | | >åæ®æå°</el-button |
| | | > |
| | | <el-button type="success" size="small" plain @click="handleInspectFileDownload"> |
| | | <el-icon class="el-icon--left"> |
| | | <Icon icon="solar:printer-minimalistic-line-duotone" /> |
| | | </el-icon> |
| | | åæ®æå° |
| | | </el-button> |
| | | <el-button type="success" size="small" @click="add" icon="Switch">ä»»å¡è°æ´</el-button> |
| | | <el-button type="primary" size="small" @click="openMap"> |
| | | ä»»å¡å°å¾<el-icon class="el-icon--right"><Right /></el-icon> |
| | |
| | | import CompSubTaskEdit from './CompSubTaskEdit.vue' |
| | | import SceneInspectFile from '@/views/inspection/scene/SceneInspectFile.vue' |
| | | import subtaskApi from '@/api/fysp/subtaskApi' |
| | | import { Icon } from '@iconify/vue' |
| | | |
| | | const props = defineProps({ |
| | | modelValue: Array, |
| | |
| | | <div class="data-dashboard"> |
| | | <!-- 顶鍿æ å¡çåº --> |
| | | <div class="top-cards"> |
| | | <div class="cards-container"> |
| | | <!-- æ¶é´å¨æé项å¡ç --> |
| | | <div class="time-period-card"> |
| | | <div class="card-title">æ¶é´å¨æ</div> |
| | | <div class="card-title">æ¶é´éæ©</div> |
| | | <div class="time-controls"> |
| | | <div class="time-tab-container"> |
| | | <div |
| | | v-for="tab in timeTabs" |
| | |
| | | {{ tab.label }} |
| | | </div> |
| | | </div> |
| | | <div class="time-navigator"> |
| | | <button class="nav-btn" @click="navigateTime(-1)" title="ä¸ä¸ä¸ªå¨æ"> |
| | | <svg |
| | | width="16" |
| | | height="16" |
| | | viewBox="0 0 24 24" |
| | | fill="none" |
| | | xmlns="http://www.w3.org/2000/svg" |
| | | > |
| | | <path |
| | | d="M15 18L9 12L15 6" |
| | | stroke="currentColor" |
| | | stroke-width="2" |
| | | stroke-linecap="round" |
| | | stroke-linejoin="round" |
| | | /> |
| | | </svg> |
| | | </button> |
| | | <div class="current-time">{{ currentTimeDisplay }}</div> |
| | | <button class="nav-btn" @click="navigateTime(1)" title="ä¸ä¸ä¸ªå¨æ"> |
| | | <svg |
| | | width="16" |
| | | height="16" |
| | | viewBox="0 0 24 24" |
| | | fill="none" |
| | | xmlns="http://www.w3.org/2000/svg" |
| | | > |
| | | <path |
| | | d="M9 18L15 12L9 6" |
| | | stroke="currentColor" |
| | | stroke-width="2" |
| | | stroke-linecap="round" |
| | | stroke-linejoin="round" |
| | | /> |
| | | </svg> |
| | | </button> |
| | | </div> |
| | | |
| | | </div> |
| | | </div> |
| | | <div class="cards-container"> |
| | | <!-- è¶
æ æ° --> |
| | | <div class="metric-card"> |
| | | <div class="card-header"> |
| | |
| | | <!-- ä¸é¨GISå°å¾åº --> |
| | | <div class="map-section"> |
| | | <div id="map" class="map-container"> |
| | | <BaseMap></BaseMap> |
| | | <BaseMap :showSatellite="true"></BaseMap> |
| | | </div> |
| | | |
| | | <!-- å°å¾ç¹ä½å¼¹çª --> |
| | |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | |
| | | </div> |
| | | <!-- å³ä¾§å®æ¶çæµæ»è§åº --> |
| | | <div class="overview-section"> |
| | | <div class="section-header"> |
| | | <h3>宿¶çæµæ»è§</h3> |
| | | <span class="view-more">æ¥çæ´å¤</span> |
| | | <h3>设å¤çæ§</h3> |
| | | <!-- <span class="view-more">æ¥çæ´å¤</span> --> |
| | | </div> |
| | | |
| | | <div class="overview-items-container"> |
| | |
| | | <canvas id="deviceStatusChart"></canvas> |
| | | </div> |
| | | </div> |
| | | <!-- å·¡æ¥æ
åµç»è®¡å¡ç --> |
| | | <el-scrollbar class="inspection-section"> |
| | | <div class="section-header"> |
| | | <h3>å·¡æ¥æ±æ»</h3> |
| | | </div> |
| | | |
| | | <!-- å·¡æ¥éç»è®¡ --> |
| | | <div class="inspection-metrics"> |
| | | <div class="inspection-metric-item"> |
| | | <div class="inspection-metric-label">åºéºæ»è®¡</div> |
| | | <div class="inspection-metric-value">{{ inspectionStats.totalShops }}</div> |
| | | </div> |
| | | <div class="inspection-metric-item"> |
| | | <div class="inspection-metric-label">å·¡æ¥åºéº</div> |
| | | <div class="inspection-metric-value">{{ inspectionStats.inspectedShops }}</div> |
| | | </div> |
| | | <div class="inspection-metric-item"> |
| | | <div class="inspection-metric-label">å·¡æ¥ç¹æ¬¡</div> |
| | | <div class="inspection-metric-value">{{ inspectionStats.inspectionPoints }}</div> |
| | | </div> |
| | | <div class="inspection-metric-item"> |
| | | <div class="inspection-metric-label">夿¥ç¹æ¬¡</div> |
| | | <div class="inspection-metric-value">{{ inspectionStats.reviewPoints }}</div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- é®é¢æ´æ¹æ
åµ --> |
| | | <div class="inspection-chart-container"> |
| | | <div class="section-header"><h3>æ´æ¹æ±æ»</h3></div> |
| | | <canvas id="rectificationChart"></canvas> |
| | | </div> |
| | | |
| | | <!-- é®é¢å®¡æ ¸æ
åµ --> |
| | | <div class="inspection-table-container"> |
| | | <div class="section-header"><h3>å®¡æ ¸æ±æ»</h3></div> |
| | | <div class="inspection-metric-label">é®é¢å®¡æ ¸</div> |
| | | <div class="inspection-table"> |
| | | <div class="inspection-metric-item"> |
| | | <div class="inspection-metric-label">æ é®é¢</div> |
| | | <div class="inspection-metric-value">{{ inspectionStats.noProblemShops }}</div> |
| | | </div> |
| | | <div class="inspection-metric-item"> |
| | | <div class="inspection-metric-label">æªå®¡æ ¸</div> |
| | | <div class="inspection-metric-value"> |
| | | {{ inspectionStats.unreviewedProblemShops }} |
| | | </div> |
| | | </div> |
| | | <div class="inspection-metric-item"> |
| | | <div class="inspection-metric-label">é¨åå®¡æ ¸</div> |
| | | <div class="inspection-metric-value"> |
| | | {{ inspectionStats.partiallyReviewedProblemShops }} |
| | | </div> |
| | | </div> |
| | | <div class="inspection-metric-item"> |
| | | <div class="inspection-metric-label">å
¨é¨å®¡æ ¸</div> |
| | | <div class="inspection-metric-value"> |
| | | {{ inspectionStats.fullyReviewedProblemShops }} |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="inspection-metric-label">æ´æ¹å®¡æ ¸</div> |
| | | <div class="inspection-table"> |
| | | <div class="inspection-metric-item"> |
| | | <div class="inspection-metric-label">æªæ´æ¹</div> |
| | | <div class="inspection-metric-value">{{ inspectionStats.unrectifiedShops }}</div> |
| | | </div> |
| | | <div class="inspection-metric-item"> |
| | | <div class="inspection-metric-label">æªå®¡æ ¸</div> |
| | | <div class="inspection-metric-value"> |
| | | {{ inspectionStats.unreviewedRectifiedShops }} |
| | | </div> |
| | | </div> |
| | | <div class="inspection-metric-item"> |
| | | <div class="inspection-metric-label">é¨åå®¡æ ¸</div> |
| | | <div class="inspection-metric-value"> |
| | | {{ inspectionStats.partiallyReviewedRectifiedShops }} |
| | | </div> |
| | | </div> |
| | | <div class="inspection-metric-item"> |
| | | <div class="inspection-metric-label">å
¨é¨å®¡æ ¸</div> |
| | | <div class="inspection-metric-value"> |
| | | {{ inspectionStats.fullyReviewedRectifiedShops }} |
| | | </div> |
| | | </div> |
| | | <!-- <div class="table-row"> |
| | | <div class="table-cell">æ é®é¢åºéºæ°é</div> |
| | | <div class="table-cell value">{{ inspectionStats.noProblemShops }}</div> |
| | | </div> |
| | | <div class="table-row"> |
| | | <div class="table-cell">é®é¢æªå®¡æ ¸åºéºæ°é</div> |
| | | <div class="table-cell value">{{ inspectionStats.unreviewedProblemShops }}</div> |
| | | </div> |
| | | <div class="table-row"> |
| | | <div class="table-cell">é®é¢é¨åå®¡æ ¸åºéºæ°é</div> |
| | | <div class="table-cell value"> |
| | | {{ inspectionStats.partiallyReviewedProblemShops }} |
| | | </div> |
| | | </div> |
| | | <div class="table-row"> |
| | | <div class="table-cell">é®é¢å
¨é¨å®¡æ ¸åºéºæ°é</div> |
| | | <div class="table-cell value">{{ inspectionStats.fullyReviewedProblemShops }}</div> |
| | | </div> |
| | | <div class="table-row"> |
| | | <div class="table-cell">æªæ´æ¹åºéºæ°</div> |
| | | <div class="table-cell value">{{ inspectionStats.unrectifiedShops }}</div> |
| | | </div> |
| | | <div class="table-row"> |
| | | <div class="table-cell">æ´æ¹æªå®¡æ ¸åºéºæ°</div> |
| | | <div class="table-cell value">{{ inspectionStats.unreviewedRectifiedShops }}</div> |
| | | </div> |
| | | <div class="table-row"> |
| | | <div class="table-cell">æ´æ¹é¨åå®¡æ ¸åºéºæ°</div> |
| | | <div class="table-cell value"> |
| | | {{ inspectionStats.partiallyReviewedRectifiedShops }} |
| | | </div> |
| | | </div> |
| | | <div class="table-row"> |
| | | <div class="table-cell">æ´æ¹å
¨é¨å®¡æ ¸åºéºæ°</div> |
| | | <div class="table-cell value">{{ inspectionStats.fullyReviewedRectifiedShops }}</div> |
| | | </div> --> |
| | | </div> |
| | | </div> |
| | | </el-scrollbar> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import * as echarts from 'echarts' |
| | | import { onMapMounted, map, AMap } from '@/utils/map/index' |
| | | import { onMapMounted, satellite } from '@/utils/map/index' |
| | | import districtSearch from '@/utils/map/districtsearch.js' |
| | | import marks from '@/utils/map/marks.js' |
| | | import { generateTestShops } from '@/debug/debugdata' |
| | | |
| | | export default { |
| | | name: 'DataDashboard', |
| | | data() { |
| | | return { |
| | | activeTime: 'day', |
| | | currentDate: new Date(), |
| | | timeTabs: [ |
| | | { label: 'æ¥', value: 'day' }, |
| | | { label: 'å¨', value: 'week' }, |
| | |
| | | onlineDevices: 220, |
| | | offlineDevices: 25, |
| | | }, |
| | | inspectionStats: { |
| | | // å·¡æ¥é |
| | | totalShops: 245, |
| | | inspectedShops: 180, |
| | | inspectionPoints: 350, |
| | | reviewPoints: 80, |
| | | // é®é¢æ´æ¹æ
åµ |
| | | problemCount: 45, |
| | | rectifiedCount: 38, |
| | | rectificationRate: 84.4, |
| | | // é®é¢å®¡æ ¸æ
åµ |
| | | noProblemShops: 135, |
| | | unreviewedProblemShops: 8, |
| | | partiallyReviewedProblemShops: 5, |
| | | fullyReviewedProblemShops: 32, |
| | | unreviewedRectifiedShops: 3, |
| | | partiallyReviewedRectifiedShops: 2, |
| | | fullyReviewedRectifiedShops: 33, |
| | | unrectifiedShops: 7, |
| | | }, |
| | | map: null, |
| | | refreshTimer: null, |
| | | } |
| | | }, |
| | | computed: { |
| | | currentTimeDisplay() { |
| | | const date = this.currentDate |
| | | switch (this.activeTime) { |
| | | case 'day': |
| | | return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}` |
| | | case 'week': |
| | | // ç®å计ç®å¨æ¾ç¤ºï¼å®é
项ç®ä¸å¯è½éè¦æ´å¤æçå¨è®¡ç®é»è¾ |
| | | let weekStart = new Date(date) |
| | | weekStart.setDate(date.getDate() - date.getDay() + 1) |
| | | let weekEnd = new Date(date) |
| | | weekEnd.setDate(date.getDate() + (7 - date.getDay())) |
| | | return `${weekStart.getFullYear()}-${String(weekStart.getMonth() + 1).padStart(2, '0')}-${String(weekStart.getDate()).padStart(2, '0')} ~ ${weekEnd.getFullYear()}-${String(weekEnd.getMonth() + 1).padStart(2, '0')}-${String(weekEnd.getDate()).padStart(2, '0')}` |
| | | case 'month': |
| | | return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}` |
| | | default: |
| | | return '' |
| | | } |
| | | }, |
| | | }, |
| | | mounted() { |
| | | this.initMap() |
| | | this.initDeviceStatusChart() |
| | | this.initRectificationChart() |
| | | this.startAutoRefresh() |
| | | }, |
| | | beforeUnmount() { |
| | |
| | | // 模æåæ¢æ¶é´å¨æåçæ°æ®æ´æ° |
| | | this.updateMetrics() |
| | | }, |
| | | getPeriodLabel() { |
| | | navigateTime(direction) { |
| | | const newDate = new Date(this.currentDate) |
| | | switch (this.activeTime) { |
| | | case 'day': |
| | | return '仿¥' |
| | | newDate.setDate(newDate.getDate() + direction) |
| | | break |
| | | case 'week': |
| | | return 'æ¬å¨' |
| | | newDate.setDate(newDate.getDate() + direction * 7) |
| | | break |
| | | case 'month': |
| | | return 'æ¬æ' |
| | | default: |
| | | newDate.setMonth(newDate.getMonth() + direction) |
| | | break |
| | | } |
| | | this.currentDate = newDate |
| | | // 模æåæ¢æ¶é´åçæ°æ®æ´æ° |
| | | this.updateMetrics() |
| | | }, |
| | | getPeriodLabel() { |
| | | const today = new Date() |
| | | const isToday = |
| | | this.activeTime === 'day' && |
| | | this.currentDate.getDate() === today.getDate() && |
| | | this.currentDate.getMonth() === today.getMonth() && |
| | | this.currentDate.getFullYear() === today.getFullYear() |
| | | |
| | | if (isToday) { |
| | | return '仿¥' |
| | | } |
| | | |
| | | switch (this.activeTime) { |
| | | case 'day': |
| | | return '彿¥' |
| | | case 'week': |
| | | return 'å½å¨' |
| | | case 'month': |
| | | return '彿' |
| | | default: |
| | | return '彿¥' |
| | | } |
| | | }, |
| | | getCompareLabel() { |
| | |
| | | taskCompletionRate: Math.floor(Math.random() * 40) + 60, |
| | | taskCompletionRateTrend: Math.floor(Math.random() * 15) - 7, |
| | | } |
| | | |
| | | // æ´æ°å·¡æ¥ç»è®¡æ°æ® |
| | | this.inspectionStats = { |
| | | totalShops: 245, |
| | | inspectedShops: Math.floor(Math.random() * 50) + 150, |
| | | inspectionPoints: Math.floor(Math.random() * 100) + 300, |
| | | reviewPoints: Math.floor(Math.random() * 50) + 50, |
| | | problemCount: Math.floor(Math.random() * 30) + 20, |
| | | rectifiedCount: Math.floor(Math.random() * 25) + 15, |
| | | rectificationRate: Math.round((Math.random() * 30 + 70) * 10) / 10, |
| | | noProblemShops: Math.floor(Math.random() * 50) + 100, |
| | | unreviewedProblemShops: Math.floor(Math.random() * 10), |
| | | partiallyReviewedProblemShops: Math.floor(Math.random() * 8), |
| | | fullyReviewedProblemShops: Math.floor(Math.random() * 20) + 15, |
| | | unreviewedRectifiedShops: Math.floor(Math.random() * 5), |
| | | partiallyReviewedRectifiedShops: Math.floor(Math.random() * 5), |
| | | fullyReviewedRectifiedShops: Math.floor(Math.random() * 20) + 15, |
| | | unrectifiedShops: Math.floor(Math.random() * 10), |
| | | } |
| | | |
| | | // æ´æ°å¾è¡¨ |
| | | this.initRectificationChart() |
| | | }, 300) |
| | | }, |
| | | initMap() { |
| | | // setTimeout(() => { |
| | | districtSearch.removeDistrict() |
| | | districtSearch.drawDistrict('䏿µ·å¸') |
| | | districtSearch.drawDistrictMask('䏿µ·å¸') |
| | | // districtSearch.districtLayer('310106') |
| | | // }, 2000) |
| | | |
| | | onMapMounted(() => { |
| | | setTimeout(() => { |
| | | marks.clearMassMarks() |
| | | const shops = generateTestShops() |
| | | console.log(shops) |
| | | |
| | | marks.drawMassMarks(shops) |
| | | }, 2000) |
| | | }) |
| | | }, |
| | | initDeviceStatusChart() { |
| | | const chartDom = document.getElementById('deviceStatusChart') |
| | |
| | | chart.setOption(option) |
| | | |
| | | // ååºå¼è°æ´ |
| | | window.addEventListener('resize', () => { |
| | | chart.resize() |
| | | }) |
| | | // window.addEventListener('resize', () => { |
| | | // chart.resize() |
| | | // }) |
| | | } |
| | | }, |
| | | initRectificationChart() { |
| | | const chartDom = document.getElementById('rectificationChart') |
| | | if (chartDom) { |
| | | const chart = echarts.init(chartDom) |
| | | const option = { |
| | | tooltip: { |
| | | trigger: 'axis', |
| | | axisPointer: { |
| | | type: 'shadow', |
| | | }, |
| | | backgroundColor: 'rgba(255, 255, 255, 0.95)', |
| | | borderColor: '#e8e8e8', |
| | | borderWidth: 1, |
| | | textStyle: { |
| | | color: '#333', |
| | | }, |
| | | }, |
| | | grid: { |
| | | left: '3%', |
| | | right: '4%', |
| | | bottom: '3%', |
| | | containLabel: true, |
| | | }, |
| | | xAxis: { |
| | | type: 'category', |
| | | data: ['é®é¢æ°', 'æ´æ¹æ°'], |
| | | axisLabel: { |
| | | color: '#86909c', |
| | | fontSize: 12, |
| | | }, |
| | | }, |
| | | yAxis: { |
| | | type: 'value', |
| | | axisLabel: { |
| | | color: '#86909c', |
| | | fontSize: 12, |
| | | }, |
| | | }, |
| | | series: [ |
| | | { |
| | | name: 'æ°é', |
| | | type: 'bar', |
| | | data: [ |
| | | { |
| | | value: this.inspectionStats.problemCount, |
| | | itemStyle: { |
| | | color: '#fa8c16', |
| | | }, |
| | | }, |
| | | { |
| | | value: this.inspectionStats.rectifiedCount, |
| | | itemStyle: { |
| | | color: '#52c41a', |
| | | }, |
| | | }, |
| | | ], |
| | | barWidth: '60%', |
| | | label: { |
| | | show: true, |
| | | position: 'top', |
| | | color: '#262626', |
| | | fontSize: 12, |
| | | }, |
| | | }, |
| | | ], |
| | | } |
| | | chart.setOption(option) |
| | | |
| | | // ååºå¼è°æ´ |
| | | // window.addEventListener('resize', () => { |
| | | // chart.resize() |
| | | // }) |
| | | } |
| | | }, |
| | | startAutoRefresh() { |
| | |
| | | /* å
¨å±æ ·å¼ */ |
| | | .data-dashboard { |
| | | width: 100%; |
| | | height: calc(100vh - 60px); |
| | | height: calc(100vh - 70px); |
| | | background-color: #f5f7fa; |
| | | color: #333; |
| | | box-sizing: border-box; |
| | |
| | | /* 顶鍿æ å¡çåº */ |
| | | .top-cards { |
| | | position: absolute; |
| | | top: 24px; |
| | | left: 24px; |
| | | top: 4px; |
| | | left: 4px; |
| | | z-index: 10; |
| | | margin-bottom: 24px; |
| | | } |
| | | |
| | | .cards-container { |
| | | display: grid; |
| | | grid-template-columns: 280px; |
| | | grid-template-rows: auto repeat(4, auto); |
| | | gap: 16px; |
| | | background-color: rgba(255, 255, 255, 0.9); |
| | | padding: 16px; |
| | | grid-template-columns: repeat(2, 180px); |
| | | grid-template-rows: auto repeat(2, auto); |
| | | gap: 8px; |
| | | /* background-color: rgba(255, 255, 255, 0.9); */ |
| | | /* padding: 16px; */ |
| | | border-radius: 8px; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); |
| | | /* box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); */ |
| | | } |
| | | |
| | | /* æ¶é´å¨æå¡ç */ |
| | | .time-period-card { |
| | | background-color: #ffffff; |
| | | border-radius: 8px; |
| | | padding: 20px; |
| | | padding: 4px 16px; |
| | | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08); |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: center; |
| | | margin-bottom: 8px; |
| | | min-width: 300px; |
| | | } |
| | | |
| | | .time-period-card .card-title { |
| | |
| | | font-weight: 500; |
| | | margin-bottom: 16px; |
| | | text-align: center; |
| | | } |
| | | |
| | | .time-controls { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 16px; |
| | | } |
| | | |
| | | .time-tab-container { |
| | |
| | | } |
| | | |
| | | .time-tab { |
| | | padding: 2px 4px; |
| | | padding: 4px 8px; |
| | | border-radius: 4px; |
| | | cursor: pointer; |
| | | font-size: 14px; |
| | |
| | | text-align: center; |
| | | border: 1px solid #e8e8e8; |
| | | background-color: #fafafa; |
| | | flex: 1; |
| | | } |
| | | |
| | | .time-tab.active { |
| | |
| | | color: #1890ff; |
| | | border-color: #e6f7ff; |
| | | background-color: #e6f7ff; |
| | | } |
| | | |
| | | .time-navigator { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | gap: 12px; |
| | | padding: 8px 0; |
| | | } |
| | | |
| | | .nav-btn { |
| | | width: 32px; |
| | | height: 32px; |
| | | border: 1px solid #e8e8e8; |
| | | background-color: #fafafa; |
| | | border-radius: 4px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | cursor: pointer; |
| | | transition: all 0.3s ease; |
| | | color: #4e5969; |
| | | } |
| | | |
| | | .nav-btn:hover { |
| | | border-color: #1890ff; |
| | | color: #1890ff; |
| | | background-color: #e6f7ff; |
| | | } |
| | | |
| | | .current-time { |
| | | font-size: 14px; |
| | | font-weight: 500; |
| | | color: #262626; |
| | | min-width: 180px; |
| | | text-align: center; |
| | | padding: 0 12px; |
| | | } |
| | | |
| | | /* ææ å¡ç */ |
| | |
| | | /* å³ä¾§å®æ¶çæµæ»è§åº */ |
| | | .overview-section { |
| | | position: absolute; |
| | | top: 200px; |
| | | right: 24px; |
| | | bottom: 4px; |
| | | left: 4px; |
| | | width: 320px; |
| | | background-color: rgba(255, 255, 255, 0.9); |
| | | border-radius: 8px; |
| | |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 24px; |
| | | padding-bottom: 16px; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | } |
| | |
| | | |
| | | .device-status-chart { |
| | | flex: 1; |
| | | margin-top: 16px; |
| | | min-height: 200px; |
| | | min-height: 100px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | /* å·¡æ¥æ
åµç»è®¡ */ |
| | | .inspection-section { |
| | | position: absolute; |
| | | top: 4px; |
| | | right: 4px; |
| | | width: 320px; |
| | | background-color: rgba(255, 255, 255, 0.9); |
| | | border-radius: 8px; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); |
| | | padding: 20px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | z-index: 10; |
| | | max-height: calc(70vh); |
| | | border-top: 1px solid #f0f0f0; |
| | | } |
| | | |
| | | .inspection-metrics { |
| | | display: grid; |
| | | grid-template-columns: repeat(2, 1fr); |
| | | gap: 12px; |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .inspection-metric-item { |
| | | background-color: #fafafa; |
| | | border-radius: 6px; |
| | | padding: 12px; |
| | | text-align: center; |
| | | } |
| | | |
| | | .inspection-metric-label { |
| | | font-size: 12px; |
| | | color: #86909c; |
| | | margin-bottom: 4px; |
| | | } |
| | | |
| | | .inspection-metric-value { |
| | | font-size: 18px; |
| | | font-weight: bold; |
| | | color: #262626; |
| | | } |
| | | |
| | | .inspection-chart-container { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .chart-title { |
| | | font-size: 14px; |
| | | font-weight: 500; |
| | | color: #262626; |
| | | margin-bottom: 12px; |
| | | } |
| | | |
| | | .inspection-table-container { |
| | | /* max-height: 200px; */ |
| | | /* overflow-y: auto; */ |
| | | } |
| | | |
| | | .inspection-table { |
| | | /* width: 100%; |
| | | border-collapse: collapse; */ |
| | | display: grid; |
| | | grid-template-columns: repeat(4, 1fr); |
| | | gap: 2px; |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .table-row { |
| | | display: flex; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | padding: 8px 0; |
| | | } |
| | | |
| | | .table-row:last-child { |
| | | border-bottom: none; |
| | | } |
| | | |
| | | .table-cell { |
| | | flex: 1; |
| | | font-size: 12px; |
| | | color: #4e5969; |
| | | } |
| | | |
| | | .table-cell.value { |
| | | font-weight: 500; |
| | | color: #262626; |
| | | text-align: right; |
| | | } |
| | | |
| | | /* å¼¹çªæ ·å¼ */ |
| | |
| | | } |
| | | |
| | | /* ååºå¼è®¾è®¡ */ |
| | | @media (max-width: 1200px) { |
| | | /* @media (max-width: 1200px) { |
| | | .top-cards { |
| | | position: relative; |
| | | margin-bottom: 24px; |
| | |
| | | margin-top: 16px; |
| | | background-color: #ffffff; |
| | | } |
| | | } |
| | | } */ |
| | | |
| | | @media (max-width: 768px) { |
| | | /* @media (max-width: 768px) { |
| | | .data-dashboard { |
| | | padding: 16px; |
| | | } |
| | |
| | | width: 100%; |
| | | text-align: left; |
| | | } |
| | | } |
| | | } */ |
| | | </style> |