Merge remote-tracking branch 'origin/master'
# Conflicts:
# src/views/system/rule/index.vue
# src/views/system/template/index.vue
31个文件已修改
20个文件已添加
2个文件已删除
| | |
| | | "axios": "0.24.0", |
| | | "clipboard": "2.0.8", |
| | | "core-js": "3.25.3", |
| | | "d3": "^7.9.0", |
| | | "echarts": "5.4.0", |
| | | "echarts-gl": "^2.0.9", |
| | | "element-ui": "2.15.14", |
| | |
| | | "quill": "1.3.7", |
| | | "screenfull": "5.0.2", |
| | | "sortablejs": "1.10.2", |
| | | "three": "^0.163.0", |
| | | "v-scale-screen": "1.0.0", |
| | | "vue": "2.6.12", |
| | | "vue-count-to": "1.0.13", |
| | |
| | | <!DOCTYPE html> |
| | | <html> |
| | | <head> |
| | | <meta charset="utf-8"> |
| | | <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> |
| | | <meta name="renderer" content="webkit"> |
| | | <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> |
| | | <link rel="icon" href="<%= BASE_URL %>favicon.ico"> |
| | | <title><%= webpackConfig.name %></title> |
| | | <!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]--> |
| | | <style> |
| | | |
| | | <head> |
| | | <meta charset="utf-8"> |
| | | <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> |
| | | <meta name="renderer" content="webkit"> |
| | | <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> |
| | | <link rel="icon" href="<%= BASE_URL %>favicon.ico"> |
| | | <title> |
| | | <%= webpackConfig.name %> |
| | | </title> |
| | | <!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]--> |
| | | <style> |
| | | html, |
| | | body, |
| | | #app { |
| | | height: 100%; |
| | | margin: 0px; |
| | | padding: 0px; |
| | | overflow: hidden; |
| | | |
| | | } |
| | | |
| | | .chromeframe { |
| | | margin: 0.2em 0; |
| | | background: #ccc; |
| | |
| | | -ms-transform: rotate(0deg); |
| | | transform: rotate(0deg); |
| | | } |
| | | |
| | | 100% { |
| | | -webkit-transform: rotate(360deg); |
| | | -ms-transform: rotate(360deg); |
| | |
| | | -ms-transform: rotate(0deg); |
| | | transform: rotate(0deg); |
| | | } |
| | | |
| | | 100% { |
| | | -webkit-transform: rotate(360deg); |
| | | -ms-transform: rotate(360deg); |
| | |
| | | opacity: 0.5; |
| | | } |
| | | </style> |
| | | </head> |
| | | <body> |
| | | <div id="app"> |
| | | <div id="loader-wrapper"> |
| | | <div id="loader"></div> |
| | | <div class="loader-section section-left"></div> |
| | | <div class="loader-section section-right"></div> |
| | | <div class="load_title">正在加载系统资源,请耐心等待</div> |
| | | </div> |
| | | </div> |
| | | </body> |
| | | </html> |
| | | </head> |
| | | |
| | | <body> |
| | | <div id="app"> |
| | | <div id="loader-wrapper"> |
| | | <div id="loader"></div> |
| | | <div class="loader-section section-left"></div> |
| | | <div class="loader-section section-right"></div> |
| | | <div class="load_title">正在加载系统资源,请耐心等待</div> |
| | | </div> |
| | | </div> |
| | | </body> |
| | | |
| | | </html> |
| | |
| | | // 查询运维阈值列表 |
| | | export function listThreshold(query) { |
| | | return request({ |
| | | url: '/ycl/threshold/list', |
| | | url: '/threshold/list', |
| | | method: 'get', |
| | | params: query |
| | | }) |
| | | } |
| | | |
| | | // 查询运维阈值详细 |
| | | export function getThreshold(id) { |
| | | export function getVideo(id) { |
| | | return request({ |
| | | url: '/ycl/threshold/' + id, |
| | | url: '/threshold/video/' + id, |
| | | method: 'get' |
| | | }) |
| | | } |
| | | |
| | | // 查询运维阈值详细 |
| | | export function getCar(id) { |
| | | return request({ |
| | | url: '/threshold/car/' + id, |
| | | method: 'get' |
| | | }) |
| | | } |
| | | |
| | | // 查询运维阈值详细 |
| | | export function getFace(id) { |
| | | return request({ |
| | | url: '/threshold/face/' + id, |
| | | method: 'get' |
| | | }) |
| | | } |
| | |
| | | // 新增运维阈值 |
| | | export function addThreshold(data) { |
| | | return request({ |
| | | url: '/ycl/threshold', |
| | | url: '/threshold', |
| | | method: 'post', |
| | | data: data |
| | | }) |
| | |
| | | // 修改运维阈值 |
| | | export function updateThreshold(data) { |
| | | return request({ |
| | | url: '/ycl/threshold', |
| | | url: '/threshold', |
| | | method: 'put', |
| | | data: data |
| | | }) |
| | |
| | | // 删除运维阈值 |
| | | export function delThreshold(id) { |
| | | return request({ |
| | | url: '/ycl/threshold/' + id, |
| | | url: '/threshold/' + id, |
| | | method: 'delete' |
| | | }) |
| | | } |
| | | |
| | | // 修改视频阈值 |
| | | export function editVideo(data) { |
| | | return request({ |
| | | url: '/threshold/video', |
| | | method: 'put', |
| | | data: data |
| | | }) |
| | | } |
| | | |
| | | // 修改车辆阈值 |
| | | export function editCar(data) { |
| | | return request({ |
| | | url: '/threshold/car', |
| | | method: 'put', |
| | | data: data |
| | | }) |
| | | } |
| | | |
| | | // 修改人脸阈值 |
| | | export function editFace(data) { |
| | | return request({ |
| | | url: '/threshold/face', |
| | | method: 'put', |
| | | data: data |
| | | }) |
| | | } |
| | |
| | | method: 'get' |
| | | }) |
| | | } |
| | | |
| | | // 获取运维单位工单统计列表 |
| | | export function workList() { |
| | | return request({ |
| | | url: '/yw-unit/work/list', |
| | | method: 'get' |
| | | }) |
| | | } |
| | |
| | | }) |
| | | } |
| | | |
| | | // 下发选择工单 |
| | | export function selectedIdsDistribute(data) { |
| | | return request({ |
| | | url: '/work-order/distribute/ids', |
| | | method: 'post', |
| | | data: data |
| | | }) |
| | | } |
| | | |
| | | // 查询运维工单详细 |
| | | export function getWorkOrder(id) { |
| | | return request({ |
| | |
| | | data: data |
| | | }) |
| | | } |
| | | |
| | | // 获取工单运维情况 |
| | | export function getYwCondition(data) { |
| | | return request({ |
| | | url: '/work-order/yw-condition/' + data, |
| | | method: 'get' |
| | | }) |
| | | } |
| | | |
| | | // 获取工单运维审核记录 |
| | | export function getYwAuditingList(data) { |
| | | return request({ |
| | | url: '/work-order/yw-auditing-list/' + data, |
| | | method: 'get' |
| | | }) |
| | | } |
| | | |
| | | // 获取工单运维情况记录 |
| | | export function getYwConditionList(data) { |
| | | return request({ |
| | | url: '/work-order/yw-condition-list/' + data, |
| | | method: 'get' |
| | | }) |
| | | } |
| | |
| | | <!-- 文件列表 --> |
| | | <transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul"> |
| | | <li :key="file.url" class="el-upload-list__item ele-upload-list__item-content" v-for="(file, index) in fileList"> |
| | | <el-link :href="`${baseUrl}${file.url}`" :underline="false" target="_blank"> |
| | | <el-link @click="handleDownload(file.url)" :underline="false" target="_blank"> |
| | | <span class="el-icon-document"> {{ getFileName(file.name) }} </span> |
| | | </el-link> |
| | | <!-- <el-link :href="`${baseUrl}${file.url}`" :underline="false" target="_blank"> |
| | | <span class="el-icon-document"> {{ getFileName(file.name) }} </span> |
| | | </el-link> --> |
| | | <div class="ele-upload-list__item-content-action"> |
| | | <el-link :underline="false" @click="handleDelete(index)" type="danger">删除</el-link> |
| | | </div> |
| | |
| | | strs += list[i].url + separator; |
| | | } |
| | | return strs != '' ? strs.substr(0, strs.length - 1) : ''; |
| | | }, |
| | | /** 下载按钮操作 */ |
| | | handleDownload (data) { |
| | | this.$download.resource(data); |
| | | } |
| | | } |
| | | }; |
| | |
| | | |
| | | NProgress.configure({ showSpinner: false }) |
| | | |
| | | const whiteList = ['/login', '/register',] |
| | | const whiteList = ['/login', '/register','/screen'] |
| | | |
| | | router.beforeEach((to, from, next) => { |
| | | NProgress.start() |
| | |
| | | <script> |
| | | import * as echarts from 'echarts'; |
| | | import 'echarts-gl'; |
| | | import mapData from '@/assets/map/zigong.json'; |
| | | import mapData from '@/assets/map/zigong2.json'; |
| | | echarts.registerMap('zigong', mapData); |
| | | console.log(mapData); |
| | | let mapChart = null; |
| | |
| | | grid: { |
| | | top: '10%', |
| | | right: 0, |
| | | bottom: '15%', |
| | | bottom: '17%', |
| | | }, |
| | | legend: { |
| | | right: 0, |
| | |
| | | margin: 10px 0; |
| | | |
| | | .panel-item { |
| | | width: 120px; |
| | | height: 120px; |
| | | width: 110px; |
| | | height: 110px; |
| | | } |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <div class="map-container"> |
| | | <wrapper-title :title="'区域地图'"></wrapper-title> |
| | | <div class="map-content"> |
| | | </div> |
| | | </div> |
| | | |
| | | </template> |
| | | |
| | | <script> |
| | | import WrapperTitle from '../wrapper-title/index'; |
| | | |
| | | export default { |
| | | name: 'ScreenMapCover', |
| | | components: { |
| | | WrapperTitle |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .map-container { |
| | | width: 100%; |
| | | flex: 1; |
| | | margin-bottom: 20px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | |
| | | .map-content { |
| | | flex: 1; |
| | | pointer-events: none; |
| | | |
| | | } |
| | | |
| | | } |
| | | </style> |
New file |
| | |
| | | import { MathUtils } from 'three'; |
| | | import { PerspectiveCamera, CameraHelper } from 'three'; |
| | | import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'; |
| | | |
| | | |
| | | export default class Camera { |
| | | constructor(experience) { |
| | | this.experience = experience; |
| | | this.scene = experience.scene; |
| | | this.canvas = experience.canvas; |
| | | this.sizes = experience.sizes; |
| | | this.setInstance(); |
| | | this.setOrbitControls(); |
| | | } |
| | | |
| | | // 设置透视相机 |
| | | setInstance() { |
| | | this.instance = new PerspectiveCamera(45, this.sizes.width / this.sizes.height, 0.1, 200); |
| | | this.instance.position.set(0, 45, 45); |
| | | this.scene.add(this.instance); |
| | | // const help = new CameraHelper(this.instance); |
| | | // this.scene.add(help); |
| | | } |
| | | |
| | | setOrbitControls() { |
| | | this.controls = new OrbitControls(this.instance, this.canvas); |
| | | this.controls.target.set(0, 0, 5); |
| | | this.controls.enableDamping = true; |
| | | this.controls.minDistance = 20; |
| | | this.controls.maxDistance = 80; |
| | | this.controls.maxPolarAngle = MathUtils.degToRad(80); |
| | | // this.controls.maxPolarAngle = (-Math.PI / 2); |
| | | } |
| | | |
| | | resize() { |
| | | // 重新计算比例 |
| | | this.cameraAspect = this.sizes.width / this.sizes.height; |
| | | this.instance.updateProjectionMatrix(); |
| | | } |
| | | |
| | | |
| | | update() { |
| | | this.controls.update(); |
| | | } |
| | | |
| | | destroy() { |
| | | this.disposeObject(); |
| | | this.removeObject(); |
| | | this.resetObject(); |
| | | } |
| | | |
| | | disposeObject() { |
| | | this.controls.dispose(); |
| | | } |
| | | |
| | | removeObject() { |
| | | this.scene.remove(this.instance); |
| | | } |
| | | resetObject() { |
| | | this.controls = null; |
| | | this.instance = null; |
| | | this.scene = null; |
| | | this.canvas = null; |
| | | this.sizes = null; |
| | | } |
| | | } |
New file |
| | |
| | | import * as THREE from 'three'; |
| | | import { CSS2DRenderer } from 'three/examples/jsm/renderers/CSS2DRenderer'; |
| | | export default class CSSRenderer { |
| | | constructor(experience) { |
| | | this.experience = experience; |
| | | this.container = experience.container; |
| | | this.canvas = experience.canvas; |
| | | this.sizes = experience.sizes; |
| | | this.scene = experience.scene; |
| | | this.camera = experience.camera; |
| | | |
| | | this.setInstance(); |
| | | } |
| | | setInstance() { |
| | | this.instance = new CSS2DRenderer(); |
| | | this.instance.setSize(this.sizes.width, this.sizes.height); |
| | | this.instance.domElement.style.position = 'absolute'; |
| | | this.instance.domElement.style.top = '0px'; |
| | | this.instance.domElement.style.left = '0px'; |
| | | this.instance.domElement.style.pointerEvents = 'none'; |
| | | this.container.appendChild(this.instance.domElement); |
| | | |
| | | } |
| | | resize() { |
| | | this.instance.setSize(this.sizes.width, this.sizes.height); |
| | | this.instance.setPixelRatio(this.sizes.pixelRatio); |
| | | } |
| | | update() { |
| | | this.instance.render(this.scene, this.camera.instance); |
| | | } |
| | | |
| | | destroy() { |
| | | this.instance.domElement.remove(); |
| | | } |
| | | } |
New file |
| | |
| | | import { Scene, GridHelper, AxesHelper } from 'three'; |
| | | import Stats from "three/examples/jsm/libs/stats.module"; |
| | | |
| | | import World from "./world/world"; |
| | | import Camera from "./camera"; |
| | | import Renderer from "./renderer"; |
| | | import CSSRenderer from './cssRenderer'; |
| | | |
| | | // 工具类 |
| | | import Sizes from "./utils/sizes"; |
| | | import Time from "./utils/time"; |
| | | |
| | | export default class Experience { |
| | | constructor(canvas) { |
| | | this.canvas = canvas; |
| | | this.container = canvas.parentElement; |
| | | this.sizes = new Sizes(this.canvas); |
| | | this.time = new Time(); |
| | | this.scene = new Scene(); |
| | | this.camera = new Camera(this); |
| | | this.renderer = new Renderer(this); |
| | | this.cssRenderer = new CSSRenderer(this); |
| | | this.world = new World(this); |
| | | |
| | | // const size = 100; |
| | | // const divisions = 100; |
| | | |
| | | // const gridHelper = new GridHelper(size, divisions); |
| | | // this.scene.add(gridHelper); |
| | | |
| | | // this.stats = new Stats(); |
| | | // document.querySelector('.map-container').appendChild(this.stats.dom); |
| | | |
| | | |
| | | |
| | | // 帧 |
| | | this.time.on('tick', () => { |
| | | this.update(); |
| | | }); |
| | | } |
| | | |
| | | update() { |
| | | this.camera.update(); |
| | | this.world.update(); |
| | | this.renderer.update(); |
| | | this.cssRenderer.update(); |
| | | // this.stats.update(); |
| | | } |
| | | |
| | | /** |
| | | * 销毁场景 |
| | | */ |
| | | destroy() { |
| | | this.disposeObject(); |
| | | this.resetObject(); |
| | | } |
| | | |
| | | disposeObject() { |
| | | this.time.destroy(); |
| | | this.world.destroy(); |
| | | this.camera.destroy(); |
| | | this.renderer.destroy(); |
| | | this.cssRenderer.destroy(); |
| | | this.scene.traverse((child) => { |
| | | if (child.material) { |
| | | // 可能存在材质为数组的情况 |
| | | if (child.material instanceof Array) { |
| | | child.material.forEach((item) => item.dispose()); |
| | | } else { |
| | | child.material.dispose(); |
| | | if (child.material.map) { |
| | | child.material.map.dispose(); |
| | | } |
| | | } |
| | | } |
| | | if (child.geometry) { |
| | | child.geometry.dispose(); |
| | | child.geometry.attributes = null; // 这些属性包括position, normal, uv等等 |
| | | } |
| | | child = null; |
| | | }); |
| | | } |
| | | |
| | | resetObject() { |
| | | this.world = null; |
| | | this.camera = null; |
| | | this.renderer = null; |
| | | this.cssRenderer = null; |
| | | this.scene = null; |
| | | this.canvas = null; |
| | | this.container = null; |
| | | this.time = null; |
| | | this.sizes = null; |
| | | } |
| | | } |
New file |
| | |
| | | import * as THREE from 'three'; |
| | | export default class Renderer { |
| | | constructor(experience) { |
| | | this.experience = experience; |
| | | this.canvas = this.experience.canvas; |
| | | this.sizes = this.experience.sizes; |
| | | this.scene = this.experience.scene; |
| | | this.camera = this.experience.camera; |
| | | |
| | | this.setInstance(); |
| | | } |
| | | setInstance() { |
| | | this.instance = new THREE.WebGLRenderer({ |
| | | canvas: this.canvas, |
| | | antialias: true, |
| | | alpha: true, |
| | | logarithmicDepthBuffer: true |
| | | }); |
| | | // this.instance.toneMapping = THREE.CineonToneMapping; |
| | | // this.instance.toneMappingExposure = 1.75; |
| | | // this.instance.shadowMap.enabled = true; |
| | | // this.instance.shadowMap.type = THREE.PCFSoftShadowMap; |
| | | this.instance.setSize(this.sizes.width, this.sizes.height); |
| | | this.instance.setPixelRatio(this.sizes.pixelRatio); |
| | | } |
| | | resize() { |
| | | this.instance.setSize(this.sizes.width, this.sizes.height); |
| | | this.instance.setPixelRatio(this.sizes.pixelRatio); |
| | | } |
| | | update() { |
| | | this.instance.render(this.scene, this.camera.instance); |
| | | } |
| | | destroy() { |
| | | this.instance.dispose(); |
| | | this.instance.domElement.remove(); |
| | | } |
| | | } |
New file |
| | |
| | | export default class EventEmitter |
| | | { |
| | | constructor() |
| | | { |
| | | this.callbacks = {} |
| | | this.callbacks.base = {} |
| | | } |
| | | |
| | | on(_names, callback) |
| | | { |
| | | // Errors |
| | | if(typeof _names === 'undefined' || _names === '') |
| | | { |
| | | console.warn('wrong names') |
| | | return false |
| | | } |
| | | |
| | | if(typeof callback === 'undefined') |
| | | { |
| | | console.warn('wrong callback') |
| | | return false |
| | | } |
| | | |
| | | // Resolve names |
| | | const names = this.resolveNames(_names) |
| | | |
| | | // Each name |
| | | names.forEach((_name) => |
| | | { |
| | | // Resolve name |
| | | const name = this.resolveName(_name) |
| | | |
| | | // Create namespace if not exist |
| | | if(!(this.callbacks[ name.namespace ] instanceof Object)) |
| | | this.callbacks[ name.namespace ] = {} |
| | | |
| | | // Create callback if not exist |
| | | if(!(this.callbacks[ name.namespace ][ name.value ] instanceof Array)) |
| | | this.callbacks[ name.namespace ][ name.value ] = [] |
| | | |
| | | // Add callback |
| | | this.callbacks[ name.namespace ][ name.value ].push(callback) |
| | | }) |
| | | |
| | | return this |
| | | } |
| | | |
| | | off(_names) |
| | | { |
| | | // Errors |
| | | if(typeof _names === 'undefined' || _names === '') |
| | | { |
| | | console.warn('wrong name') |
| | | return false |
| | | } |
| | | |
| | | // Resolve names |
| | | const names = this.resolveNames(_names) |
| | | |
| | | // Each name |
| | | names.forEach((_name) => |
| | | { |
| | | // Resolve name |
| | | const name = this.resolveName(_name) |
| | | |
| | | // Remove namespace |
| | | if(name.namespace !== 'base' && name.value === '') |
| | | { |
| | | delete this.callbacks[ name.namespace ] |
| | | } |
| | | |
| | | // Remove specific callback in namespace |
| | | else |
| | | { |
| | | // Default |
| | | if(name.namespace === 'base') |
| | | { |
| | | // Try to remove from each namespace |
| | | for(const namespace in this.callbacks) |
| | | { |
| | | if(this.callbacks[ namespace ] instanceof Object && this.callbacks[ namespace ][ name.value ] instanceof Array) |
| | | { |
| | | delete this.callbacks[ namespace ][ name.value ] |
| | | |
| | | // Remove namespace if empty |
| | | if(Object.keys(this.callbacks[ namespace ]).length === 0) |
| | | delete this.callbacks[ namespace ] |
| | | } |
| | | } |
| | | } |
| | | |
| | | // Specified namespace |
| | | else if(this.callbacks[ name.namespace ] instanceof Object && this.callbacks[ name.namespace ][ name.value ] instanceof Array) |
| | | { |
| | | delete this.callbacks[ name.namespace ][ name.value ] |
| | | |
| | | // Remove namespace if empty |
| | | if(Object.keys(this.callbacks[ name.namespace ]).length === 0) |
| | | delete this.callbacks[ name.namespace ] |
| | | } |
| | | } |
| | | }) |
| | | |
| | | return this |
| | | } |
| | | |
| | | trigger(_name, _args) |
| | | { |
| | | // Errors |
| | | if(typeof _name === 'undefined' || _name === '') |
| | | { |
| | | console.warn('wrong name') |
| | | return false |
| | | } |
| | | |
| | | let finalResult = null |
| | | let result = null |
| | | |
| | | // Default args |
| | | const args = !(_args instanceof Array) ? [] : _args |
| | | |
| | | // Resolve names (should on have one event) |
| | | let name = this.resolveNames(_name) |
| | | |
| | | // Resolve name |
| | | name = this.resolveName(name[ 0 ]) |
| | | |
| | | // Default namespace |
| | | if(name.namespace === 'base') |
| | | { |
| | | // Try to find callback in each namespace |
| | | for(const namespace in this.callbacks) |
| | | { |
| | | if(this.callbacks[ namespace ] instanceof Object && this.callbacks[ namespace ][ name.value ] instanceof Array) |
| | | { |
| | | this.callbacks[ namespace ][ name.value ].forEach(function(callback) |
| | | { |
| | | result = callback.apply(this, args) |
| | | |
| | | if(typeof finalResult === 'undefined') |
| | | { |
| | | finalResult = result |
| | | } |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | |
| | | // Specified namespace |
| | | else if(this.callbacks[ name.namespace ] instanceof Object) |
| | | { |
| | | if(name.value === '') |
| | | { |
| | | console.warn('wrong name') |
| | | return this |
| | | } |
| | | |
| | | this.callbacks[ name.namespace ][ name.value ].forEach(function(callback) |
| | | { |
| | | result = callback.apply(this, args) |
| | | |
| | | if(typeof finalResult === 'undefined') |
| | | finalResult = result |
| | | }) |
| | | } |
| | | |
| | | return finalResult |
| | | } |
| | | |
| | | resolveNames(_names) |
| | | { |
| | | let names = _names |
| | | names = names.replace(/[^a-zA-Z0-9 ,/.]/g, '') |
| | | names = names.replace(/[,/]+/g, ' ') |
| | | names = names.split(' ') |
| | | |
| | | return names |
| | | } |
| | | |
| | | resolveName(name) |
| | | { |
| | | const newName = {} |
| | | const parts = name.split('.') |
| | | |
| | | newName.original = name |
| | | newName.value = parts[ 0 ] |
| | | newName.namespace = 'base' // Base namespace |
| | | |
| | | // Specified namespace |
| | | if(parts.length > 1 && parts[ 1 ] !== '') |
| | | { |
| | | newName.namespace = parts[ 1 ] |
| | | } |
| | | |
| | | return newName |
| | | } |
| | | } |
New file |
| | |
| | | /** |
| | | * 计算大小 |
| | | */ |
| | | import EventEmitter from './eventEmitter'; |
| | | export default class Sizes extends EventEmitter { |
| | | constructor(canvas) { |
| | | super(); |
| | | this.container = document.querySelector('.map-container'); |
| | | this.pixelRatio = Math.min(window.devicePixelRatio, 2); |
| | | this.width = this.container.offsetWidth; |
| | | this.height = this.container.offsetHeight; |
| | | this.device = document.body.clientWidth <= 968 ? 'mobile' : 'pc'; |
| | | // this.resizeObserver = new ResizeObserver(entries => { |
| | | // let rect = canvas.getBoundingClientRect(); |
| | | // this.scaleX = rect.width / this.width; |
| | | // this.scaleY = rect.height / this.height; |
| | | // console.log(this.scaleX, this.scaleY); |
| | | // }) |
| | | |
| | | // this.resizeObserver.observe(this.container); |
| | | // 宽高变化 |
| | | // window.addEventListener('resize', () => { |
| | | // this.pixelRatio = Math.min(window.devicePixelRatio, 2); |
| | | // this.trigger('resize'); |
| | | |
| | | // if (this.width < 968 && this.device !== 'mobile') { |
| | | // this.device = 'mobile'; |
| | | // this.trigger('devicechange'); |
| | | // } else if (this.width >= 968 && this.device !== 'pc') { |
| | | // this.device = 'pc'; |
| | | // this.trigger('devicechange'); |
| | | // } |
| | | // }); |
| | | } |
| | | } |
New file |
| | |
| | | import EventEmitter from "./eventEmitter"; |
| | | export default class Time extends EventEmitter { |
| | | constructor() { |
| | | super(); |
| | | this.start = Date.now(); |
| | | this.current = this.start; |
| | | this.elapsed = 0; |
| | | this.delta = 16; |
| | | // 合适的时机执行loop循环 |
| | | window.requestAnimationFrame(() => { |
| | | this.tick(); |
| | | }); |
| | | } |
| | | |
| | | tick() { |
| | | const currentTime = Date.now(); |
| | | this.delta = currentTime - this.current; |
| | | this.current = currentTime; |
| | | this.elapsed = this.current - this.start; |
| | | this.trigger('tick'); |
| | | |
| | | this.loopId = window.requestAnimationFrame(() => { |
| | | this.tick(); |
| | | }); |
| | | } |
| | | |
| | | destroy() { |
| | | window.cancelAnimationFrame(this.loopId); |
| | | this.off('tick'); |
| | | } |
| | | } |
New file |
| | |
| | | import * as THREE from 'three'; |
| | | import rotatingAperture from '@/assets/map/texture/rotatingAperture.png'; |
| | | import rotatingPoint from '@/assets/map/texture/rotating-point2.png'; |
| | | import circlePoint from '@/assets/map/texture/circle-point.png'; |
| | | import sceneBg from '@/assets/map/texture/scene-bg2.png'; |
| | | |
| | | import { GUI } from "three/examples/jsm/libs/lil-gui.module.min.js"; |
| | | |
| | | export default class Enviroment { |
| | | constructor(experience) { |
| | | this.experience = experience; |
| | | this.scene = this.experience.scene; |
| | | this.textureLoader = new THREE.TextureLoader(); |
| | | |
| | | this.setSunLight(); |
| | | this.setRotateHola(); |
| | | this.setBackground(); |
| | | this.setCirclePoint(); |
| | | |
| | | // this.debuger(); |
| | | } |
| | | setSunLight() { |
| | | // 平行光1 |
| | | this.directionalLight1 = new THREE.DirectionalLight(0xffffff, 0.9); |
| | | this.directionalLight1.position.set(0, 57, 33); |
| | | // 平行光2 |
| | | this.directionalLight2 = new THREE.DirectionalLight(0xffffff, 0.6); |
| | | this.directionalLight2.position.set(-95, 28, -33); |
| | | // 环境光 |
| | | this.ambientLight = new THREE.AmbientLight(0xffffff, 0.8); |
| | | |
| | | this.scene.add(this.directionalLight1); |
| | | this.scene.add(this.directionalLight2); |
| | | this.scene.add(this.ambientLight); |
| | | } |
| | | |
| | | setRotateHola() { |
| | | const rotatingApertureTexture = this.textureLoader.load(rotatingAperture); |
| | | const rotatingPointTexture = this.textureLoader.load(rotatingPoint); |
| | | const meshConfig1 = { |
| | | width: 48, |
| | | height: 48, |
| | | texture: rotatingApertureTexture, |
| | | positionList: [0, 0.4, 0], |
| | | scaleList: [1, 1, 1], |
| | | rotateList: [-Math.PI / 2, 0, 0] |
| | | }; |
| | | const meshConfig2 = { |
| | | width: 40, |
| | | height: 40, |
| | | texture: rotatingPointTexture, |
| | | positionList: [0, 0.3, 0], |
| | | scaleList: [1, 1, 1], |
| | | rotateList: [-Math.PI / 2, 0, 0] |
| | | }; |
| | | this.hola1 = this.createMesh(meshConfig1); |
| | | this.hola2 = this.createMesh(meshConfig2); |
| | | this.scene.add(this.hola1); |
| | | this.scene.add(this.hola2); |
| | | } |
| | | |
| | | setBackground() { |
| | | const sceneBgTexture = this.textureLoader.load(sceneBg); |
| | | const plane = new THREE.PlaneGeometry(120, 120); |
| | | const material = new THREE.MeshPhongMaterial({ |
| | | // color: 0x061920, |
| | | color: 0xffffff, |
| | | map: sceneBgTexture, |
| | | transparent: true, |
| | | opacity: 1, |
| | | // depthTest: true |
| | | }); |
| | | this.background = new THREE.Mesh(plane, material); |
| | | this.background.rotation.set(-Math.PI / 2, 0, 0); |
| | | this.background.position.set(0, 0.1, 0); |
| | | this.scene.add(this.background); |
| | | } |
| | | |
| | | setCirclePoint() { |
| | | const circleTexture = this.textureLoader.load(circlePoint); |
| | | const plane = new THREE.PlaneGeometry(45, 45); |
| | | const material = new THREE.MeshPhongMaterial({ |
| | | color: 0x00ffff, |
| | | map: circleTexture, |
| | | transparent: true, |
| | | opacity: 1, |
| | | depthTest: false, |
| | | }); |
| | | this.circle = new THREE.Mesh(plane, material); |
| | | this.circle.rotation.set(-Math.PI / 2, 0, 0); |
| | | this.circle.position.set(0, 0.2, 0); |
| | | this.scene.add(this.circle); |
| | | } |
| | | |
| | | createMesh(config) { |
| | | let { width, height, texture, positionList, rotateList, scaleList } = config; |
| | | let plane = new THREE.PlaneGeometry(width, height); |
| | | let material = new THREE.MeshBasicMaterial({ |
| | | map: texture, |
| | | transparent: true, |
| | | opacity: 1, |
| | | depthTest: false, |
| | | }); |
| | | let mesh = new THREE.Mesh(plane, material); |
| | | mesh.position.set(...positionList); |
| | | mesh.scale.set(...scaleList); |
| | | mesh.rotation.set(...rotateList); |
| | | return mesh; |
| | | } |
| | | |
| | | update() { |
| | | if (this.hola1) { |
| | | this.hola1.rotation.z += 0.001; |
| | | } |
| | | if (this.hola2) { |
| | | this.hola2.rotation.z -= 0.001; |
| | | } |
| | | } |
| | | |
| | | destroy() { |
| | | this.disposeObject(); |
| | | this.removeObject(); |
| | | this.resetObject(); |
| | | } |
| | | |
| | | disposeObject() { |
| | | this.hola1.geometry.dispose(); |
| | | this.hola1.material.dispose(); |
| | | this.hola2.geometry.dispose(); |
| | | this.hola2.material.dispose(); |
| | | this.background.geometry.dispose(); |
| | | this.background.material.dispose(); |
| | | this.circle.geometry.dispose(); |
| | | this.circle.material.dispose(); |
| | | this.directionalLight1.dispose(); |
| | | this.directionalLight2.dispose(); |
| | | this.ambientLight.dispose(); |
| | | } |
| | | |
| | | removeObject() { |
| | | this.scene.remove(this.hola1); |
| | | this.scene.remove(this.hola2); |
| | | this.scene.remove(this.background); |
| | | this.scene.remove(this.circle); |
| | | } |
| | | |
| | | resetObject() { |
| | | this.hola1 = null; |
| | | this.hola2 = null; |
| | | this.background = null; |
| | | this.circle = null; |
| | | this.directionalLight1 = null; |
| | | this.directionalLight2 = null; |
| | | this.ambientLight = null; |
| | | } |
| | | |
| | | debuger() { |
| | | const gui = new GUI(); |
| | | |
| | | const folder1 = gui.addFolder('平行光1'); |
| | | const folder2 = gui.addFolder('平行光2'); |
| | | const folder3 = gui.addFolder('环境光'); |
| | | |
| | | folder1.add(this.directionalLight1.position, 'x').min(-200).max(200).step(1).name("x轴的位置"); |
| | | folder1.add(this.directionalLight1.position, 'y').min(-200).max(200).step(1).name("y轴的位置"); |
| | | folder1.add(this.directionalLight1.position, 'z').min(-200).max(200).step(1).name("z轴的位置"); |
| | | folder1.add(this.directionalLight1, 'intensity').min(0).max(1).step(0.1).name("强度"); |
| | | |
| | | folder2.add(this.directionalLight2.position, 'x').min(-200).max(200).step(1).name("x轴的位置"); |
| | | folder2.add(this.directionalLight2.position, 'y').min(-200).max(200).step(1).name("y轴的位置"); |
| | | folder2.add(this.directionalLight2.position, 'z').min(-200).max(200).step(1).name("z轴的位置"); |
| | | folder2.add(this.directionalLight2, 'intensity').min(0).max(1).step(0.1).name("强度"); |
| | | |
| | | |
| | | folder3.add(this.ambientLight, 'intensity').min(0).max(1).step(0.1).name("强度"); |
| | | } |
| | | } |
New file |
| | |
| | | import * as THREE from 'three'; |
| | | import * as d3 from 'd3'; |
| | | import mapData from '@/assets/map/zigong2.json'; |
| | | import { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer'; |
| | | |
| | | import textureMapImage from '@/assets/map/texture/gz-map.jpg'; |
| | | import textureMapFxImage from '@/assets/map/texture/gz-map-fx.jpg'; |
| | | |
| | | import gsap from 'gsap'; |
| | | |
| | | // 地图深度 |
| | | const MAP_DEPTH = 0.2; |
| | | |
| | | const projection = d3.geoMercator().center([104.779307, 29.33924]).translate([0, 0, 0]); |
| | | |
| | | const raycaster = new THREE.Raycaster(); |
| | | |
| | | export default class Map { |
| | | constructor(experience) { |
| | | this.experience = experience; |
| | | this.scene = experience.scene; |
| | | this.camera = experience.camera; |
| | | |
| | | this.provinceMeshList = []; |
| | | this.labelList = []; |
| | | this.textureLoader = new THREE.TextureLoader(); |
| | | this.setTexture(); |
| | | this.operationData(mapData); |
| | | setTimeout(() => { |
| | | this.enterAnimation(); |
| | | }, 500); |
| | | } |
| | | setTexture() { |
| | | const textureMap = this.textureLoader.load(textureMapImage); |
| | | const textureMapFx = this.textureLoader.load(textureMapFxImage); |
| | | textureMap.wrapS = textureMapFx.wrapS = THREE.RepeatWrapping; |
| | | textureMap.wrapT = textureMapFx.wrapT = THREE.RepeatWrapping; |
| | | textureMap.flipY = textureMapFx.flipY = false; |
| | | textureMap.rotation = textureMapFx.rotation = THREE.MathUtils.degToRad(45); |
| | | const scale = 0.128; |
| | | textureMap.repeat.set(scale, scale); |
| | | textureMapFx.repeat.set(scale, scale); |
| | | this.topFaceMaterial = new THREE.MeshPhongMaterial({ |
| | | map: textureMap, |
| | | // color: 0xb4eeea, |
| | | color: 0xb3fffa, |
| | | combine: THREE.MultiplyOperation, |
| | | transparent: true, |
| | | opacity: 1, |
| | | }); |
| | | this.sideMaterial = new THREE.MeshLambertMaterial({ |
| | | color: 0x123024, |
| | | transparent: true, |
| | | opacity: 0.9, |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * 解析json数据,并绘制地图多边形 |
| | | * @param {*} jsondata 地图数据 |
| | | */ |
| | | operationData(jsondata) { |
| | | this.map = new THREE.Group(); |
| | | |
| | | // geo信息 |
| | | const features = jsondata.features; |
| | | features.forEach((feature) => { |
| | | // 单个省份 对象 |
| | | const province = new THREE.Object3D(); |
| | | // 地址 |
| | | province.properties = feature.properties.name; |
| | | province.isHover = false; |
| | | // 多个情况 |
| | | // console.log(feature.geometry.type); |
| | | if (feature.geometry.type === "MultiPolygon") { |
| | | feature.geometry.coordinates.forEach((coordinate) => { |
| | | coordinate.forEach((rows) => { |
| | | const line = this.drawBoundary(rows); |
| | | const mesh = this.drawExtrudeMesh(rows); |
| | | province.add(line); |
| | | province.add(mesh); |
| | | this.provinceMeshList.push(mesh); |
| | | }); |
| | | }); |
| | | } |
| | | |
| | | // 单个情况 |
| | | if (feature.geometry.type === "Polygon") { |
| | | feature.geometry.coordinates.forEach((coordinate) => { |
| | | const line = this.drawBoundary(coordinate); |
| | | const mesh = this.drawExtrudeMesh(coordinate); |
| | | province.add(line); |
| | | province.add(mesh); |
| | | this.provinceMeshList.push(mesh); |
| | | }); |
| | | } |
| | | const label = this.drawLabelText(feature); |
| | | this.labelList.push({ name: feature.properties.name, label }); |
| | | province.add(label); |
| | | this.map.add(province); |
| | | }); |
| | | this.map.position.set(1, 1, -1.5); |
| | | this.map.scale.set(10, 10, 1); |
| | | this.map.rotation.set(THREE.MathUtils.degToRad(-90), 0, THREE.MathUtils.degToRad(20)); |
| | | this.scene.add(this.map); |
| | | |
| | | this.setMouseEvent(); |
| | | } |
| | | |
| | | /** |
| | | * 画区域分界线 |
| | | * @param {*} polygon 区域坐标点数组 |
| | | * @returns 区域分界线 |
| | | */ |
| | | drawBoundary(polygon) { |
| | | const points = []; |
| | | for (let i = 0; i < polygon.length; i++) { |
| | | const [x, y] = projection(polygon[i]); |
| | | points.push(new THREE.Vector3(x, -y, 0)); |
| | | } |
| | | const lineGeometry = new THREE.BufferGeometry().setFromPoints(points); |
| | | const lineMaterial = new THREE.LineBasicMaterial({ |
| | | color: 0xffffff, |
| | | linewidth: 2, |
| | | transparent: true, |
| | | depthTest: false, |
| | | }); |
| | | const line = new THREE.Line(lineGeometry, lineMaterial); |
| | | line.translateZ(MAP_DEPTH + 0.001); |
| | | return line; |
| | | } |
| | | /** |
| | | * 绘制区域多边形 |
| | | * @param {*} polygon 区域坐标点数组 |
| | | * @returns 区域多边形 |
| | | */ |
| | | drawExtrudeMesh(polygon) { |
| | | const shape = new THREE.Shape(); |
| | | for (let i = 0; i < polygon.length; i++) { |
| | | const [x, y] = projection(polygon[i]); |
| | | if (i === 0) { |
| | | shape.moveTo(x, -y); |
| | | } |
| | | shape.lineTo(x, -y); |
| | | } |
| | | const geometry = new THREE.ExtrudeGeometry(shape, { |
| | | depth: MAP_DEPTH, |
| | | bevelEnabled: false, |
| | | bevelSegments: 1, |
| | | bevelThickness: 0.1, |
| | | }); |
| | | return new THREE.Mesh(geometry, [ |
| | | this.topFaceMaterial, |
| | | this.sideMaterial, |
| | | ]); |
| | | } |
| | | |
| | | drawLabelText(province) { |
| | | const [x, y] = projection(province.properties.center); |
| | | const div = document.createElement('div'); |
| | | div.innerHTML = province.properties.name; |
| | | div.style.padding = '4px 10px'; |
| | | div.style.color = '#fff'; |
| | | div.style.fontSize = '16px'; |
| | | div.style.position = 'absolute'; |
| | | div.style.backgroundColor = 'rgba(25,25,25,0.5)'; |
| | | div.style.borderRadius = '5px'; |
| | | const label = new CSS2DObject(div); |
| | | div.style.pointerEvents = 'none'; |
| | | label.position.set(x, y, MAP_DEPTH + 0.05); |
| | | return label; |
| | | } |
| | | |
| | | |
| | | setMouseEvent() { |
| | | this.mouseEvent = this.handleEvent.bind(this); |
| | | this.experience.canvas.addEventListener("mousemove", this.mouseEvent); |
| | | } |
| | | |
| | | removeMouseEvent() { |
| | | this.experience.canvas.removeEventListener("mousemove", this.mouseEvent); |
| | | } |
| | | |
| | | handleEvent(e) { |
| | | // console.log(this); |
| | | // return; |
| | | if (this.map) { |
| | | let mouse = new THREE.Vector2(); |
| | | let getBoundingClientRect = this.experience.canvas.getBoundingClientRect(); |
| | | let x = ((e.clientX - getBoundingClientRect.left) / getBoundingClientRect.width) * 2 - 1; |
| | | let y = -((e.clientY - getBoundingClientRect.top) / getBoundingClientRect.height) * 2 + 1; |
| | | mouse.x = x; |
| | | mouse.y = y; |
| | | |
| | | raycaster.setFromCamera(mouse, this.camera.instance); |
| | | |
| | | let intersects = raycaster.intersectObjects(this.provinceMeshList, false); |
| | | |
| | | if (intersects.length) { |
| | | let temp = intersects[0].object; |
| | | this.animation(temp.parent); |
| | | this.showLabel(temp.parent); |
| | | } else { |
| | | this.animation(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | throttle(callback, delay) { |
| | | let lastCall = 0; |
| | | return function () { |
| | | let now = new Date().getTime(); |
| | | if (now - lastCall >= delay) { |
| | | lastCall = now; |
| | | callback.apply(null, arguments); |
| | | } |
| | | }; |
| | | } |
| | | |
| | | animation(province) { |
| | | if (province) { |
| | | if (!province.isHover) { |
| | | province.isHover = true; |
| | | this.map.children.forEach((item) => { |
| | | if (item.properties === province.properties) { |
| | | gsap.to(province.position, { |
| | | z: 0.12, |
| | | duration: 0.6 |
| | | }) |
| | | } else { |
| | | this.resetAnimation(item); |
| | | } |
| | | }) |
| | | } |
| | | } else { |
| | | this.resetAllAnimation(); |
| | | } |
| | | |
| | | } |
| | | |
| | | resetAnimation(province) { |
| | | gsap.to(province.position, { |
| | | z: 0, |
| | | duration: 0.6, |
| | | onComplete: () => { |
| | | province.isHover = false; |
| | | } |
| | | }) |
| | | } |
| | | |
| | | resetAllAnimation() { |
| | | this.map.children.forEach((item) => { |
| | | this.resetAnimation(item); |
| | | }) |
| | | } |
| | | |
| | | showLabel(province) { |
| | | this.labelList.forEach((item) => { |
| | | // if (item.name === province.properties) { |
| | | // item.label.element.style.visibility = 'visible'; |
| | | // } else { |
| | | // item.label.element.style.visibility = 'hidden'; |
| | | // } |
| | | }) |
| | | } |
| | | |
| | | enterAnimation() { |
| | | gsap.to(this.map.scale, { |
| | | z: 10, |
| | | duration: 0.6, |
| | | ease: 'power1.out' |
| | | }) |
| | | } |
| | | |
| | | destroy() { |
| | | this.removeMouseEvent(); |
| | | this.disposeObject(); |
| | | this.removeObject(); |
| | | this.resetObject(); |
| | | } |
| | | |
| | | disposeObject() { |
| | | this.map.traverse((child) => { |
| | | if (child.material) { |
| | | // 可能存在材质为数组的情况 |
| | | if (child.material instanceof Array) { |
| | | child.material.forEach((item) => item.dispose()); |
| | | } else { |
| | | child.material.dispose(); |
| | | if (child.material.map) { |
| | | child.material.map.dispose(); |
| | | } |
| | | } |
| | | } |
| | | if (child.geometry) { |
| | | child.geometry.dispose(); |
| | | child.geometry.attributes = null; // 这些属性包括position, normal, uv等等 |
| | | } |
| | | child = null; |
| | | }); |
| | | this.topFaceMaterial.dispose(); |
| | | this.sideMaterial.dispose(); |
| | | } |
| | | |
| | | removeObject() { |
| | | this.scene.remove(this.map); |
| | | } |
| | | |
| | | resetObject() { |
| | | this.map = null; |
| | | this.provinceMeshList = null; |
| | | this.labelList = null; |
| | | this.textureLoader = null; |
| | | } |
| | | } |
New file |
| | |
| | | import EventEmitter from '../utils/eventEmitter'; |
| | | import Enviroment from './enviroment'; |
| | | import Map from './map'; |
| | | |
| | | export default class World extends EventEmitter { |
| | | constructor(experience) { |
| | | super(); |
| | | this.experience = experience; |
| | | this.scene = this.experience.scene; |
| | | this.enviroment = new Enviroment(this.experience); |
| | | this.map = new Map(this.experience); |
| | | } |
| | | |
| | | update() { |
| | | this.enviroment.update(); |
| | | } |
| | | destroy() { |
| | | this.enviroment.destroy(); |
| | | this.map.destroy(); |
| | | } |
| | | } |
New file |
| | |
| | | <template> |
| | | <div class="map-container"> |
| | | <canvas class="world" ref="worldContainer"></canvas> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import Experience from './experience/index'; |
| | | let world = null; |
| | | export default { |
| | | name: 'ScreenMapThree', |
| | | props: { |
| | | loadEnd: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | }, |
| | | watch: { |
| | | loadEnd: { |
| | | handler(newVal) { |
| | | if (newVal) { |
| | | world = new Experience(this.$refs.worldContainer); |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | mounted() { |
| | | |
| | | }, |
| | | beforeDestroy() { |
| | | world.destroy(); |
| | | world = null; |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .map-container { |
| | | width: 100%; |
| | | height: 100%; |
| | | position: absolute; |
| | | left: 0; |
| | | top: 0; |
| | | z-index: 0; |
| | | |
| | | .world { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | } |
| | | </style> |
| | |
| | | <script> |
| | | import * as echarts from 'echarts'; |
| | | import 'echarts-gl'; |
| | | import mapData from '@/assets/map/zigong1.json'; |
| | | import mapData from '@/assets/map/zigong2.json'; |
| | | import WrapperTitle from '../wrapper-title/index'; |
| | | import ScreenData from '../screen-data/index'; |
| | | |
| | |
| | | 返回 |
| | | </div> |
| | | <div class="wrapper-content"> |
| | | <screen-map-three :loadEnd="isEnd"></screen-map-three> |
| | | <div class="left-container wrapper"> |
| | | <screen-face class="enter-left" :class="{ 'animate-enter-x': isEnd }"></screen-face> |
| | | <screen-car class="enter-left animate-delay-1" :class="{ 'animate-enter-x': isEnd }"></screen-car> |
| | | <screen-video class="enter-left animate-delay-2" :class="{ 'animate-enter-x': isEnd }"></screen-video> |
| | | </div> |
| | | <div class="center-container center-wrapper"> |
| | | <screen-map></screen-map> |
| | | <screen-map-cover></screen-map-cover> |
| | | <screen-table class="enter-top" :class="{ 'animate-enter-y': isEnd }"></screen-table> |
| | | <!-- <screen-detection></screen-detection> --> |
| | | |
| | |
| | | import ScreenFace from '../screen-face/index'; |
| | | import ScreenVideo from '../screen-video/index'; |
| | | import ScreenCar from '../screen-car/index'; |
| | | import ScreenMap from '../screen-map/index'; |
| | | import ScreenMapCover from '../screen-map-cover/index'; |
| | | import ScreenTable from '../screen-table/index'; |
| | | import ScreenMapThree from '../screen-map-three/index'; |
| | | import ScreenData from '../screen-data/index'; |
| | | |
| | | export default { |
| | | name: 'ScreenWrapper', |
| | | components: { |
| | | SelectItem, |
| | | ScreenExamine, |
| | | ScreenMap, |
| | | ScreenTable, |
| | | ScreenMapCover, |
| | | ScreenMapThree, |
| | | ScreenFace, |
| | | ScreenVideo, |
| | | ScreenCar, |
| | |
| | | }, |
| | | data() { |
| | | return { |
| | | isEnd: false |
| | | isEnd: false, |
| | | } |
| | | }, |
| | | methods: { |
| | |
| | | const container = document.querySelector('.screen-wrapper'); |
| | | container.addEventListener('transitionend', this.checkAnimationEnd); |
| | | }, |
| | | destroyed() { |
| | | beforDestroy() { |
| | | const container = document.querySelector('.screen-wrapper'); |
| | | container.removeEventListener('transitionend', this.checkAnimationEnd); |
| | | } |
| | |
| | | flex-direction: column; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .animate-enter-x { |
| | | animation: enter-x 0.4s ease forwards; |
| | | } |
| | | |
| | | .animate-enter-y { |
| | | animation: enter-y 0.4s ease forwards; |
| | | } |
| | | |
| | | .enter-left { |
| | | transform: translateX(-100px); |
| | | opacity: 0; |
| | | } |
| | | |
| | | .enter-right { |
| | | transform: translateX(100px); |
| | | opacity: 0; |
| | | } |
| | | |
| | | .enter-top { |
| | | transform: translateY(100px); |
| | | opacity: 0; |
| | | } |
| | | |
| | | .animate-delay-1 { |
| | | animation-delay: 0.1s; |
| | | } |
| | |
| | | } |
| | | |
| | | @keyframes enter-x { |
| | | 100% { |
| | | from { |
| | | opacity: 0; |
| | | } |
| | | |
| | | to { |
| | | opacity: 1; |
| | | transform: translateX(0); |
| | | } |
| | | } |
| | | |
| | | @keyframes enter-y { |
| | | 100% { |
| | | from { |
| | | opacity: 0; |
| | | } |
| | | |
| | | to { |
| | | opacity: 1; |
| | | transform: translateY(0); |
| | | } |
| | |
| | | <template> |
| | | <div class="screen-container"> |
| | | |
| | | <screen-title></screen-title> |
| | | <v-scale-screen width="1920" height="1080" :autoScale="true" :delay="0" class="screen"> |
| | | <screen-wrapper></screen-wrapper> |
| | |
| | | <script> |
| | | import ScreenTitle from './components/screen-title/index.vue'; |
| | | import ScreenWrapper from './components/screen-wrapper/index.vue'; |
| | | |
| | | |
| | | export default { |
| | | name: 'App', |
| | |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .screen-container { |
| | | user-select: none; |
| | | -webkit-user-select: none; |
| | | } |
| | | .screen { |
| | | background: url('../../assets/images/screen/pageBg1.jpg') !important; |
| | | background-size: cover !important; |
| | |
| | | icon="el-icon-delete" |
| | | size="mini" |
| | | :disabled="multiple" |
| | | v-hasPermi="['system:result:remove']" |
| | | @click="handleDelete" |
| | | >删除</el-button> |
| | | </el-col> |
| | |
| | | plain |
| | | icon="el-icon-download" |
| | | size="mini" |
| | | v-hasPermi="['system:result:export']" |
| | | @click="handleExport" |
| | | >导出</el-button> |
| | | </el-col> |
| | |
| | | type="text" |
| | | icon="el-icon-edit" |
| | | @click="handleUpdate(scope.row)" |
| | | v-hasPermi="['calculate:rule:edit']" |
| | | >修改</el-button> |
| | | <el-button |
| | | size="mini" |
| | | type="text" |
| | | icon="el-icon-plus" |
| | | @click="handleAdd(scope.row)" |
| | | v-hasPermi="['calculate:rule:add']" |
| | | >新增</el-button> |
| | | <el-button |
| | | size="mini" |
| | | type="text" |
| | | icon="el-icon-delete" |
| | | @click="handleDelete(scope.row)" |
| | | v-hasPermi="['calculate:rule:remove']" |
| | | >删除</el-button> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | icon="el-icon-download" |
| | | size="mini" |
| | | @click="handleExport" |
| | | v-hasPermi="['system:monitor:export']" |
| | | >导出</el-button> |
| | | </el-col> |
| | | <right-toolbar :showSearch.sync="showSearch" @queryTable="getList" :columns="columns"></right-toolbar> |
| | |
| | | plain |
| | | icon="el-icon-plus" |
| | | size="mini" |
| | | v-hasPermi="['system:contract:add']" |
| | | @click="handleAdd" |
| | | >新增</el-button> |
| | | </el-col> |
| | |
| | | plain |
| | | icon="el-icon-top" |
| | | size="mini" |
| | | v-hasPermi="['system:contract:import']" |
| | | @click="handleImportPoint" |
| | | >导入</el-button> |
| | | </el-col> |
| | |
| | | icon="el-icon-download" |
| | | size="mini" |
| | | @click="handleExport" |
| | | v-hasPermi="['system:monitor:export']" |
| | | >导出</el-button> |
| | | </el-col> |
| | | <right-toolbar :showSearch.sync="showSearch" @queryTable="getList" :columns="columns"></right-toolbar> |
| | |
| | | size="mini" |
| | | :disabled="single" |
| | | @click="handleUpdate" |
| | | v-hasPermi="['point:edit']" |
| | | >修改</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | |
| | | size="mini" |
| | | :disabled="multiple" |
| | | @click="handleDelete" |
| | | v-hasPermi="['point:remove']" |
| | | >删除</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | |
| | | icon="el-icon-top" |
| | | size="mini" |
| | | @click="handleImportPoint" |
| | | v-hasPermi="['point:import']" |
| | | >导入点位</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | |
| | | icon="el-icon-receiving" |
| | | size="mini" |
| | | @click="handleEditBatch" |
| | | v-hasPermi="['point:edit']" |
| | | >批量修改</el-button> |
| | | </el-col> |
| | | <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> |
| | |
| | | type="text" |
| | | icon="el-icon-edit" |
| | | @click="handleUpdate(scope.row)" |
| | | v-hasPermi="['point:edit']" |
| | | >修改</el-button> |
| | | <el-button |
| | | size="mini" |
| | | type="text" |
| | | icon="el-icon-delete" |
| | | @click="handleDelete(scope.row)" |
| | | v-hasPermi="['point:remove']" |
| | | >删除</el-button> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | icon="el-icon-plus" |
| | | size="mini" |
| | | @click="handleAdd" |
| | | v-hasPermi="['system:report:add']" |
| | | >新增</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | |
| | | size="mini" |
| | | :disabled="single" |
| | | @click="handleUpdate" |
| | | v-hasPermi="['system:report:edit']" |
| | | >修改</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | |
| | | size="mini" |
| | | :disabled="multiple" |
| | | @click="handleDelete" |
| | | v-hasPermi="['system:report:remove']" |
| | | >删除</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | |
| | | icon="el-icon-download" |
| | | size="mini" |
| | | @click="handleExport" |
| | | v-hasPermi="['system:report:export']" |
| | | >导出</el-button> |
| | | </el-col> |
| | | <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> |
| | |
| | | type="text" |
| | | icon="el-icon-edit" |
| | | @click="handleUpdate(scope.row)" |
| | | v-hasPermi="['system:report:edit']" |
| | | >修改</el-button> |
| | | <el-button |
| | | size="mini" |
| | | type="text" |
| | | icon="el-icon-delete" |
| | | @click="handleDelete(scope.row)" |
| | | v-hasPermi="['system:report:remove']" |
| | | >删除</el-button> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | icon="el-icon-plus" |
| | | size="mini" |
| | | @click="handleAdd" |
| | | v-hasPermi="['system:report:add']" |
| | | >新增</el-button> |
| | | </el-col> |
| | | <!-- <el-col :span="1.5">--> |
| | |
| | | size="mini" |
| | | :disabled="multiple" |
| | | @click="handleDelete" |
| | | v-hasPermi="['system:report:remove']" |
| | | >删除</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | |
| | | icon="el-icon-download" |
| | | size="mini" |
| | | @click="handleExport" |
| | | v-hasPermi="['system:report:export']" |
| | | >导出</el-button> |
| | | </el-col> |
| | | <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> |
| | |
| | | type="text" |
| | | icon="el-icon-edit" |
| | | @click="handleAuditing(scope.row)" |
| | | v-hasPermi="['system:report:audit']" |
| | | v-hasPermi="['system:report:edit']" |
| | | v-if="scope.row.status === 0" |
| | | >审核</el-button> |
| | | <el-button |
| | |
| | | |
| | | </div> |
| | | <div class="bottom-publish"> |
| | | <el-button size="medium" type="success">发布</el-button> |
| | | <el-button size="medium" @click="jumpDetail" type="info">详情</el-button> |
| | | <el-button size="medium" v-hasPermi="['calculate:rule:add']" type="success">发布</el-button> |
| | | <el-button size="medium" v-hasPermi="['calculate:rule:query']" @click="jumpDetail" type="info">详情</el-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | type="text" |
| | | icon="el-icon-edit" |
| | | @click="handleUpdate(scope.row)" |
| | | v-hasPermi="['system:rule:edit']" |
| | | >修改</el-button> |
| | | <el-button |
| | | size="mini" |
| | | type="text" |
| | | icon="el-icon-plus" |
| | | @click="handleAdd(scope.row)" |
| | | v-hasPermi="['system:rule:add']" |
| | | >新增</el-button> |
| | | <el-button |
| | | size="mini" |
| | | type="text" |
| | | icon="el-icon-delete" |
| | | @click="handleDelete(scope.row)" |
| | | v-hasPermi="['system:rule:remove']" |
| | | >删除</el-button> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | icon="el-icon-plus" |
| | | size="mini" |
| | | @click="handleAdd" |
| | | v-hasPermi="['system:template:add']" |
| | | >新增</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | |
| | | size="mini" |
| | | :disabled="single" |
| | | @click="handleUpdate" |
| | | v-hasPermi="['system:template:edit']" |
| | | >修改</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | |
| | | size="mini" |
| | | :disabled="multiple" |
| | | @click="handleDelete" |
| | | v-hasPermi="['system:template:remove']" |
| | | >删除</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | |
| | | icon="el-icon-download" |
| | | size="mini" |
| | | @click="handleExport" |
| | | v-hasPermi="['system:auditing:export']" |
| | | v-hasPermi="['system:template:export']" |
| | | >导出</el-button> |
| | | </el-col> |
| | | <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> |
| | |
| | | icon="el-icon-plus" |
| | | size="mini" |
| | | @click="handleAdd" |
| | | v-hasPermi="['platform:template:add']" |
| | | >新增</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | |
| | | icon="el-icon-edit" |
| | | size="mini" |
| | | :disabled="single" |
| | | v-hasPermi="['platform:template:edit']" |
| | | @click="handleUpdate" |
| | | >修改</el-button> |
| | | </el-col> |
| | |
| | | icon="el-icon-delete" |
| | | size="mini" |
| | | :disabled="multiple" |
| | | v-hasPermi="['platform:template:remove']" |
| | | @click="handleDelete" |
| | | >删除</el-button> |
| | | </el-col> |
| | |
| | | plain |
| | | icon="el-icon-download" |
| | | size="mini" |
| | | v-hasPermi="['platform:template:export']" |
| | | @click="handleExport" |
| | | >导出</el-button> |
| | | </el-col> |
| | |
| | | type="text" |
| | | icon="el-icon-edit" |
| | | @click="handleUpdate(scope.row)" |
| | | v-hasPermi="['platform:template:edit']" |
| | | >修改</el-button> |
| | | <el-button |
| | | size="mini" |
| | | type="text" |
| | | icon="el-icon-delete" |
| | | @click="handleDelete(scope.row)" |
| | | v-hasPermi="['platform:template:remove']" |
| | | >删除</el-button> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | <el-table-column type="selection" width="55" align="center"/> |
| | | <el-table-column label="设备类型" align="center" prop="monitorType"> |
| | | <template slot-scope="scope"> |
| | | <span v-show="scope.row['monitorType'] === '1'">人脸</span> |
| | | <span v-show="scope.row['monitorType'] === '2'">车辆</span> |
| | | <span v-show="scope.row['monitorType'] === '3'">视频</span> |
| | | <span v-show="scope.row['monitorType'] === 'face'">人脸</span> |
| | | <span v-show="scope.row['monitorType'] === 'car'">车辆</span> |
| | | <span v-show="scope.row['monitorType'] === 'video'">视频</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="超时天数" align="center" prop="timeout"/> |
| | | <el-table-column label="工单阈值" align="center" prop="indicator"> |
| | | <template slot-scope="scope"> |
| | | <div v-for="item in JSON.parse(scope.row.indicator)" :key="item" style="display: flex;flex-direction: row"> |
| | | <div style="width: 120px;text-align: right">{{ item.label }}</div> |
| | | <div style="width: 60px;text-align: right">{{ item.value}}</div> |
| | | <div class="table-row" style="display: flex;flex-direction: row"> |
| | | <div class="table-row-item">图像质量</div> |
| | | <div class="table-row-item">{{ scope.row.imageQuality }}</div> |
| | | </div> |
| | | <div class="table-row" style="display: flex;flex-direction: row"> |
| | | <div class="table-row-item">视频质量</div> |
| | | <div class="table-row-item">{{ scope.row.videoQuality }}</div> |
| | | </div> |
| | | <div class="table-row" style="display: flex;flex-direction: row"> |
| | | <div class="table-row-item">标注准确率</div> |
| | | <div class="table-row-item">{{ scope.row.annotationAccuracy }}</div> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="下发阈值" align="center" prop="indicator"> |
| | | <template slot-scope="scope"> |
| | | <div v-for="item in JSON.parse(scope.row.indicator)" :key="item" style="display: flex;flex-direction: row"> |
| | | <div style="width: 120px;text-align: right">{{ item.label }}</div> |
| | | <div style="width: 60px;text-align: right">{{ item.value2}}</div> |
| | | <div class="table-row" style="display: flex;flex-direction: row"> |
| | | <div class="table-row-item">图像质量</div> |
| | | <div class="table-row-item">{{ scope.row.imageQualityAuto }}</div> |
| | | </div> |
| | | <div class="table-row" style="display: flex;flex-direction: row"> |
| | | <div class="table-row-item">视频质量</div> |
| | | <div class="table-row-item">{{ scope.row.videoQualityAuto }}</div> |
| | | </div> |
| | | <div class="table-row" style="display: flex;flex-direction: row"> |
| | | <div class="table-row-item">标注准确率</div> |
| | | <div class="table-row-item">{{ scope.row.annotationAccuracyAuto }}</div> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | size="mini" |
| | | type="text" |
| | | icon="el-icon-edit" |
| | | @click="handleUpdate(scope.row)" |
| | | v-hasPermi="['ycl:threshold:edit']" |
| | | @click="updateWho(scope.row)" |
| | | >修改 |
| | | </el-button> |
| | | <!-- <el-button--> |
| | |
| | | @pagination="getList" |
| | | /> |
| | | |
| | | <!-- 添加或修改运维阈值对话框 --> |
| | | <el-dialog :title="title" :visible.sync="open" width="400px" append-to-body> |
| | | <el-form ref="form" :model="form" :rules="rules" label-width="150px"> |
| | | <!-- 人脸阈值 --> |
| | | <el-dialog title="修改人脸工单阈值" :visible.sync="faceOpen" width="400px" append-to-body> |
| | | <el-form ref="faceForm" :model="faceForm" :rules="rules" label-width="150px"> |
| | | <el-form-item label="设备类型" prop="monitorType"> |
| | | <el-select v-model="form.monitorType" placeholder="请选择设备类型" @change="handleModeNameChange"> |
| | | <el-option label="人脸" value="1"/> |
| | | <el-option label="车辆" value="2"/> |
| | | <el-option label="视频" value="3"/> |
| | | <el-select v-model="faceForm.monitorType" placeholder="请选择设备类型" @change="handleModeNameChange"> |
| | | <el-option label="人脸" value="face"/> |
| | | <el-option label="车辆" value="car"/> |
| | | <el-option label="视频" value="video"/> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="超时天数" prop="timeout" label-width="150px"> |
| | | <el-input type="number" min="0" max="1000" v-model="form.timeout" placeholder="请输入超时天数"/> |
| | | </el-form-item> |
| | | <el-form-item :label="indicator.label" prop="indexOneValue" v-for="indicator in indicators" label-width="150px"> |
| | | <el-input class="el-input-half-width" v-model="indicator.value" placeholder="工单阈值"/> |
| | | <el-input style="float: right;" class="el-input-half-width" v-model="indicator.value2" placeholder="下发阈值"/> |
| | | |
| | | </el-form> |
| | | <div slot="footer" class="dialog-footer"> |
| | | <el-button type="primary" @click="editFace">确 定</el-button> |
| | | <el-button @click="cancelFace">取 消</el-button> |
| | | </div> |
| | | </el-dialog> |
| | | |
| | | <!-- 车辆阈值 --> |
| | | <el-dialog title="修改车辆工单阈值" :visible.sync="faceOpen" width="400px" append-to-body> |
| | | <el-form ref="faceForm" :model="faceForm" :rules="rules" label-width="150px"> |
| | | <el-form-item label="设备类型" prop="monitorType"> |
| | | <el-select v-model="faceForm.monitorType" placeholder="请选择设备类型" @change="handleModeNameChange"> |
| | | <el-option label="人脸" value="face"/> |
| | | <el-option label="车辆" value="car"/> |
| | | <el-option label="视频" value="video"/> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-form> |
| | | <div slot="footer" class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm">确 定</el-button> |
| | | <el-button @click="cancel">取 消</el-button> |
| | | <el-button type="primary" @click="editCar">确 定</el-button> |
| | | <el-button @click="cancelCar">取 消</el-button> |
| | | </div> |
| | | </el-dialog> |
| | | |
| | | <!-- 视频阈值 --> |
| | | <el-dialog title="修改视频工单阈值" :visible.sync="videoOpen" width="500px" append-to-body> |
| | | <el-form ref="videoForm" :model="videoForm" :rules="rules" label-width="100px"> |
| | | <el-form-item label="设备类型" prop="monitorType"> |
| | | <el-select v-model="videoForm.monitorType" disabled placeholder="请选择设备类型" @change="handleModeNameChange"> |
| | | <el-option label="人脸" value="face"/> |
| | | <el-option label="车辆" value="car"/> |
| | | <el-option label="视频" value="video"/> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="图像质量" prop="imageQuality" label-width="100px"> |
| | | <el-select v-model="videoForm.imageQuality" placeholder="工单阈值" @change="handleModeNameChange"> |
| | | <el-option :key="dict.value" :label="dict.value" v-for="dict in dict.type.image_qualify"/> |
| | | </el-select> |
| | | <el-select v-model="videoForm.imageQualityAuto" placeholder="下发阈值" @change="handleModeNameChange"> |
| | | <el-option :key="dict.value" :label="dict.value" v-for="dict in dict.type.image_qualify"/> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="视频质量" prop="videoQuality" label-width="100px"> |
| | | <el-select v-model="videoForm.videoQuality" placeholder="工单阈值" @change="handleModeNameChange"> |
| | | <el-option :key="dict.value" :label="dict.value" v-for="dict in dict.type.video_qualify"/> |
| | | </el-select> |
| | | <el-select v-model="videoForm.videoQualityAuto" placeholder="下发阈值" @change="handleModeNameChange"> |
| | | <el-option :key="dict.value" :label="dict.value" v-for="dict in dict.type.video_qualify"/> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="标注准确率" prop="annotationAccuracy" label-width="100px"> |
| | | <el-input v-model="videoForm.annotationAccuracy" type="number" size="small" placeholder="工单阈值"></el-input> |
| | | <el-input v-model="videoForm.annotationAccuracy" type="number" size="small" placeholder="下发阈值"></el-input> |
| | | </el-form-item> |
| | | </el-form> |
| | | <div slot="footer" class="dialog-footer"> |
| | | <el-button type="primary" @click="editVideo">确 定</el-button> |
| | | <el-button @click="cancelVideo">取 消</el-button> |
| | | </div> |
| | | </el-dialog> |
| | | |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { listThreshold, getThreshold, delThreshold, addThreshold, updateThreshold } from '@/api/platform/threshold' |
| | | import { listThreshold, getThreshold, editVideo } from '@/api/platform/threshold' |
| | | import { editCar, editFace, getCar, getFace, getVideo } from '../../../api/platform/threshold' |
| | | |
| | | export default { |
| | | dicts: ['image_qualify', 'video_qualify'], |
| | | name: 'Threshold', |
| | | data() { |
| | | return { |
| | |
| | | // 弹出层标题 |
| | | title: '', |
| | | // 是否显示弹出层 |
| | | open: false, |
| | | videoOpen: false, |
| | | faceOpen: false, |
| | | // 查询参数 |
| | | queryParams: { |
| | | pageNum: 1, |
| | |
| | | monitorType: null |
| | | }, |
| | | // 表单参数 |
| | | form: {}, |
| | | videoForm: {}, |
| | | carForm: {}, |
| | | faceForm: {}, |
| | | // 表单校验 |
| | | rules: { |
| | | monitorType: [ |
| | | { required: true, message: '设备类型:1人脸 2车辆 3视频不能为空', trigger: 'change' } |
| | | ], |
| | | timeout: [ |
| | | { required: true, message: '超时天数不能为空', trigger: 'blur' } |
| | | ] |
| | | videoQuality: [ |
| | | { required: true, message: '请选择视频质量阈值', trigger: 'change' } |
| | | ], |
| | | imageQuality: [ |
| | | { required: true, message: '请选择图像质量阈值', trigger: 'change' } |
| | | ], |
| | | annotationAccuracy: [ |
| | | { required: true, message: '请填写标注准确率阈值', trigger: 'blur' } |
| | | ], |
| | | } |
| | | } |
| | | }, |
| | |
| | | this.getList() |
| | | }, |
| | | methods: { |
| | | editVideo() { |
| | | this.$refs['videoForm'].validate(validate => { |
| | | if (validate) { |
| | | editVideo(this.videoForm).then(res => { |
| | | if (res.code === 200) { |
| | | this.$message.success("修改成功") |
| | | this.getList(); |
| | | } else { |
| | | this.$message.success("修改失败") |
| | | } |
| | | }) |
| | | } |
| | | }) |
| | | }, |
| | | editFace() { |
| | | this.$refs['faceForm'].validate(validate => { |
| | | if (validate) { |
| | | editFace(this.videoForm).then(res => { |
| | | if (res.code === 200) { |
| | | this.$message.success("修改成功") |
| | | this.getList(); |
| | | } else { |
| | | this.$message.success("修改失败") |
| | | } |
| | | }) |
| | | } |
| | | }) |
| | | }, |
| | | editCar() { |
| | | this.$refs['carForm'].validate(validate => { |
| | | if (validate) { |
| | | editCar(this.carForm).then(res => { |
| | | if (res.code === 200) { |
| | | this.$message.success("修改成功") |
| | | this.getList(); |
| | | } else { |
| | | this.$message.success("修改失败") |
| | | } |
| | | }) |
| | | } |
| | | }) |
| | | }, |
| | | /** 查询运维阈值列表 */ |
| | | getList() { |
| | | this.loading = true |
| | |
| | | }) |
| | | }, |
| | | // 取消按钮 |
| | | cancel() { |
| | | this.open = false |
| | | this.reset() |
| | | cancelFace() { |
| | | this.faceOpen = false |
| | | this.resetFace() |
| | | }, |
| | | cancelCar() { |
| | | this.carOpen = false |
| | | this.resetCar() |
| | | }, |
| | | cancelVideo() { |
| | | this.videoOpen = false |
| | | this.resetVideo() |
| | | }, |
| | | // 表单重置 |
| | | reset() { |
| | |
| | | deleted: null |
| | | } |
| | | this.resetForm('form') |
| | | }, |
| | | resetVideo() { |
| | | this.videoForm = { |
| | | id: null, |
| | | monitorType: "", |
| | | imageQuality: "", |
| | | imageQualityAuto: "", |
| | | videoQuality: "", |
| | | videoQualityAuto: "", |
| | | annotationAccuracy: null, |
| | | annotationAccuracyAuto: null, |
| | | } |
| | | this.resetForm('videoForm') |
| | | }, |
| | | resetFace() { |
| | | this.faceForm = { |
| | | id: null, |
| | | monitorType: "", |
| | | imageQuality: "", |
| | | imageQualityAuto: "", |
| | | videoQuality: "", |
| | | videoQualityAuto: "", |
| | | annotationAccuracy: null, |
| | | annotationAccuracyAuto: null, |
| | | } |
| | | this.resetForm('faceForm') |
| | | }, |
| | | resetCar() { |
| | | this.carForm = { |
| | | id: null, |
| | | monitorType: "", |
| | | imageQuality: "", |
| | | imageQualityAuto: "", |
| | | videoQuality: "", |
| | | videoQualityAuto: "", |
| | | annotationAccuracy: null, |
| | | annotationAccuracyAuto: null, |
| | | } |
| | | this.resetForm('carForm') |
| | | }, |
| | | /** 搜索按钮操作 */ |
| | | handleQuery() { |
| | |
| | | this.handleModeNameChange() |
| | | }, |
| | | /** 修改按钮操作 */ |
| | | updateWho(row) { |
| | | if (row.monitorType === 'face') { |
| | | getFace(row.id).then(response => { |
| | | this.faceForm = response.data |
| | | this.faceOpen = true; |
| | | }) |
| | | } else if (row.monitorType === 'car') { |
| | | getCar(row.id).then(response => { |
| | | this.carForm = response.data |
| | | this.carOpen = true; |
| | | }) |
| | | } else { |
| | | getVideo(row.id).then(response => { |
| | | this.videoForm = response.data |
| | | this.videoOpen = true; |
| | | }) |
| | | } |
| | | }, |
| | | handleUpdate(row) { |
| | | this.reset() |
| | | const id = row.id || this.ids |
| | | getThreshold(id).then(response => { |
| | | this.form = response.data |
| | | this.indicators = JSON.parse(this.form.indicator) |
| | | this.open = true |
| | | this.videoOpen = true |
| | | this.title = '修改运维阈值' |
| | | }) |
| | | }, |
| | |
| | | value: null |
| | | } |
| | | ] |
| | | } else if (this.form.monitorType === '2') { |
| | | } else if (this.form.monitorType === 'car') { |
| | | this.indicators = [ |
| | | { |
| | | label: '过车数据量', |
| | |
| | | value: null |
| | | } |
| | | ] |
| | | } else if (this.form.monitorType === '3') { |
| | | } else if (this.form.monitorType === 'video') { |
| | | this.indicators = [ |
| | | { |
| | | label: '采集设备总数', |
| | | label: '录像质量', |
| | | value: null |
| | | }, |
| | | { |
| | | label: '监测正常设备数', |
| | | label: '标注准确率', |
| | | value: null |
| | | }, |
| | | { |
| | | label: '编码异常设备数', |
| | | label: '图像质量', |
| | | value: null |
| | | }, |
| | | { |
| | | label: '经纬度异常设备数', |
| | | value: null |
| | | } |
| | | ] |
| | | } |
| | | } |
| | |
| | | .el-input-half-width { |
| | | width: calc(50% - 6px); /* 减去一些间隔 */ |
| | | } |
| | | .table-row { |
| | | display: flex; |
| | | flex-direction: row; |
| | | } |
| | | .table-row-item { |
| | | width: 120px; |
| | | text-align: center; |
| | | } |
| | | </style> |
| | |
| | | icon="el-icon-plus" |
| | | size="mini" |
| | | @click="handleAdd" |
| | | v-hasPermi="['unit:add']" |
| | | >新增</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | |
| | | size="mini" |
| | | :disabled="single" |
| | | @click="handleUpdate" |
| | | v-hasPermi="['unit:edit']" |
| | | >修改</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | |
| | | size="mini" |
| | | :disabled="multiple" |
| | | @click="handleDelete" |
| | | v-hasPermi="['unit:remove']" |
| | | >删除</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | |
| | | icon="el-icon-download" |
| | | size="mini" |
| | | @click="handleExport" |
| | | v-hasPermi="['unit:export']" |
| | | >导出</el-button> |
| | | </el-col> |
| | | <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> |
| | |
| | | type="text" |
| | | icon="el-icon-edit" |
| | | @click="handleUpdate(scope.row)" |
| | | v-hasPermi="['unit:edit']" |
| | | >修改</el-button> |
| | | <el-button |
| | | size="mini" |
| | | type="text" |
| | | icon="el-icon-delete" |
| | | @click="handleDelete(scope.row)" |
| | | v-hasPermi="['unit:remove']" |
| | | >删除</el-button> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | icon="el-icon-plus" |
| | | size="mini" |
| | | @click="handleAdd" |
| | | v-hasPermi="['unit:people:add']" |
| | | >新增</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | |
| | | size="mini" |
| | | :disabled="single" |
| | | @click="handleUpdate" |
| | | v-hasPermi="['unit:people:edit']" |
| | | >修改</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | |
| | | size="mini" |
| | | :disabled="multiple" |
| | | @click="handleDelete" |
| | | v-hasPermi="['unit:people:remove']" |
| | | >删除</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | |
| | | icon="el-icon-download" |
| | | size="mini" |
| | | @click="handleExport" |
| | | v-hasPermi="['unit:people:export']" |
| | | >导出</el-button> |
| | | </el-col> |
| | | <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> |
| | |
| | | type="text" |
| | | icon="el-icon-edit" |
| | | @click="handleUpdate(scope.row)" |
| | | v-hasPermi="['unit:people:edit']" |
| | | >修改</el-button> |
| | | <el-button |
| | | size="mini" |
| | | type="text" |
| | | icon="el-icon-delete" |
| | | @click="handleDelete(scope.row)" |
| | | v-hasPermi="['unit:people:remove']" |
| | | >删除</el-button> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | icon="el-icon-download" |
| | | size="mini" |
| | | @click="handleExport" |
| | | v-hasPermi="['system:monitor:export']" |
| | | >导出</el-button> |
| | | </el-col> |
| | | <right-toolbar :showSearch.sync="showSearch" @queryTable="getList" :columns="columns"></right-toolbar> |
| | |
| | | <el-col :span="24" style="position: relative"> |
| | | <el-menu :default-active="activeIndex" class="el-menu" mode="horizontal" @select="handleSelect"> |
| | | <el-menu-item index="0" @click="changeUnit(null, '全部')"> |
| | | 全部单位(430) |
| | | 全部单位({{ totalWorkOrders }}) |
| | | </el-menu-item> |
| | | <el-menu-item index="1"> |
| | | 自流井运维单位(70) |
| | | <el-menu-item :index="index + 1" v-for="(item, index) in unitList" :key="index" @click="changeUnit(item.id, item.value)"> |
| | | {{ item.unitName }}({{ item.workOrderCount }}) |
| | | </el-menu-item> |
| | | <el-menu-item index="2"> |
| | | 大安运维(50) |
| | | </el-menu-item> |
| | | <el-menu-item index="3">富顺运维单位(70)</el-menu-item> |
| | | <el-menu-item index="4">高新运维单位(15)</el-menu-item> |
| | | <el-menu-item index="5">荣县运维单位(90)</el-menu-item> |
| | | <el-menu-item index="6">贡井运维单位(45)</el-menu-item> |
| | | <el-menu-item index="7">沿滩运维单位(70)</el-menu-item> |
| | | </el-menu> |
| | | <el-popover |
| | | placement="right" |
| | | width="400" |
| | | trigger="click"> |
| | | <el-form :model="settingForm" :rules="settingRules" ref="settingForm" label-width="120px"> |
| | | <el-form-item label="录像质量" prop="videoQuality"> |
| | | <el-select style="width: 100%" v-model="settingForm.videoQuality" placeholder="最低录像质量"> |
| | | <el-option label="全录像" value="全录像"/> |
| | | <el-option label="部分录像" value="部分录像"/> |
| | | <el-option label="无录像" value="无录像"/> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="点位离线时长" prop="outLine"> |
| | | <el-input type="number" v-model="settingForm.outLine" placeholder="不能超过多久"> |
| | | <template slot="append">分钟</template> |
| | | </el-input> |
| | | </el-form-item> |
| | | <el-form-item label="视频标注准确率" prop="videoLabel"> |
| | | <el-input type="number" v-model="settingForm.videoLabel" placeholder="最低准确率"> |
| | | <template slot="append">%</template> |
| | | </el-input> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="submitSetting">保存</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | <el-button title="自动生成工单设置" slot="reference" class="setting" style="" type="success" icon="el-icon-s-tools" circle></el-button> |
| | | </el-popover> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | |
| | | <span style="font-weight: bold;font-size: 16px">快捷下发</span> |
| | | <el-form ref="fastDistributeForm" :model="fastDistributeForm" :rules="fastDistributeRules" label-width="80px"> |
| | | <el-form-item label="快捷方式" prop="fastWay"> |
| | | <el-radio v-model="fastDistributeForm.fastWay" label="0">最近30分钟</el-radio> |
| | | <el-radio v-model="fastDistributeForm.fastWay" label="01">最近1小时</el-radio> |
| | | <el-radio v-model="fastDistributeForm.fastWay" label="10">最近2小时</el-radio> |
| | | <el-radio v-model="fastDistributeForm.fastWay" label="11">最近1天</el-radio> |
| | | <el-radio v-model="fastDistributeForm.fastWay" label="101">自定义</el-radio> |
| | | <el-radio v-model="fastDistributeForm.fastWay" label="LAST_HALF_HOUR">最近30分钟</el-radio> |
| | | <el-radio v-model="fastDistributeForm.fastWay" label="LAST_HOUR">最近1小时</el-radio> |
| | | <el-radio v-model="fastDistributeForm.fastWay" label="LAST_TWO_HOUR">最近2小时</el-radio> |
| | | <el-radio v-model="fastDistributeForm.fastWay" label="LAST_DAY">最近1天</el-radio> |
| | | <el-radio v-model="fastDistributeForm.fastWay" label="CUSTOM">自定义</el-radio> |
| | | </el-form-item> |
| | | <el-form-item v-if="fastDistributeForm.fastWay === '101'" label="时间范围"> |
| | | <el-form-item v-if="fastDistributeForm.fastWay === 'CUSTOM'" label="时间范围"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="fastTimeRange" |
| | | type="datetimerange" |
| | | range-separator="至" |
| | | start-placeholder="开始日期" |
| | | value-format="yyyy-MM-dd HH:mm:ss" |
| | | end-placeholder="结束日期"> |
| | | </el-date-picker> |
| | | </el-form-item> |
| | |
| | | <el-option |
| | | v-for="item in unitList" |
| | | :key="item.id" |
| | | :label="item.value" |
| | | :label="item.unitName" |
| | | :value="item.id"> |
| | | </el-option> |
| | | </el-select> |
| | |
| | | reserve-keyword |
| | | placeholder="请选择来源" |
| | | :remote-method="remoteGetPoints" |
| | | @change="setPointId" |
| | | :loading="selectLoading"> |
| | | <el-option |
| | | v-for="item in pointList" |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import {distributeWorkOrder, fastDistribute, addWorkOrder, updateWorkOrder} from '@/api/platform/work-order' |
| | | import {unitSelect} from "@/api/platform/unit"; |
| | | import {distributeWorkOrder, fastDistribute, addWorkOrder, updateWorkOrder, selectedIdsDistribute} from '@/api/platform/work-order' |
| | | import {workList} from "@/api/platform/unit"; |
| | | import { pointSelectData } from "@/api/platform/point"; |
| | | export default { |
| | | name: 'index', |
| | | data() { |
| | | return { |
| | | selectedIdsDistributeForm: { |
| | | ids: [], |
| | | unitId: null |
| | | }, |
| | | unitList: [], |
| | | settingForm: { |
| | | // 离线 |
| | | outLine: null, |
| | |
| | | // 下发表单验证 |
| | | fastDistributeRules: { |
| | | fastWay: [ |
| | | { required: true, message: "请选择快速分发方式", trigger: "change" } |
| | | { required: true, message: "请选择快速分发方式", trigger: "blur" } |
| | | ], |
| | | fastNumLimit: [ |
| | | { required: true, message: "请输入快速分发数量限制", trigger: "change" } |
| | | { required: true, message: "请输入快速分发数量限制", trigger: "blur" } |
| | | ], |
| | | errorType: [ |
| | | { required: true, message: "请故障类型", trigger: "change" } |
| | | { required: true, message: "请故障类型", trigger: "blur" } |
| | | ], |
| | | }, |
| | | queryParams: { |
| | |
| | | }, |
| | | mounted() { |
| | | this.page(); |
| | | this.selectUnit(); |
| | | }, |
| | | computed: { |
| | | totalWorkOrders() { |
| | | return this.unitList.reduce((total, item) => total + item.workOrderCount, 0); |
| | | }, |
| | | }, |
| | | methods: { |
| | | setPointId(selectedValue) { |
| | | const selectedItem = this.pointList.find(item => item.value === selectedValue); |
| | | this.form.pointId = selectedItem.id |
| | | }, |
| | | submitSetting() { |
| | | this.$refs['settingForm'].validate((valid) => { |
| | | if (valid) { |
| | |
| | | }, |
| | | page() { |
| | | this.loading = true; |
| | | this.selectUnit(); |
| | | distributeWorkOrder(this.queryParams).then(res => { |
| | | this.workOrderList = res.data; |
| | | this.total = res.total; |
| | |
| | | this.fastDistributeForm.end = null |
| | | this.fastDistributeForm.fastNumLimit = null |
| | | this.fastTimeRange = [] |
| | | this.fastDistributeForm.errorType = null |
| | | }, |
| | | // 全部下发 |
| | | allDistribute() { |
| | | this.fastDistribute(); |
| | | this.selectedIdsDistributeForm.unitId = this.unitId |
| | | selectedIdsDistribute(this.selectedIdsDistributeForm).then(res => { |
| | | this.$message.success("工单下发成功") |
| | | this.page(); |
| | | }) |
| | | }, |
| | | // 快速下发 |
| | | fastDistribute() { |
| | | // this.$refs['fastDistributeForm'].validate((valid) => { |
| | | // if (valid) { |
| | | // 如果是自定义方式,那么时间段必填 |
| | | if (this.fastDistributeForm.fastWay === '101' && !this.fastTimeRange.length > 0) { |
| | | this.$message.warning("请选择时间范围") |
| | | return false |
| | | } |
| | | if (this.fastTimeRange.length > 0) { |
| | | this.fastDistributeForm.start = this.fastTimeRange[0] |
| | | this.fastDistributeForm.end = this.fastTimeRange[1] |
| | | } |
| | | this.$refs['fastDistributeForm'].validate((valid) => { |
| | | if (valid) { |
| | | this.fastDistributeForm.start = this.fastTimeRange[0] |
| | | this.fastDistributeForm.end = this.fastTimeRange[1] |
| | | this.fastDistributeForm.unitId = this.unitId |
| | | fastDistribute(this.fastDistributeForm).then(res => { |
| | | // this.clearFastDistributeForm(); |
| | | res.code == 200 ? this.$message.success(res.msg) : this.$message.warning(res.msg) |
| | | this.clearFastDistributeForm(); |
| | | this.page(); |
| | | }) |
| | | // } else { |
| | | // return false |
| | | // } |
| | | // }) |
| | | } |
| | | }) |
| | | }, |
| | | // 选中工单下发 |
| | | selectedDistribute() { |
| | | if (this.multipleSelection.length < 1) { |
| | | this.$message.warning("请先选择要下发的工单") |
| | | return |
| | | } |
| | | this.fastDistribute(); |
| | | } |
| | | this.selectedIdsDistributeForm.unitId = this.unitId; |
| | | this.selectedIdsDistributeForm.ids = this.multipleSelection; |
| | | selectedIdsDistribute(this.selectedIdsDistributeForm).then(res => { |
| | | this.$message.success("工单下发成功") |
| | | this.selectedIdsDistributeForm.ids = []; |
| | | this.page(); |
| | | }) |
| | | }, |
| | | handleSelect(key, keyPath) { |
| | | console.log(key, keyPath); |
| | |
| | | }, |
| | | // 运维公司下拉数据 |
| | | selectUnit() { |
| | | unitSelect().then(res => { |
| | | workList().then(res => { |
| | | this.unitList = res.data; |
| | | }) |
| | | }, |
| | |
| | | <el-option label="设备遗失" value="设备遗失"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="审核状态" prop="status"> |
| | | <el-select v-model="queryParams.status" placeholder="审核状态" clearable @clear="handleQuery"> |
| | | <el-option label="已下发" value="DISTRIBUTED"></el-option> |
| | | <el-option label="运维已处理" value="YW_HANDLE"></el-option> |
| | | <el-option label="审核通过" value="AUDITING_SUCCESS"></el-option> |
| | | <el-option label="审核不通过" value="AUDITING_FAIL"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="运维处理时间"> |
| | | <el-date-picker |
| | | clearable |
| | |
| | | size="mini" |
| | | type="text" |
| | | @click="handleReport(item)" |
| | | v-hasPermi="['system:report:add']" |
| | | >事后报备</el-button> |
| | | </el-row> |
| | | </div> |
| | |
| | | <!-- 事后报备 --> |
| | | <el-dialog title="事后报备" :visible.sync="reportOpen" width="600px" append-to-body> |
| | | <el-form ref="reportForm" :model="reportForm" :rules="reportFormRules" label-width="80px"> |
| | | <el-form-item label="点位" prop="pointId"> |
| | | <el-input v-model="reportForm.pointId" disabled /> |
| | | <el-form-item label="点位" prop="source"> |
| | | <el-input v-model="reportForm.source" disabled /> |
| | | </el-form-item> |
| | | <el-form-item label="报备类型"> |
| | | <el-input v-model="reportForm.reportType" disabled /> |
| | |
| | | <el-form-item label="运维人员" prop="ywPeopleName"> |
| | | <el-input v-model="auditingForm.ywPeopleName" disabled /> |
| | | </el-form-item> |
| | | <el-form-item label="现场情况"> |
| | | <el-form-item label="现场情况" v-if="auditingForm.condition"> |
| | | <el-input type="textarea" v-html="auditingForm.condition" disabled /> |
| | | </el-form-item> |
| | | <el-form-item label="佐证材料"> |
| | | <el-form-item label="佐证材料" v-if="auditingForm.proofMaterials"> |
| | | <el-link v-for="item in auditingForm.proofMaterials != null ? auditingForm.proofMaterials.split(',') : auditingForm.proofMaterials" :underline="false" :key="item" @click="handleDownload(item)">{{ item.substring(item.lastIndexOf("/") + 1) }}</el-link> |
| | | </el-form-item> |
| | | <el-form-item label="审核结果" prop="auditingResult"> |
| | | <el-radio v-model="auditingForm.auditingResult" label="pass">通过</el-radio> |
| | | <el-radio v-model="auditingForm.auditingResult" label="return">驳回</el-radio> |
| | | <el-radio v-model="auditingForm.auditingResult" label="AUDITING_SUCCESS">通过</el-radio> |
| | | <el-radio v-model="auditingForm.auditingResult" label="AUDITING_FAIL">驳回</el-radio> |
| | | </el-form-item> |
| | | <el-form-item label="审核备注" prop="auditingRemark"> |
| | | <el-input v-model="auditingForm.auditingRemark" type="textarea" maxlength="30" show-word-limit/> |
| | |
| | | </el-dialog> |
| | | |
| | | <el-dialog title="运维情况记录" :visible.sync="ywConditionOpen" width="500px" append-to-body> |
| | | <el-form ref="ywConditionForm" :model="ywConditionForm" :rules="ywConditionRules" label-width="80px"> |
| | | <el-form ref="form" :model="form" :rules="ywConditionRules" label-width="80px"> |
| | | <el-form-item label="工单号" prop="workOrderNo"> |
| | | <el-input v-model="ywConditionForm.workOrderNo" disabled /> |
| | | </el-form-item> |
| | |
| | | <el-input v-model="ywConditionForm.unitName" disabled /> |
| | | </el-form-item> |
| | | <el-form-item label="运维人员" prop="ywPeopleName"> |
| | | <el-input v-model="ywConditionForm.ywPeopleName" /> |
| | | <el-input v-model="ywConditionForm.ywPeopleName" disabled /> |
| | | </el-form-item> |
| | | <el-form-item label="现场情况" prop="reportContent"> |
| | | <editor v-model="form.condition" :min-height="192"/> |
| | | <el-form-item label="现场情况" prop="ywCondition"> |
| | | <editor v-model="form.ywCondition" :min-height="192"/> |
| | | </el-form-item> |
| | | <el-form-item label="佐证材料" prop="reportMaterials"> |
| | | <file-upload v-model="form.proofMaterials"/> |
| | | <el-form-item label="佐证材料" prop="ywProofMaterials"> |
| | | <file-upload v-model="form.ywProofMaterials"/> |
| | | </el-form-item> |
| | | </el-form> |
| | | <div slot="footer" class="dialog-footer"> |
| | |
| | | <!-- 过程图 --> |
| | | <el-dialog title="过程图" :visible.sync="flowOpen" width="1200px" :close-on-click-modal="false" append-to-body> |
| | | <div> |
| | | <el-steps :active="2" :space="500"> |
| | | <el-steps :active="ywAuditingList.length != 0 ? 3 : ywHandleList.length != 0 ? 2 : 1" :space="500"> |
| | | <el-step title="产生工单"> |
| | | <template slot="description"> |
| | | <div> |
| | |
| | | <div class="flow-item-x"> |
| | | 创建时间:{{flowForm.createTime}} |
| | | </div> |
| | | <div class="flow-item-x"> |
| | | 处理期限:<el-tag type="danger" size="small">12小时</el-tag> |
| | | <div class="flow-item-x" v-if="flowForm.processingPeriod"> |
| | | 处理期限:<el-tag type="danger" size="small">{{ flowForm.processingPeriod }}</el-tag> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | </el-step> |
| | | <el-step title="运维处理"> |
| | | <template slot="description"> |
| | | <div class="y-item"> |
| | | <div class="y-item" v-for="(item, index) in ywHandleList"> |
| | | <div class="y-item-1"> |
| | | <div class="flow-item-x"> |
| | | 运维状态:<el-tag type="danger" size="small">结果上报</el-tag> |
| | | 现场情况: |
| | | <el-tooltip class="item" effect="dark" :content="item.ywCondition" placement="top"> |
| | | <el-tag size="small" class="line-limit-length">{{ item.ywCondition }}</el-tag> |
| | | </el-tooltip> |
| | | </div> |
| | | <div class="flow-item-x"> |
| | | 运维人员:<el-tag type="danger" size="small">{{flowForm.ywPeopleName}}</el-tag> |
| | | </div> |
| | | <!-- <div class="flow-item-x"> |
| | | <el-tag size="small" v-for="file in item.ywProofMaterials != null ? item.ywProofMaterials.split(',') : item.ywProofMaterials" :key="file" @click="handleDownload(file)">{{ file.substring(file.lastIndexOf("/") + 1) }}</el-tag> |
| | | </div> --> |
| | | </div> |
| | | <div class="y-item-2"> |
| | | <div > |
| | | {{flowForm.ywHandleTime}} |
| | | {{ parseTime(item.createTime) }} |
| | | </div> |
| | | <div > |
| | | 第几次:1 |
| | | 第几次:{{ index + 1 }} |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="y-item"> |
| | | <div class="y-item-1"> |
| | | <div class="flow-item-x"> |
| | | 运维状态:<el-tag type="danger" size="small">结果上报</el-tag> |
| | | </div> |
| | | <div class="flow-item-x"> |
| | | 运维人员:<el-tag type="danger" size="small">{{flowForm.ywPeopleName}}</el-tag> |
| | | </div> |
| | | </div> |
| | | <div class="y-item-2"> |
| | | <div > |
| | | {{flowForm.ywHandleTime}} |
| | | </div> |
| | | <div > |
| | | 第几次:2 |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | </template> |
| | | </el-step> |
| | | <el-step title="结果审核"> |
| | | <template slot="description"> |
| | | <div class="y-item"> |
| | | <div class="y-item" v-for="(item, index) in ywAuditingList"> |
| | | <div class="y-item-1"> |
| | | <div class="flow-item-x"> |
| | | 审核结果:<el-tag type="danger" size="small">驳回</el-tag> |
| | | 审核结果:<el-tag :type="item.result == '审核通过' ? 'success' : 'danger'" size="small">{{ item.result }}</el-tag> |
| | | </div> |
| | | <div class="flow-item-x"> |
| | | 审核说明:<el-tag type="danger" size="small">未成功处理</el-tag> |
| | | 审核说明:<el-tag size="small" v-if="item.remark">{{ item.remark }}</el-tag> |
| | | </div> |
| | | </div> |
| | | <div class="y-item-2"> |
| | | <div > |
| | | {{flowForm.ywHandleTime}} |
| | | {{ parseTime(item.createTime) }} |
| | | </div> |
| | | <div > |
| | | 第几次:1 |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="y-item"> |
| | | <div class="y-item-1"> |
| | | <div class="flow-item-x"> |
| | | 审核状态:<el-tag type="info" size="small">审核中</el-tag> |
| | | </div> |
| | | <div class="flow-item-x"> |
| | | 审核说明: |
| | | </div> |
| | | </div> |
| | | <div class="y-item-2"> |
| | | <div > |
| | | {{flowForm.ywHandleTime}} |
| | | </div> |
| | | <div > |
| | | 第几次:2 |
| | | 第几次:{{ index + 1 }} |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | } |
| | | </style> |
| | | <script> |
| | | import { listWorkOrder, getWorkOrder, delWorkOrder, addWorkOrder, updateWorkOrder,auditing, ywCondition } from "@/api/platform/work-order"; |
| | | import { listWorkOrder, getWorkOrder, delWorkOrder, addWorkOrder, updateWorkOrder,auditing, ywCondition, getYwCondition, getYwConditionList, getYwAuditingList } from "@/api/platform/work-order"; |
| | | import { addReport } from "@/api/platform/report"; |
| | | export default { |
| | | name: "Work-order", |
| | | components: { |
| | | }, |
| | | data() { |
| | | return { |
| | | ywHandleList: [], |
| | | ywAuditingList: [], |
| | | reportFormRules: { |
| | | reportContent: [ |
| | | { required: true, message: "报备内容不能为空", trigger: "blur" } |
| | |
| | | reportOpen: false, |
| | | reportForm: { |
| | | reportType: "事后报备", |
| | | pointId: "琼于镇3街1号摄像头", |
| | | pointId: "", |
| | | errorType: "", |
| | | reportContent: "", |
| | | reportMaterials: "" |
| | |
| | | ywHandleTime: null, |
| | | ywResult: null, |
| | | ywCondition: null, |
| | | status: '' |
| | | }, |
| | | // 表单参数 |
| | | form: {}, |
| | |
| | | submitReportForm() { |
| | | this.$refs["reportForm"].validate(valid => { |
| | | if (valid) { |
| | | addReport(this.form).then(response => { |
| | | addReport(this.reportForm).then(response => { |
| | | this.$modal.msgSuccess("成功提交报备"); |
| | | this.open = false; |
| | | this.reportOpen = false; |
| | | this.getList(); |
| | | }); |
| | | } |
| | |
| | | }, |
| | | // 事后报备按钮 |
| | | handleReport(row) { |
| | | this.reportForm.pointId = row.source; |
| | | this.reportForm.pointId = row.pointId; |
| | | this.reportForm.source = row.source; |
| | | this.reportOpen = true; |
| | | }, |
| | | // 审核按钮 |
| | | handleAuditing(row) { |
| | | this.auditingForm = row; |
| | | this.auditingForm.condition = '设备异常遮挡,现场修复完成' |
| | | this.auditingForm.proofMaterials = '30路由配置_20240411101816A008.png' |
| | | this.auditingOpen = true; |
| | | getYwCondition(row.id).then(response => { |
| | | if (response.data) { |
| | | this.auditingForm.condition = response.data.ywCondition; |
| | | this.auditingForm.proofMaterials = response.data.ywProofMaterials; |
| | | } |
| | | this.auditingOpen = true; |
| | | }); |
| | | }, |
| | | // 运维情况按钮 |
| | | handleYwCondition(row) { |
| | | this.form = {}; |
| | | this.ywConditionForm = row; |
| | | this.ywConditionOpen = true; |
| | | this.form.id = row.id; |
| | | }, |
| | | // 运维结果按钮 |
| | | handleYwResult(row) { |
| | |
| | | }, |
| | | // 过程图查看 |
| | | handleFlow(row) { |
| | | this.flowOpen = true; |
| | | this.flowForm = row; |
| | | getYwAuditingList(row.id).then(response => { |
| | | if (response.data) { |
| | | this.ywAuditingList = response.data; |
| | | } |
| | | }); |
| | | getYwConditionList(row.id).then(response => { |
| | | if (response.data) { |
| | | this.ywHandleList = response.data; |
| | | } |
| | | this.flowOpen = true; |
| | | }); |
| | | }, |
| | | // 提交审核 |
| | | submitAuditing() { |
| | |
| | | auditing(this.auditingForm).then(res => { |
| | | this.auditingOpen = false; |
| | | this.$modal.msgSuccess("操作成功"); |
| | | this.getList(); |
| | | }) |
| | | } |
| | | }) |
| | |
| | | }, |
| | | // 提交运维情况 |
| | | submitYwCondition() { |
| | | this.$refs["ywConditionForm"].validate(valid => { |
| | | this.$refs["form"].validate(valid => { |
| | | if (valid) { |
| | | ywCondition(this.ywConditionForm).then(res => { |
| | | ywCondition(this.form).then(res => { |
| | | this.ywConditionOpen = false; |
| | | this.$modal.msgSuccess("操作成功"); |
| | | this.getList(); |
| | | }) |
| | | } |
| | | }) |
| | |
| | | getList() { |
| | | this.loading = true; |
| | | this.queryParams.params = {}; |
| | | if (null != this.daterangeYwHandleTime && '' != this.daterangeYwHandleTime) { |
| | | this.queryParams["start"] = this.daterangeYwHandleTime[0]; |
| | | this.queryParams["end"] = this.daterangeYwHandleTime[1]; |
| | | } |
| | | this.queryParams["start"] = this.daterangeYwHandleTime[0]; |
| | | this.queryParams["end"] = this.daterangeYwHandleTime[1]; |
| | | if (this.queryParams["status"] == "") { this.queryParams["status"] = "DISTRIBUTED"; } |
| | | listWorkOrder(this.queryParams).then(response => { |
| | | this.workOrderList = response.data; |
| | | this.total = response.total; |
| | |
| | | height: 150px; |
| | | padding: 10px; |
| | | } |
| | | |
| | | .line-limit-length { |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | width: 200px; |
| | | } |
| | | </style> |
| | |
| | | proxy: { |
| | | // detail: https://cli.vuejs.org/config/#devserver-proxy |
| | | [process.env.VUE_APP_BASE_API]: { |
| | | target: `http://localhost:8080`, |
| | | // target: `http://localhost:8080`, |
| | | target: `http://192.168.3.87:8080`, |
| | | changeOrigin: true, |
| | | pathRewrite: { |
| | | ['^' + process.env.VUE_APP_BASE_API]: '' |