Commit 7aaec1a0 authored by 张牧越's avatar 张牧越

初版大屏

parents
NODE_ENV = "development"
Mock: true
VUE_APP_API_URL = "http://detectapi.cnjsjd.net"
VUE_APP_CIVIL_API_URL = ""
NODE_ENV = "production"
Mock: false
VUE_APP_API_URL = "http://detectapi.cnjsjd.net"
VUE_APP_CIVIL_API_URL = "http://dhjc.vnet1000.net"
\ No newline at end of file
module.exports = {
root: true,
env: {
node: true
},
'extends': [
'plugin:vue/essential',
'eslint:recommended'
],
parserOptions: {
parser: '@babel/eslint-parser'
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
//在rules中添加自定义规则
//关闭组件命名规则
"vue/multi-word-component-names": "off",
},
overrides: [
{
files: [
'**/__tests__/*.{j,t}s?(x)',
'**/tests/unit/**/*.spec.{j,t}s?(x)'
],
env: {
jest: true
}
}
]
}
.DS_Store
node_modules
/dist
dist.zip
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
# digital-construction
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Lints and fixes files
```
npm run lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}
{
"compilerOptions": {
"target": "es5",
"module": "esnext",
"baseUrl": "./",
"moduleResolution": "node",
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
}
}
This diff is collapsed.
{
"name": "digital-construction",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"@amap/amap-jsapi-loader": "^1.0.1",
"autoprefixer": "^10.4.14",
"axios": "^1.3.4",
"core-js": "^3.8.3",
"echarts": "^5.5.1",
"element-ui": "^2.15.13",
"jquery": "^3.7.1",
"js-md5": "^0.8.3",
"lib-flexible": "^0.3.2",
"precss": "^4.0.0",
"video.js": "^8.0.4",
"videojs-contrib-hls": "^5.15.0",
"vue": "^2.6.14",
"vue-calendar-component": "^2.8.2",
"vue-router": "^3.5.2",
"vue-seamless-scroll": "^1.1.23",
"vue-video-player": "^5.0.1",
"vuex": "^3.6.2"
},
"postcss": {
"plugins": {
"autoprefixer": {},
"precss": {}
}
},
"devDependencies": {
"@babel/core": "^7.12.16",
"@babel/eslint-parser": "^7.12.16",
"@vue/cli-plugin-babel": "~5.0.0",
"@vue/cli-plugin-eslint": "~5.0.0",
"@vue/cli-service": "~5.0.0",
"eslint": "^7.32.0",
"eslint-plugin-vue": "^8.0.3",
"less": "^4.1.3",
"less-loader": "^11.1.0",
"postcss-plugin-px2rem": "^0.8.1",
"px2rem-loader": "^0.1.9",
"style-resources-loader": "^1.5.0",
"vue-cli-plugin-style-resources-loader": "^0.1.5",
"vue-template-compiler": "^2.6.14"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "@babel/eslint-parser"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>
长兴县建设工程质量安全管理站
</title>
<style>
.el-icon-loading {
font-size: 30px !important;
}
.el-loading-text {
font-size: 16px !important;
}
.amap-logo {
display: none !important;
}
.amap-copyright {
opacity: 0 !important;
}
.el-loading-mask {
z-index: 99999 !important;
}
.full-screen .el-dialog {
width: 100% !important;
height: 100% !important;
margin: 0 !important;
}
.full-screen .el-dialog__body {
height: calc(100% - .54rem) !important;
display: flex;
flex-direction: column;
}
</style>
<script src="<%= BASE_URL %>js/h5player.min.js"></script>
</head>
<body style="height: 100vh;">
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
\ No newline at end of file
This diff is collapsed.
<template>
<div id="app">
<router-view v-if="signIn"></router-view>
</div>
</template>
<script>
const debounce = (fn, delay) => {
let timer = null;
return function () {
let context = this;
let args = arguments;
clearTimeout(timer);
timer = setTimeout(function () {
fn.apply(context, args);
}, delay);
};
};
const _ResizeObserver = window.ResizeObserver;
window.ResizeObserver = class ResizeObserver extends _ResizeObserver {
constructor(callback) {
callback = debounce(callback, 16);
super(callback);
}
};
import { checkLogin } from "@/api/index";
export default {
name: "App",
components: {},
data() {
return {
signIn: false,
};
},
methods: {
bodyScale() {
// var deviceHeight = window.innerHeight;
// var scale = deviceHeight / 1080;
// document.body.style.zoom = scale;
// document.body.style.height = (1 / scale) * 100 + "vh";
// document.styleSheets[document.styleSheets.length - 1].insertRule(
// "canvas:not(.amap-layer):not(.amap-labels) {zoom: " +
// Number(1 / scale).toFixed(2) +
// "!important}"
// );
// document.styleSheets[document.styleSheets.length - 1].insertRule(
// "canvas:not(.amap-layer):not(.amap-labels) {transform: scale(" +
// scale +
// ")!important}"
// );
// document.styleSheets[document.styleSheets.length - 1].insertRule(
// "canvas:not(.amap-layer):not(.amap-labels) {transform-origin: 0 0}"
// );
var designW = 1920;
var font_rate = 100;
document.getElementsByTagName("html")[0].style.fontSize =
(document.body.offsetWidth / designW) * font_rate + "px";
document.getElementsByTagName("body")[0].style.fontSize =
(document.body.offsetWidth / designW) * font_rate + "px";
// //监测窗口大小变化
window.addEventListener(
"onorientationchange" in window ? "orientationchange" : "resize",
function () {
document.getElementsByTagName("html")[0].style.fontSize =
(document.body.offsetWidth / designW) * font_rate + "px";
document.getElementsByTagName("body")[0].style.fontSize =
(document.body.offsetWidth / designW) * font_rate + "px";
},
false
);
},
getcookie(sname) {
var acookie = document.cookie.split("; ");
for (var i = 0; i < acookie.length; i++) {
var arr = acookie[i].split("=");
if (sname == arr[0]) {
if (arr.length > 1) return unescape(arr[1]);
else return "";
}
}
return "";
},
checkLogin() {
checkLogin().then((res) => {
if (res.status == 200) {
this.signIn = true;
} else {
window.location.href = window.location.origin + "/wisdom";
}
});
},
},
mounted() {
var isChrome = window.navigator.userAgent.indexOf("Chrome") !== -1;
if (isChrome) {
this.bodyScale();
}
this.checkLogin();
},
};
</script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
margin: 0px;
}
#app {
height: 100%;
}
/* 滚动条样式 */
*::-webkit-scrollbar {
width: 8px; /* 设置纵轴(y轴)轴滚动条 */
height: 4px; /* 设置横轴(x轴)轴滚动条 */
}
/* 滚动条滑块(里面小方块) */
*::-webkit-scrollbar-thumb {
border-radius: 10px;
box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
background: rgba(255, 255, 255, 0.3);
}
/* 滚动条轨道 */
*::-webkit-scrollbar-track {
border-radius: 0;
box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
background: rgba(0, 0, 0, 0.5);
}
</style>
import request from "@/utils/request";
export async function checkLogin() {
return await request({
url: '/wisdom/screen/login/check',
method: 'get'
})
}
export async function getInfo() {
return await request({
url: '/wisdom/screen/noise/info',
method: 'get'
})
}
export async function getPM10Analysis() {
return await request({
url: '/wisdom/screen/noise/year/chart',
method: 'get'
})
}
export async function getMapData() {
return await request({
url: '/wisdom/screen/noise/env/project',
method: 'get'
})
}
export async function getPm10RateRank(type) {
return await request({
url: `/wisdom/screen/noise/weekpm10/${type}`,
method: 'get'
})
}
export async function getVideoImportList() {
return await request({
url: `/wisdom/screen/monitor/project`,
method: 'get'
})
}
export async function getStatistics() {
return await request({
url: `/wisdom/screen/statistics`,
method: 'get'
})
}
export async function getProjectDetail(id) {
return await request({
url: `/wisdom/screen/project/${id}`,
method: 'get'
})
}
export async function getRegions() {
return await request({
url: `/wisdom/screen/region`,
method: 'get'
})
}
export async function getProjectList(params) {
return await request({
url: `/wisdom/screen/project`,
method: 'get',
params,
noloading: true,
})
}
export async function getRealTimeDustData(id) {
return await request({
url: `/wisdom/screen/noise/realtime/${id}`,
method: 'get',
})
}
export async function getWarningList(params, id) {
return await request({
url: `/wisdom/screen/noise/waring/${id}`,
method: 'get',
params,
noloading: true,
})
}
export async function getDustHistory(params, id) {
return await request({
url: `/wisdom/screen/noise/env/${id}`,
method: 'get',
params,
noloading: true,
})
}
export async function getDustList(type) {
return await request({
url: `/wisdom/screen/noise/${type}`,
method: 'get'
})
}
import request from "@/utils/request";
export async function getDeviceListByProjectId(projectId, params) {
return await request({
url: `/wisdom/screen/monitor/device/${projectId}`,
method: 'get',
params
})
}
export async function getDevicePlayAddress(id) {
return await request({
url: `/wisdom/screen/monitor/info/${id}`,
method: 'get'
})
}
export async function getPlayBackUrl(id, params) {
return await request({
url: `/wisdom/screen/monitor/info/${id}`,
method: 'get',
params
})
}
::v-deep .el-dialog__body {
padding: 15px !important;
height: 700px;
}
::v-deep .el-form {
margin-bottom: 10px;
background: #12407F;
padding: 5px 5px 0 5px;
}
::v-deep .el-form-item {
margin-bottom: 5px;
}
::v-deep .el-form-item__content {
line-height: 0;
}
::v-deep .el-form-item__label {
line-height: 30px;
height: 30px;
color: #60FFF6;
}
::v-deep .el-input .el-input__inner {
background: #072350 !important;
border: none !important;
height: 30px !important;
font-size: 14px;
color: rgba(255, 255, 255, 0.7);
}
.inputInfo {
width: 120px;
}
.selectInfo {
width: 150px;
}
::v-deep .el-range-editor.el-input__inner {
height: 30px !important;
background: #072350 !important;
border: none !important;
font-size: 14px;
color: rgba(255, 255, 255, 0.7);
}
::v-deep .el-range-editor .el-range-input {
font-size: 14px;
color: rgba(255, 255, 255, 0.7);
}
::v-deep .el-date-editor .el-range__icon {
line-height: 37px;
}
::v-deep .el-range-editor .el-range-separator {
line-height: 26px;
}
.searchButton {
height: 30px !important;
padding: 0 10px;
background: #37CCC4;
}
/* 表格头部样式 背景颜色 */
::v-deep .el-table th.el-table__cell {
background: #16488b;
color: #01fff5;
font-size: 14px;
}
/* 表格身体背景颜色 */
::v-deep .el-table__body-wrapper {
background-color: #0c3163;
}
::v-deep .el-table tr:nth-child(even) {
background: #0e356b;
}
::v-deep .el-table tr:nth-child(odd) {
background: #0c3163;
}
/* 表格列和行的间距 */
.el-table .el-table__cell {
padding: 7px 0;
}
/* 表格外部 top 和 left 线条 */
::v-deep .el-table--border,
::v-deep .el-table--group {
border-color: #1f4c89;
}
/* 表格外部 right 和 bottom 线条 */
::v-deep .el-table--border::after,
::v-deep .el-table--group::after,
::v-deep .el-table::before {
background-color: #1f4c89;
}
/* 表格头部内部线条 */
::v-deep .el-table th.el-table__cell.is-leaf {
border: 1px solid #1f4c89 !important;
padding: 8px 0;
text-align: center;
}
/* 表格内部样式 线条 */
::v-deep .el-table td.el-table__cell {
border-bottom: 1px solid #1f4c89;
border-right: 1px solid #1f4c89;
color: #ffffff;
font-size: 12px;
}
.pagination {
height: 40px;
background: #0c3163;
border: 1px solid #1f4c89;
display: flex;
align-items: center;
justify-content: end;
}
\ No newline at end of file
@font-face {
font-family: 'kufangti';
src: url('./kufangti.ttf');
}
.amap-info-content {
background: #0f2e68;
border: 1px solid #05B9FD;
padding: 0;
}
.amap-info-close {
color: #fff;
}
.amap-info-sharp {
border: none !important;
}
.amap-info-outer {
border-radius: 8px;
}
\ No newline at end of file
/* select style */
.el-select__wrapper {
background: transparent;
box-shadow: none;
border: 1px solid rgba(49, 97, 166, 1);
}
.el-select__placeholder {
color: #fff;
}
.el-input__inner {
color: #fff;
}
/* table style */
.el-table {
background-color: transparent;
color: #fff;
font-size: 12px;
}
.el-table tr {
background-color: transparent;
}
.el-table .cell {
padding: 8px 6px;
line-height: 18px;
}
.el-table thead {
color: #fff;
}
.el-table th.el-table__cell {
background: rgba(35, 221, 255, 0.2);
}
.el-table .el-table__cell {
padding: 0;
}
.el-table thead th {
font-weight: 400;
}
.el-table * {
border-color: rgba(11, 116, 136, 1);
}
.el-table {
--el-table-border-color: rgba(11, 116, 136, 1);
}
.el-table--enable-row-hover .el-table__body tr:hover>td.el-table__cell {
background: rgba(35, 221, 255, .3) !important;
}
.el-table--striped .el-table__body tr.el-table__row--striped td.el-table__cell {
background: rgba(35, 221, 255, .1);
}
.el-table__empty-text {
color: #fff;
}
/* dialog style */
.el-dialog {
padding: 0;
}
.el-dialog__header {
text-align: center;
padding: 16px 0;
background: #063B80;
position: relative;
}
.el-dialog__header .el-dialog__title {
color: #fff;
z-index: 999;
position: absolute;
left: 50%;
top: 50%;
transform: translateX(-50%)translateY(-50%);
}
.el-dialog__header::after {
content: '';
position: absolute;
top: 0;
left: 50%;
width: 100%;
height: 100%;
background: url('@/assets/images/dialog-title-bg.png') no-repeat;
background-size: 100% 100%;
transform: translateX(-50%);
z-index: 0;
}
.el-dialog__header .el-dialog__headerbtn {
z-index: 999
}
.el-dialog .el-dialog__body {
height: 800px;
display: flex;
flex-direction: column;
padding: 20px;
background: #033168;
}
.el-dialog.full-screen .el-dialog__body {
height: calc(100% - 90px);
display: flex;
flex-direction: column;
}
.search-form {
width: 100%;
}
.el-icon.el-dialog__close {
color: #fff;
font-size: 20px;
line-height: 20px;
vertical-align: top;
margin-top: 2px;
}
.el-dialog__headerbtn {
width: 20px;
height: 20px;
top: 15px;
right: 14px;
transform: scale(1.2);
}
/* form-style */
.search-form {
background: #12407F;
line-height: 40px;
position: relative;
}
.search-form .el-form-item {
margin: 4px 0 !important;
}
.search-form .el-form-item__label {
font-size: 14px;
color: #60FFF6;
padding-left: 8px;
}
.search-form .el-select {
min-width: 120px;
}
.search-form .el-select__wrapper {
background: #072350;
box-shadow: none;
border: none;
}
.search-form .el-input__wrapper {
background: #072350;
box-shadow: none;
border: none;
}
.search-form .el-date-editor .el-range-separator {
color: #fff;
}
.search-form .el-date-editor.el-input__inner {
background: rgba(6, 53, 114, 1) !important;
border: none;
}
.search-form .el-date-editor .el-range-input {
background-color: transparent !important;
color: #fff;
}
.search-form .el-button--primary {
background: #37CCC4;
margin-left: 10px;
border: none;
}
.search-form .el-form--inline .el-form-item {
vertical-align: top;
}
/* dialog-table style */
.dialog-data-table {
margin-top: 10px;
width: 100%;
}
.dialog-data-table .el-scrollbar__view {
height: 100%;
}
.dialog-data-table:not(.no-minheight) {
flex-grow: 1;
}
.dialog-data-table.el-table th.el-table__cell {
background: #16488B;
}
.dialog-data-table.el-table {
--el-table-border-color: #1F4C89;
}
.table-pagination {
line-height: 50px;
border: 1.5px solid #1F4C89;
border-top: none;
padding: 0 10px;
color: #fff;
justify-content: right;
width: 100%;
box-sizing: border-box;
display: flex;
}
.table-pagination .el-pagination__sizes,
.el-pagination__total,
.el-pagination__jump {
color: #fff;
}
.table-pagination .el-input__inner {
background: transparent;
border: 1px solid rgba(60, 117, 193, 1);
box-shadow: none;
}
.table-pagination .el-input__inner {
color: #fff;
}
.table-pagination.el-pagination button .el-icon {
width: 1em !important;
height: 1em !important;
}
.table-pagination.el-pagination button,
.table-pagination.el-pagination button.is-disabled,
.table-pagination.el-pagination button:disabled {
background-color: transparent;
color: #fff;
line-height: 32px;
vertical-align: top;
}
.table-pagination .el-pager li {
background-color: transparent;
color: #fff;
}
.table-pagination .el-pager li.is-active,
.table-pagination .el-pager li:hover {
color: #409eff;
}
.table-pagination .el-pagination__total {
flex-grow: 1;
}
/* calendar-style */
.el-calendar {
background: transparent;
--el-calendar-border: 1px solid #033168;
}
.el-calendar-table {
border-spacing: 4px;
}
.el-calendar-table thead th {
color: #fff;
}
.el-calendar__body {
padding: 0;
}
.el-calendar-table .el-calendar-day {
height: 40px;
}
.el-calendar-day {
color: #7DFBF4;
border: 1px solid #2857AE;
}
.el-calendar-table td {
background: #0E3779;
}
.el-calendar-day:hover {
background: #16428B !important;
}
.el-calendar-table:not(.is-range) td.next,
.el-calendar-table:not(.is-range) td.prev {
background: #033168 !important;
}
.el-calendar-table td.is-selected {
background: #0E3779 !important;
border: 1px solid #fff !important;
}
.el-calendar__header {
padding: 0;
}
.el-calendar-table thead th {
padding: 4px 0;
}
/* radio style */
.el-radio-button__inner {
background: #072350;
border: none !important;
color: #fff;
}
.el-icon {
width: 20px;
height: 20px;
}
.el-picker-panel__body .el-input__inner {
color: #606266 !important;
}
.el-pagination button,
.el-pagination span:not([class*=suffix]) {
line-height: 50px;
}
.table-pagination.el-pagination button,
.table-pagination.el-pagination button.is-disabled,
.table-pagination.el-pagination button:disabled {
line-height: 50px;
}
.el-pagination button,
.el-pagination span:not([class*=suffix]) {
height: 50px;
}
.el-pager li {
height: 50px;
line-height: 50px;
}
.el-table--border {
border: 1px solid rgba(31, 76, 137, 1) !important;
}
.el-table td.el-table__cell,
.el-table th.el-table__cell.is-leaf {
border-bottom: 1px solid rgba(31, 76, 137, 1) !important;
}
.el-table--border::after,
.el-table--group::after,
.el-table::before {
background-color: rgba(31, 76, 137, 1) !important;
}
.el-table--border .el-table__cell,
.el-table__body-wrapper .el-table--border.is-scrolling-left~.el-table__fixed {
border-right: 1px solid rgba(31, 76, 137, 1) !important;
}
.el-message {
font-size: 14px !important;
}
.el-pager .more::before {
line-height: 50px;
}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
[
{
"name": "龙山街道|fef905b7-7211-4caa-8af5-2e7ddf7932d3",
"value": [
119.89250900,
31.05627900,
15,
"#00ce7c"
]
},
{
"name": "小浦镇|775cb556-7b9e-4e03-9230-08f04d7348b5",
"value": [
119.79350300,
31.02995200,
12,
"#00ce7c"
]
},
{
"name": "林城镇|737e7e89-dd67-49ba-944c-3e6a6dd2ad6a",
"value": [
119.76529000,
30.93043300,
11,
"#00ce7c"
]
},
{
"name": "虹星桥镇|b28f79a3-e427-403e-aa7a-7ee2f4018ed0",
"value": [
119.85721800,
30.90588400,
12,
"#00ce7c"
]
},
{
"name": "洪桥镇|c2def5e2-6ff2-4251-bdf9-342829c24ffb",
"value": [
120.03421500,
30.97812100,
13,
"#00ce7c"
]
},
{
"name": "泗安镇|5ed099d5-bccc-42b4-80ca-5ea37881cfb0",
"value": [
119.65104400,
30.92607000,
12,
"#00ce7c"
]
},
{
"name": "画溪街道|983a5dce-183b-41a8-8f69-b3e5220e428e",
"value": [
119.85284600,
30.97594900,
14,
"#00ce7c"
]
},
{
"name": "太湖街道|f7a12eed-ae8f-4cb6-952d-10f33d08bc52",
"value": [
119.95362900,
31.02751400,
10,
"#00ce7c"
]
},
{
"name": "吕山乡|9604b6b5-5ecb-4a93-9833-c40a90af671d",
"value": [
119.92743100,
30.90016800,
12,
"#00ce7c"
]
},
{
"name": "水口乡|4d6499c6-11d9-4a5f-99e2-188ada5adccd",
"value": [
119.84335400,
31.11564200,
12,
"#00ce7c"
]
},
{
"name": "夹浦镇|34f719fc-b702-477b-a105-b70cc7656ffb",
"value": [
119.92974100,
31.12346500,
11,
"#00ce7c"
]
},
{
"name": "雉城街道|a665a449-04d5-4684-af29-89b9dbfe84e0",
"value": [
119.89859200,
31.00199000,
12,
"#00ce7c"
]
},
{
"name": "李家巷镇|80d53478-1f41-45d4-aefc-91c3281c1a57",
"value": [
119.97091400,
30.95079100,
11,
"#00ce7c"
]
},
{
"name": "和平镇|c1f061a7-0d8e-4aba-ab0e-04bd3b7e8633",
"value": [
119.84728100,
30.80435200,
13,
"#00ce7c"
]
},
{
"name": "煤山镇|d859939e-9bfb-45b8-ab4c-e0b210fb3b89",
"value": [
119.70732600,
31.09870500,
18,
"#00ce7c"
]
}
]
\ No newline at end of file
@font-face {
font-family: "iconfont";
/* Project id 4643432 */
src: url('//at.alicdn.com/t/c/font_4643432_hn8mhtnaszc.woff2?t=1725007580136') format('woff2'),
url('//at.alicdn.com/t/c/font_4643432_hn8mhtnaszc.woff?t=1725007580136') format('woff'),
url('//at.alicdn.com/t/c/font_4643432_hn8mhtnaszc.ttf?t=1725007580136') format('truetype');
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-shujuqueshihuozheziduanqueshi-01:before {
content: "\eac4";
}
.icon-shujuqueshihuozheziduanqueshi-01-2:before {
content: "\eac5";
}
.icon-jinhangzhong:before {
content: "\eac3";
}
.icon-weikaishi:before {
content: "\eac2";
}
.icon-dian-01:before {
content: "\eab7";
}
.icon-dui:before {
content: "\e614";
}
.icon-jurassic_warning:before {
content: "\e696";
}
.icon-daba:before {
content: "\e62f";
}
.icon-shebeixinxi:before {
content: "\e689";
}
.icon-a-Group6922-2:before {
content: "\eab5";
}
.icon--cheliang:before {
content: "\e60a";
}
.icon-dzzw_linquan:before {
content: "\e627";
}
.icon-xiaofangshuiyuan:before {
content: "\e7d5";
}
.icon-a-02-5xiaofangduiwu:before {
content: "\e606";
}
.icon-ren:before {
content: "\eab2";
}
.icon-xianshi-01:before {
content: "\eab1";
}
.icon-yincang-01:before {
content: "\eab0";
}
.icon-paixu:before {
content: "\e600";
}
.icon-xiangshang:before {
content: "\e601";
}
.icon-suoxiao:before {
content: "\e616";
}
.icon-bofang:before {
content: "\e624";
}
.icon-dian_blue:before {
content: "\e7b8";
}
.icon-shangchuan:before {
content: "\e605";
}
.icon-mima1:before {
content: "\e7e2";
}
.icon-zhanghao:before {
content: "\e66d";
}
.icon-tianqi:before {
content: "\e87f";
}
.icon-security:before {
content: "\e667";
}
.icon-taifeng:before {
content: "\e687";
}
.icon-prev-step:before {
content: "\ea85";
}
.icon-next-step:before {
content: "\ea89";
}
.icon-zhanghaoguanli:before {
content: "\e6bb";
}
.icon-weixingyuntu:before {
content: "\e6e7";
}
.icon-fangda:before {
content: "\e60e";
}
.icon-qixiangleida:before {
content: "\e6b8";
}
.icon-jiantou-2:before {
content: "\eaa0";
}
.icon-sanweiditu:before {
content: "\eaa1";
}
.icon-yingxiangditu:before {
content: "\eaa2";
}
.icon-report:before {
content: "\eaa4";
}
.icon-sousuo:before {
content: "\e65a";
}
.icon-shanchu1:before {
content: "\e8b6";
}
.icon-shang-01:before {
content: "\e8e3";
}
.icon-shang-02:before {
content: "\e8e4";
}
.icon-a-huaban2fuben53:before {
content: "\e60f";
}
.icon-xia-01:before {
content: "\e9d4";
}
.icon-shang-011:before {
content: "\e9d5";
}
.icon-zuo-01:before {
content: "\e9d6";
}
.icon-you-01:before {
content: "\e9d7";
}
.icon-you-2-2:before {
content: "\ea37";
}
.icon-you-22:before {
content: "\ea38";
}
.icon-you-23:before {
content: "\ea39";
}
.icon-guanbi-17-2-2:before {
content: "\ea3a";
}
.icon-xia:before {
content: "\ea3b";
}
.icon-ruliriqixiao:before {
content: "\ea60";
}
\ No newline at end of file
This diff is collapsed.
<template>
<div class="nav-header">
<div class="left-nav">
<span>{{ date }} {{ weekDay }} </span>
</div>
<div class="mid-title">
<span>长兴县建设工程质量安全管理站</span>
</div>
<div class="right-nav">
{{ time }}
</div>
</div>
</template>
<script>
import { mapState } from "vuex";
export default {
data() {
return {
date: "",
weekDay: "",
time: "",
};
},
methods: {
getTime() {
let date = new Date();
let year = date.getFullYear();
let month = date.getMonth() + 1;
let day = date.getDate();
month = month > 9 ? month : "0" + month;
day = day < 10 ? "0" + day : day;
let today = year + "年" + month + "月" + day + "日";
this.date = today;
let hour = date.getHours() < 10 ? "0" + date.getHours() : date.getHours();
let min =
date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();
let sec =
date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
this.time = `${hour}:${min}:${sec}`;
let str = "星期";
let weekDay = new Date().getDay();
switch (weekDay) {
case 0:
str += "日";
break;
case 1:
str += "一";
break;
case 2:
str += "二";
break;
case 3:
str += "三";
break;
case 4:
str += "四";
break;
case 5:
str += "五";
break;
case 6:
str += "六";
break;
}
this.weekDay = str;
},
},
mounted() {
setInterval(() => {
this.getTime();
}, 1000);
},
computed: {
...mapState(["userInfo"]),
},
};
</script>
<style lang="less" scoped>
.nav-header {
display: flex;
align-content: center;
line-height: 40px;
padding: 0 30px;
height: 94px;
margin: 0px;
background: url("@/assets/images/index/inmg_toubu_yi@2x.png");
background-repeat: no-repeat;
background-size: 100% 100%;
position: relative;
.left-nav {
width: calc(100% / 3);
display: flex;
justify-content: flex-start;
span {
color: #fff;
font-size: 18px;
}
.weather-img {
vertical-align: top;
width: 30px;
height: 30px;
margin: 24px 0;
margin-right: 30px;
}
}
.mid-title {
width: calc(100% / 3);
font-size: 32px;
color: #fefeff;
text-align: center;
letter-spacing: 3px;
line-height: 70px;
position: relative;
span {
position: absolute;
left: 0;
width: 100%;
height: 100%;
font-weight: bold;
white-space: nowrap;
background-clip: text;
-webkit-text-fill-color: transparent;
background-image: linear-gradient(to bottom, #ffffff, #a4c7e8);
z-index: 999;
}
}
.right-nav {
width: calc(100% / 3);
text-align: right;
font-size: 16px;
color: #fff;
img {
width: 26px;
height: 26px;
vertical-align: top;
border-radius: 50%;
margin-right: 10px;
margin-top: 26px;
object-fit: cover;
}
}
}
</style>
\ No newline at end of file
<template>
<div id="index" style="height: 100%">
<Header></Header>
<div class="route-container">
<router-view></router-view>
</div>
</div>
</template>
<script>
import Header from "./Header";
export default {
name: "Index",
components: { Header },
data() {
return {
time: "",
weekDay: "",
date: "",
zoom: 1,
screenDetail: {},
leftNav: [],
rightNav: [],
childRouteName: "",
totalMenu: [],
};
},
methods: {},
computed: {
token() {
return localStorage.getItem("token");
},
},
mounted() {},
};
</script>
<style scoped lang="less">
#index {
background: url("@/assets/images/background.png") no-repeat;
background-size: 100% 100%;
background-attachment: fixed;
}
.route-container {
position: fixed;
top: 80px;
left: 0;
width: 100%;
height: calc(100% - 80px);
}
.router-change {
position: fixed;
right: 40px;
bottom: 40px;
z-index: 1000;
img {
width: 70px;
height: 70px;
vertical-align: top;
cursor: pointer;
opacity: 0.6;
&:hover {
opacity: 1;
}
}
}
</style>
\ No newline at end of file
<template>
<el-dialog
:visible.sync="dialogVisible"
:class="[isFullScreen ? 'full-screen' : '']"
:append-to-body="true"
:width="width"
top=".98rem"
@close="closeDialog"
:destroy-on-close="true"
>
<template slot="title">
<div class="dialog-title">
<span class="dialog-title-span">
{{ title }}
</span>
<span class="op-buttons">
<i
@click="changeFullScreen"
:class="['iconfont', isFullScreen ? 'icon-suoxiao' : 'icon-fangda']"
></i>
</span>
</div>
</template>
<slot />
</el-dialog>
</template>
<script>
export default {
name: "Dialog",
props: {
visible: {
type: Boolean,
default: false,
},
title: {
type: String,
default: "",
},
width: {
type: [String, Number],
default: 1200,
},
},
data() {
return {
isFullScreen: false,
};
},
computed: {
dialogVisible: {
get() {
return this.visible;
},
set(val) {
this.$emit("change-visible", val);
},
},
},
methods: {
closeDialog() {
console.log("???");
this.dialogVisible = false;
console.log(this.dialogVisible);
},
changeFullScreen() {
this.isFullScreen = !this.isFullScreen;
this.$nextTick(() => {
window.dispatchEvent(new Event("resize"));
});
},
},
};
</script>
<style lang="less" scoped>
.dialog-title {
position: relative;
z-index: 999;
color: #fff;
font-size: 18px;
line-height: 0.22rem;
.op-buttons {
position: absolute;
right: 15px;
top: 0px;
i {
cursor: pointer;
margin-left: 15px;
font-size: 18px;
margin-right: 18px;
padding: 0 12px;
&:hover {
color: #409eff;
}
}
}
}
.dialog-title-span {
position: relative;
}
</style>
\ No newline at end of file
<template>
<div class="data-table-out">
<el-table
border
class="dialog-data-table"
:data="tableData"
v-loading="loading"
:element-loading-background="loadingBG"
height="calc(100% - .5rem)"
>
<el-table-column
v-if="hasIndex"
label="序号"
type="index"
align="center"
></el-table-column>
<template v-for="(column, cIndex) in columns">
<!-- 无插槽 -->
<el-table-column
v-if="!column.hasSlot"
:key="column.prop"
:label="column.label"
:prop="column.prop"
:align="column.align ? column.align : 'center'"
:min-width="column.minWidth ? column.minWidth : ''"
></el-table-column>
<!-- 自定义插槽 -->
<el-table-column
v-else
:key="cIndex"
:label="column.label"
:prop="column.prop"
:align="column.align ? column.align : 'center'"
:min-width="column.minWidth ? column.minWidth : ''"
>
<template #default="scope">
<slot :name="column.prop" :data="scope.row" />
</template>
</el-table-column>
</template>
</el-table>
<el-pagination
v-if="hasPagination"
class="table-pagination"
:current-page="currentPage"
:page-size="pageSize"
:page-sizes="[10, 20, 30, 40, 50]"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</template>
<script>
export default {
name: "DialogApiDataTable",
props: {
api: {
type: Function,
required: true,
},
height: {
type: String,
default: "6rem",
},
columns: {
type: Array,
required: true,
default: () => {
return [];
},
},
parameters: {
type: Object,
default: () => {
return {};
},
},
hasIndex: {
type: Boolean,
default: true,
},
hasPagination: {
type: Boolean,
default: true,
},
autoLoad: {
type: Boolean,
default: true,
},
apiType: {
default: "",
},
pathId: {
default: "",
},
},
data() {
return {
tableData: [],
currentPage: 1,
total: 0,
pageSize: 10,
loadingBG: "rgba(0, 0, 0, 0.2)",
loading: false,
};
},
mounted() {
if (this.autoLoad) {
this.getData();
}
},
methods: {
getData() {
if (this.api) {
this.loading = true;
this.tableData = [];
if (!this.pathId) {
this.api({
...this.parameters,
page: this.currentPage,
limit: this.pageSize,
}).then((res) => {
this.loading = false;
this.tableData = res.data.data;
this.total = res.data.total;
});
} else {
this.api(
{
...this.parameters,
page: this.currentPage,
limit: this.pageSize,
},
this.pathId
).then((res) => {
this.loading = false;
this.tableData = res.data.data;
this.total = res.data.total;
});
}
}
},
handleSizeChange(size) {
this.pageSize = size;
this.handleCurrentChange(1);
},
handleCurrentChange(currentPage) {
this.currentPage = currentPage;
this.getData();
},
},
};
</script>
<style>
.data-table-out {
display: flex;
flex-direction: column;
height: 100%;
}
</style>
\ No newline at end of file
<template>
<div class="dialog-tab">
<div
v-for="tab in tabList"
:key="tab.name"
:class="['tab-pane', currentTab == tab.name ? 'active' : '']"
@click="changeTab(tab.name)"
>
{{ tab.label }}
</div>
<div class="separate-lines">
<div class="separate-line"></div>
<img
class="separate-arrow"
src="@/assets/images/common/icon_tab_arr.png"
/>
</div>
</div>
</template>
<script>
export default {
name: "DialogTabs",
props: {
currentTab: {
type: String,
default: "",
},
tabList: {
type: Array,
default: () => {
return [];
},
},
},
methods: {
changeTab(tabName) {
this.$emit("change", tabName);
},
},
data() {
return {};
},
};
</script>
<style lang="less" scoped>
.dialog-tab {
width: 100%;
display: flex;
justify-content: space-between;
.tab-pane {
font-size: 16px;
color: #82a4e4;
line-height: 20px;
padding: 0 10px;
border-left: 1px solid #2857ae;
cursor: pointer;
&:hover {
color: #fff;
}
&.active {
padding-left: 30px;
position: relative;
color: #fff;
&::before {
position: absolute;
content: "";
width: 4px;
height: 4px;
background: #23ddff;
border: 3px solid #fff;
border-radius: 50%;
left: 10px;
top: 50%;
transform: translateY(-50%);
}
}
}
.separate-lines {
flex-grow: 1;
border-left: 1px solid #2857ae;
display: flex;
align-items: center;
.separate-line {
display: flex;
height: 1px;
background: #2857ae;
flex-grow: 1;
}
.separate-arrow {
width: 20px;
padding-left: 4px;
vertical-align: top;
}
}
}
</style>
\ No newline at end of file
<template>
<div class="s-table">
<div class="table-headers">
<div
v-for="(header, index) in headers"
:key="index"
:style="{
width: header.width ? header.width : '',
...header.style,
}"
>
{{ header.name }}
</div>
</div>
<div
class="table-data"
v-infinite-scroll="load"
:infinite-scroll-distance="1"
:infinite-scroll-delay="1000"
ref="tableData"
>
<div
class="table-data-columns"
v-for="(row, index) in tableData"
:key="index"
@click="rowClick(row)"
>
<div
v-for="(header, hIndex) in headers"
:key="hIndex"
:style="{
width: header.width ? header.width : '',
...header.style,
}"
class="table-data-column"
>
<template v-if="header.slot">
<slot :row="row" :header="header" />
</template>
<template v-else>
<el-tooltip
class="table-data-cell"
effect="dark"
:content="String(row[header.props])"
>
<div style="cursor: pointer">
{{ row[header.props] }}
</div>
</el-tooltip>
</template>
</div>
</div>
<div v-if="!tableData || tableData.length == 0" class="no-data">
<span>暂无数据</span>
</div>
</div>
</div>
</template>
<script>
export default {
name: "STable",
props: {
headers: {
type: Array,
default: () => {
return [];
},
},
tableData: {
type: Array,
default: () => {
return [];
},
},
pagination: {
type: Boolean,
default: false,
},
},
methods: {
load() {
if (this.pagination) {
this.$emit("load");
}
},
rowClick(row) {
this.$emit("row-click", row);
},
},
data() {
return {};
},
mounted() {
this.$refs.tableData.onscroll = () => {
let list = document.getElementsByClassName("el-tooltip__popper");
if (list.length > 0) {
list[list.length - 1].style.display = "none";
}
};
},
};
</script>
<style lang="less" scoped>
.s-table {
height: 100%;
width: calc(100% - 20px);
margin: 0 10px;
}
.table-headers {
line-height: 32px;
color: #afcfed;
font-size: 13px;
text-align: center;
display: flex;
justify-content: space-between;
flex-wrap: nowrap;
background: #19396e;
div {
padding: 0 4px;
}
}
.table-data {
height: calc(100% - 34px);
overflow-y: auto;
background: rgba(25, 57, 110, 0.3);
.table-data-columns {
line-height: 34px;
display: flex;
justify-content: space-between;
flex-wrap: nowrap;
text-align: center;
color: #fff;
font-size: 14px;
&:hover {
background: rgba(25, 57, 110, 1) !important;
}
&:nth-child(2n) {
background: rgba(25, 57, 110, 0.5);
}
.table-data-cell {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
padding: 0 4px;
}
}
}
.no-data {
text-align: center;
color: #fff;
height: 100%;
font-size: 20px;
position: relative;
span {
position: absolute;
left: 50%;
top: 50%;
transform: translateX(-50%) translateY(-50%);
}
}
</style>
\ No newline at end of file
<template>
<div class="section" :style="{ height: height }">
<Title :title="title" v-if="title"> </Title>
<div :class="[title ? 'container' : 'notitle-container']">
<slot />
</div>
</div>
</template>
<script>
export default {
name: "Section",
props: {
title: {
type: String,
default: "",
},
height: {
type: String,
default: "400px",
},
type: {
type: String,
},
},
};
</script>
<style lang="less" scoped>
.notitle-container {
height: 100%;
}
.container {
height: calc(100% - 34px);
}
</style>
\ No newline at end of file
<template>
<div class="title">
{{ title }}
</div>
</template>
<script>
export default {
name: "Title",
props: {
title: {
type: String,
default: "",
},
},
};
</script>
<style lang="less" scoped>
.title {
font-size: 18px;
color: #fff;
line-height: 34px !important;
text-align: left;
padding-left: 20px;
background: url("@/assets/images/common/icon_title.png");
background-repeat: no-repeat;
background-size: 100% 100%;
}
.right-slot {
float: right;
}
</style>
\ No newline at end of file
import Vue from 'vue'
import App from './App.vue'
import router from '@/router/index'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import 'lib-flexible'
import store from "@/store/index"
import * as echarts from "echarts"
import scroll from 'vue-seamless-scroll'
import Title from "@/components/common/Title"
import Section from "@/components/common/Section"
import STable from "@/components/common/STable"
import "@/assets/iconfont/iconfont.css";
import "@/assets/common/common.less"
import "@/assets/common/element.less"
import "@/utils/moment.js"
import Dialog from "@/components/common/Dialog.vue"
import DialogTabs from "@/components/common/DialogTabs.vue"
import DialogApiDataTable from "@/components/common/DialogApiDataTable.vue"
window._AMapSecurityConfig = {
securityJsCode: 'a5006042196de6dda20a434eb443bf45',
}
Vue.use(scroll)
Vue.prototype.$echarts = echarts
Vue.prototype.$eventBus = new Vue();
Vue.config.productionTip = false
Vue.use(ElementUI)
Vue.component('Title', Title)
Vue.component('Section', Section)
Vue.component('STable', STable)
Vue.component('Dialog', Dialog)
Vue.component('DialogTabs', DialogTabs)
Vue.component('DialogApiDataTable', DialogApiDataTable)
new Vue({
render: h => h(App),
store,
router
}).$mount('#app')
import Vue from 'vue'
import VueRouter from 'vue-router'
import Index from "@/components/Index"
import DataStatis from "@/views/DataStatis/Index"
Vue.use(VueRouter)
const router = new VueRouter({
routes: [
{
path: '/', component: Index, redirect: "/dataStatis",
children: [
{
path: '', component: DataStatis,
meta: {
title: '企业检测大屏'
}
},
],
},
]
})
router.beforeEach((to, from, next) => {
if (to.meta.title) {
document.title = to.meta.title
}
next()
})
export default router
\ No newline at end of file
import Vue from 'vue'
import Vuex from "vuex"
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
userInfo: {}
},
getters: {
},
mutations: {
changeUserInfo(state, userInfo) {
state.userInfo = userInfo
}
},
actions: {
}
})
export default store
This diff is collapsed.
import axios from 'axios'
import Vue from 'vue'
import { Message, Loading } from 'element-ui';
import _ from 'lodash';
// loading框设置局部刷新,且所有请求完成后关闭loading框
let loadingInstance; //loading 实例
let needLoadingRequestCount = 0; //当前正在请求的数量
// import { getAccess } from "@/api/index"
// import md5 from "js-md5"
axios.defaults.maxRedirects = 0
function showLoading() {
let main = document.querySelector('#app') //获取dom节点
if (main) {
if (needLoadingRequestCount === 0 && !loadingInstance) {
loadingInstance = Loading.service({
target: main, text: '正在加载...', background: 'rgba(0,0,0,0.6)', spinner: 'el-icon-loading'
});
}
needLoadingRequestCount++;
}
}
function closeLoading() {
Vue.nextTick(() => { // 以服务的方式调用的 Loading 需要异步关闭
needLoadingRequestCount--;
needLoadingRequestCount = Math.max(needLoadingRequestCount, 0); // 保证大于等于0
if (needLoadingRequestCount === 0) {
if (loadingInstance) {
hideLoading()
}
}
});
}
//防抖
var hideLoading = _.debounce(() => {
loadingInstance.close();
loadingInstance = null;
}, 10);
const request = axios.create({
withCredentials: false,
maxRedirects: 0
// baseURL: process.env.VUE_APP_API_URL
})
request.interceptors.request.use(
config => {
const Authorization = localStorage.getItem('Authorization')
if (Authorization) {
config.headers['Authorization'] = Authorization
}
if (!config.noloading) {
showLoading()
}
return config
},
error => {
closeLoading()
return Promise.reject(new Error(error).message)
}
)
request.interceptors.response.use(
response => {
console.log(response)
closeLoading()
if (response.data.status != 200) {
Message({
message: response.data.msg,
type: 'error'
})
}
return response.data
},
async (error) => {
console.log(error)
if (error.request.status == 401) {
// closeLoading()
// localStorage.setItem('Authorization', '')
// var config = error.config
// var data = {
// api_key: 10012,
// timestamp: new Date().getTime(),
// sign: md5(
// `api_key${10012}timestamp${new Date().getTime()}${"757D0789-8971-4E6E-872E-1C471A672102"}`
// ),
// };
// getAccess(data).then((res) => {
// if (res.status == 200) {
// localStorage.setItem("Authorization", `${res.data.token_type} ${res.data.access_token}`);
// }
// });
// var backoff = new Promise((resolve) => {
// setTimeout(() => {
// resolve();
// }, 1);
// });
// // 再次发送请求
// return backoff.then(() => {
// return request(config);
// });
}
Message({
message: '服务器错误',
type: 'error'
})
return Promise.reject(new Error(error).message)
}
)
export default request
This diff is collapsed.
<template>
<Dialog
title="工程列表"
:visible="dialogVisible"
width="70%"
@change-visible="changeVisible"
>
<div class="dialog-body-container">
<el-form inline :model="searchForm" class="search-form">
<el-form-item label="区域:">
<el-select v-model="searchForm.project_place1" clearable>
<el-option
v-for="region in regions"
:label="region.name"
:value="region.id"
:key="region.id"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="扬尘监测:">
<el-select v-model="searchForm.noise_status" clearable>
<el-option label="已接入" value="1"></el-option>
<el-option label="未接入" value="0"></el-option>
</el-select>
</el-form-item>
<el-form-item label="视频监控:">
<el-select v-model="searchForm.monitor_status" clearable>
<el-option label="已接入" value="1"></el-option>
<el-option label="未接入" value="0"></el-option>
</el-select>
</el-form-item>
<el-form-item label="施工单位:">
<el-input v-model="searchForm.unit_name"></el-input>
</el-form-item>
<el-form-item label="工程名称:">
<el-input v-model="searchForm.project_name"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSearch">查询</el-button>
</el-form-item>
</el-form>
<DialogApiDataTable
:has-index="true"
ref="table"
:columns="columns"
:parameters="searchForm"
:api="api"
:auto-load="false"
>
<template #noise_status="{ data }">
<img
class="icon-img"
v-if="data.noise_status == 1"
src="@/assets/images/common/pm10-icon-active.png"
alt=""
@click="openProjectDetail('Dust', data)"
/>
<img
class="icon-img"
v-else
src="@/assets/images/common/pm10-icon.png"
alt=""
@click="showErrPm"
/>
</template>
<template #monitor_status="{ data }">
<img
class="icon-img"
v-if="data.monitor_status == 1"
src="@/assets/images/common/video-icon-active.png"
alt=""
@click="openProjectDetail('VideoSupervisory', data)"
/>
<img
class="icon-img"
v-else
src="@/assets/images/common/video-icon.png"
alt=""
@click="showErrVideo"
/>
</template>
</DialogApiDataTable>
</div>
<ProjectDialog
v-if="projectDialogVisible"
:visible="projectDialogVisible"
:project-name="currentProjectName"
:project-id="projectId"
@change-visible="(val) => (projectDialogVisible = val)"
></ProjectDialog>
</Dialog>
</template>
<script>
import { getRegions, getProjectList } from "@/api/index";
import ProjectDialog from "@/views/DataStatis/project/Index.vue";
export default {
name: "ProjectListDialog",
components: { ProjectDialog },
props: {
visible: {
type: Boolean,
default: false,
},
areaId: {
type: [String, Number],
default: "",
},
},
data() {
return {
regions: [],
searchForm: {},
columns: [
{ label: "区域", prop: "project_region_name" },
{ label: "工程名称", prop: "project_name" },
{ label: "施工单位", prop: "sg_unit_name" },
{ label: "面积(㎡)", prop: "area" },
{ label: "造价(万元)", prop: "project_currency" },
{ label: "扬尘监测", prop: "noise_status", hasSlot: true },
{ label: "视频监控", prop: "monitor_status", hasSlot: true },
],
api: getProjectList,
projectDialogVisible: false,
currentProjectName: "",
projectId: "",
};
},
computed: {
dialogVisible: {
get() {
return this.visible;
},
set(val) {
this.$emit("change-visible", val);
},
},
},
methods: {
changeVisible(val) {
console.log(val);
this.dialogVisible = val;
},
handleSearch() {
this.$refs.table.getData();
},
showErrPm() {
this.$message.error("扬尘暂未接入");
},
showErrVideo() {
this.$message.error("视频暂未接入");
},
openProjectDetail(type, data) {
this.currentProjectName = data.project_name;
this.projectId = data.id;
this.projectDialogVisible = true;
this.$eventBus.$emit("switchTab", type);
},
},
mounted() {
getRegions().then((res) => {
this.regions = res.data;
});
},
watch: {
visible(val) {
if (val) {
this.searchForm = {
project_place1: this.areaId,
};
this.$nextTick(() => {
this.$refs.table.getData();
});
}
},
},
};
</script>
<style lang="less" scoped>
::v-deep .search-form .el-select {
width: 100px !important;
}
::v-deep .el-input .el-input__inner {
background: #072350 !important;
border: none !important;
font-size: 14px;
color: rgba(255, 255, 255, 0.7);
}
.dialog-body-container {
height: calc(100% - 50px);
}
.icon-img {
width: 50px;
vertical-align: top;
cursor: pointer;
}
</style>
\ No newline at end of file
<template>
<div class="project-info">
<div class="title">
数据更新时间
<span class="history" @click="historyVisible = true">查看历史记录</span>
<HistoryDust
:visible="historyVisible"
:project-id="projectId"
@change-visible="(val) => (historyVisible = val)"
></HistoryDust>
</div>
<div class="info">
<div class="dust-bg">
<div class="temp">
<img src="@/assets/images/common/temp.png" alt="" />
<div class="label">当前温度</div>
<div class="value">{{ noiseData.temperature }}</div>
</div>
<div class="temp">
<img src="@/assets/images/common/humidy.png" alt="" />
<div class="label">当前湿度</div>
<div class="value">{{ noiseData.humidity }}%</div>
</div>
</div>
<div class="dust-bg values-inline">
<div class="lt-label">
<div class="great" v-if="noiseData.pm25.qualified == 0"></div>
<div class="good" v-else-if="noiseData.pm25.qualified == 1"></div>
<div class="bad" v-else-if="noiseData.pm25.qualified == 2"></div>
<div class="label">当前 PM2.5 值为</div>
<div
:class="[
'value',
noiseData.pm25.qualified == 0
? 'great-value'
: noiseData.pm25.qualified == 1
? 'good-value'
: 'bad-value',
]"
>
{{ noiseData.pm25.pm25 }} <span class="unit">ug/m³</span>
</div>
</div>
<div class="rt-label">
<div>
<div>
<div class="great tip"></div>
扬尘值0-35ug/m3
</div>
<div>
<div class="good tip"></div>
扬尘值36-75ug/m3
</div>
<div>
<div class="bad tip"></div>
扬尘值>75ug/m3
</div>
</div>
</div>
</div>
<div class="dust-bg values-inline">
<div class="lt-label">
<div class="great" v-if="noiseData.pm10.qualified == 0"></div>
<div class="good" v-else-if="noiseData.pm10.qualified == 1"></div>
<div class="bad" v-else-if="noiseData.pm10.qualified == 2"></div>
<div class="label">当前 PM10 值为</div>
<div
:class="[
'value',
noiseData.pm10.qualified == 0
? 'great-value'
: noiseData.pm10.qualified == 1
? 'good-value'
: 'bad-value',
]"
>
{{ noiseData.pm10.pm10 }} <span class="unit">ug/m³</span>
</div>
</div>
<div class="rt-label">
<div>
<div>
<div class="great tip"></div>
浓度值0-50ug/m3
</div>
<div>
<div class="good tip"></div>
浓度值51-150ug/m3
</div>
<div>
<div class="bad tip"></div>
浓度值>150ug/m3
</div>
</div>
</div>
</div>
<div class="dust-bg values-inline">
<div class="lt-label">
<div class="great" v-if="noiseData.noise.qualified == 0"></div>
<div class="good" v-else-if="noiseData.noise.qualified == 1"></div>
<div class="bad" v-else-if="noiseData.noise.qualified == 2"></div>
<div class="label">当前 噪音 值为</div>
<div
:class="[
'value',
noiseData.pm25.qualified == 0
? 'great-value'
: noiseData.pm25.qualified == 1
? 'good-value'
: 'bad-value',
]"
>
{{ noiseData.noise.noise }} <span class="unit">dB</span>
</div>
</div>
<div class="rt-label">
<div>
<div>
<div class="great tip"></div>
噪音值0-40dB
</div>
<div>
<div class="good tip"></div>
噪音值41-70dB
</div>
<div>
<div class="bad tip"></div>
噪音值>70dB
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { getRealTimeDustData } from "@/api/index";
import HistoryDust from "./HistoryDust.vue";
export default {
components: { HistoryDust },
props: {
projectId: {
type: [Number, String],
default: "",
},
},
data() {
return {
noiseData: {
noise: {},
pm10: {},
pm25: {},
},
historyVisible: false,
};
},
mounted() {
getRealTimeDustData(this.projectId).then((res) => {
this.noiseData = res.data;
});
},
};
</script>
<style lang="less" scoped>
.project-info {
padding-top: 16px;
}
.title {
background: #0e4092;
line-height: 36px;
padding-left: 22px;
color: #fff;
font-size: 14px;
position: relative;
&::before {
content: "";
position: absolute;
width: 3px;
height: 16px;
background: #f99b2d;
left: 10px;
top: 10px;
}
.history {
float: right;
cursor: pointer;
margin-right: 20px;
}
}
.info {
background: #072c5d;
padding: 30px;
}
.dust-bg {
background: url("@/assets/images/index/dust-bg.png");
background-repeat: no-repeat;
background-size: 100% 100%;
height: 130px;
width: 100%;
padding: 30px 0;
margin-bottom: 30px;
&:last-child {
margin-bottom: 0;
}
}
.temp {
display: flex;
justify-content: center;
align-items: center;
width: 50%;
img {
width: 50px;
}
.label {
padding-left: 60px;
padding-right: 100px;
}
.value {
color: #22c3ed;
font-size: 24px;
font-weight: bold;
}
&:first-child {
border-right: 1px solid #7e8ed4;
}
}
.dust-bg {
display: flex;
justify-content: center;
font-size: 16px;
color: #fff;
}
.great {
background: rgba(19, 169, 86, 0.3);
border-radius: 4px;
border: 1px solid #13a956;
color: #1ecc6c;
font-size: 16px;
line-height: 24px;
width: 54px;
text-align: center;
display: inline-block;
}
.good {
background: rgba(205, 111, 29, 0.3);
border-radius: 4px;
border: 1px solid #cd6f1d;
color: #e17e27;
font-size: 16px;
line-height: 24px;
width: 54px;
text-align: center;
display: inline-block;
}
.bad {
background: rgba(219, 68, 53, 0.3);
border-radius: 4px;
border: 1px solid #db4435;
color: #db4435;
font-size: 16px;
line-height: 24px;
width: 54px;
text-align: center;
display: inline-block;
}
.lt-label,
.rt-label {
width: 50%;
}
.lt-label {
display: flex;
justify-content: center;
align-items: center;
border-right: 1px solid #7e8ed4;
.label {
padding-left: 60px;
padding-right: 40px;
font-size: 16px;
}
.value {
font-size: 24px;
.unit {
font-size: 16px;
}
}
}
.rt-label {
display: flex;
justify-content: center;
align-items: center;
}
.tip {
margin-right: 10px;
margin-bottom: 4px;
}
.great-value {
color: #1ecc6c;
}
.good-value {
color: #e17e27;
}
.bad-value {
color: #ff6151;
}
</style>
\ No newline at end of file
<template>
<Dialog
title="扬尘监测历史记录"
:visible="dialogVisible"
width="70%"
@change-visible="changeVisible"
>
<div class="dialog-body-container">
<el-form inline :model="searchForm" class="search-form">
<el-form-item label="时间:">
<el-date-picker
v-model="dateRange"
type="daterange"
start-placeholder="开始时间"
end-placeholder="结束时间"
value-format="yyyy-MM-dd"
@change="changeTime"
/>
</el-form-item>
<el-form-item label="噪音:">
<el-select v-model="searchForm.noise_status" clearable>
<el-option label="正常" value="0"></el-option>
<el-option label="超标" value="1"></el-option>
</el-select>
</el-form-item>
<el-form-item label="PM2.5:">
<el-select v-model="searchForm.pm25_status" clearable>
<el-option label="正常" value="0"></el-option>
<el-option label="超标" value="1"></el-option>
</el-select>
</el-form-item>
<el-form-item label="PM10:">
<el-select v-model="searchForm.pm10_status" clearable>
<el-option label="正常" value="0"></el-option>
<el-option label="超标" value="1"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSearch">查询</el-button>
</el-form-item>
</el-form>
<DialogApiDataTable
:has-index="true"
ref="table"
:columns="columns"
:parameters="searchForm"
:api="api"
:auto-load="false"
:path-id="projectId"
>
<template #pm25="{ data }">
<span
:class="[
data.pm25_qualified == 0
? 'green'
: data.pm25_qualified == 1
? 'yellow'
: 'red',
]"
>
{{ data.pm25 }}
</span>
</template>
<template #pm10="{ data }">
<span
:class="[
data.pm10_qualified == 0
? 'green'
: data.pm10_qualified == 1
? 'yellow'
: 'red',
]"
>
{{ data.pm10 }}
</span>
</template>
<template #noise="{ data }">
<span
:class="[
data.noise_qualified == 0
? 'green'
: data.noise_qualified == 1
? 'yellow'
: 'red',
]"
>
{{ data.pm10 }}
</span>
</template>
</DialogApiDataTable>
</div>
</Dialog>
</template>
<script>
import { getDustHistory } from "@/api/index";
export default {
name: "HistoryDust",
props: {
visible: {
type: Boolean,
default: false,
},
projectId: {
type: [String, Number],
default: "",
},
},
data() {
return {
searchForm: {},
dateRange: [],
columns: [
{ label: "更新时间", prop: "update_time" },
{ label: "温度(℃)", prop: "temperature" },
{ label: "湿度/%", prop: "humidity" },
{ label: "PM2.5/ug/m³", prop: "pm25", hasSlot: true },
{ label: "PM10/ug/m³", prop: "pm10", hasSlot: true },
{ label: "噪音/dB", prop: "noise", hasSlot: true },
],
api: getDustHistory,
};
},
computed: {
dialogVisible: {
get() {
return this.visible;
},
set(val) {
this.$emit("change-visible", val);
},
},
},
methods: {
changeVisible(val) {
console.log(val);
this.dialogVisible = val;
},
handleSearch() {
this.$refs.table.getData();
},
changeTime(tr) {
this.searchForm.date_value_start = tr[0] ? tr[0] : "";
this.searchForm.date_value_end = tr[1] ? tr[1] : "";
},
},
watch: {
visible(val) {
if (val) {
this.$nextTick(() => {
this.$refs.table.getData();
});
}
},
},
};
</script>
<style lang="less" scoped>
::v-deep .search-form .el-select {
width: 100px !important;
}
::v-deep .el-input .el-input__inner {
background: #072350 !important;
border: none !important;
font-size: 14px;
color: rgba(255, 255, 255, 0.7);
}
.dialog-body-container {
height: calc(100% - 50px);
}
.icon-img {
width: 50px;
vertical-align: top;
cursor: pointer;
}
.green {
color: #1ecc6c;
}
.yellow {
color: #e17e27;
}
.red {
color: #ff6151;
}
</style>
\ No newline at end of file
<template>
<Dialog
:title="projectName"
:visible="dialogVisible"
width="70%"
@change-visible="changeVisible"
>
<DialogTabs
:tabList="tabList"
:currentTab="currentTabNow"
@change="(val) => changeTab(val)"
></DialogTabs>
<component :is="currentTabNow" :project-id="projectId"></component>
</Dialog>
</template>
<script>
import ProjectDetail from "./ProjectDetail.vue";
import Dust from "./Dust.vue";
import VideoSupervisory from "./VideoSupervisory.vue";
import WarningMsg from "./WarningMsg.vue";
export default {
name: "ProjectDialog",
components: { ProjectDetail, Dust, VideoSupervisory, WarningMsg },
props: {
projectName: {
type: String,
default: "",
},
visible: {
type: Boolean,
default: false,
},
projectId: {
type: [Number, String],
default: "",
},
},
data() {
return {
tabList: [
{ name: "ProjectDetail", label: "项目概况" },
{ name: "Dust", label: "扬尘监测" },
{ name: "VideoSupervisory", label: "视频监控" },
{ name: "WarningMsg", label: "预警信息" },
],
currentTabNow: "ProjectDetail",
};
},
computed: {
dialogVisible: {
get() {
return this.visible;
},
set(val) {
this.$emit("change-visible", val);
},
},
},
methods: {
changeTab(e) {
this.currentTabNow = e;
},
changeVisible(val) {
console.log(val);
this.dialogVisible = val;
},
},
mounted() {
this.$eventBus.$on("switchTab", (type) => {
this.$nextTick(() => {
this.currentTabNow = type;
});
});
},
};
</script>
<style lang="less" scoped>
</style>
\ No newline at end of file
<template>
<div class="project-info">
<div class="title">基本信息</div>
<div class="info">
<div class="data long">
<div class="label">工程名称:</div>
<div class="value">{{ projectDetail.project_name }}</div>
</div>
<div class="data">
<div class="label">建设性质:</div>
<div class="value">{{ projectDetail.project_kind_name }}</div>
</div>
<div class="data long">
<div class="label">工程地址:</div>
<div class="value">{{ projectDetail.project_address }}</div>
</div>
<div class="data">
<div class="label">受理日期:</div>
<div class="value">{{ projectDetail.create_date }}</div>
</div>
<div class="data">
<div class="label">工程进度:</div>
<div class="value">{{ projectDetail.state_name }}</div>
</div>
<div class="data">
<div class="label">工程属性:</div>
<div class="value"></div>
</div>
<div class="data">
<div class="label">工程建设规划许可证:</div>
<div class="value">{{ projectDetail.licence_no }}</div>
</div>
<div class="data">
<div class="label">施工许可证:</div>
<div class="value">{{ projectDetail.sg_no }}</div>
</div>
<div class="data">
<div class="label">工程范围:</div>
<div class="value">{{ projectDetail.area1 }}</div>
</div>
<div class="data">
<div class="label">工程投资性质:</div>
<div class="value">{{ projectDetail.invest_type_name }}</div>
</div>
<div class="data">
<div class="label">工程类型:</div>
<div class="value">{{ projectDetail.project_type_name }}</div>
</div>
<div class="data">
<div class="label">结构类型:</div>
<div class="value">{{ projectDetail.structure_name }}</div>
</div>
<div class="data">
<div class="label">基础类型:</div>
<div class="value">{{ projectDetail.project_base_name }}</div>
</div>
<div class="data">
<div class="label">层高(最高层):</div>
<div class="value">{{ projectDetail.floor_kind }}</div>
</div>
<div class="data">
<div class="label">单层最高高度:</div>
<div class="value">{{ projectDetail.monolayer_height }}</div>
</div>
<div class="data">
<div class="label">总层高:</div>
<div class="value">{{ projectDetail.buildind_height }}</div>
</div>
<div class="data">
<div class="label">总面积:</div>
<div class="value">{{ projectDetail.area_covered }}</div>
</div>
<div class="data">
<div class="label">地上面积:</div>
<div class="value">{{ projectDetail.ground_area }}</div>
</div>
<div class="data">
<div class="label">地下面积:</div>
<div class="value">{{ projectDetail.underground_area }}</div>
</div>
<div class="data">
<div class="label">总用地面积:</div>
<div class="value">{{ projectDetail.area_covered }}</div>
</div>
<div class="data">
<div class="label">造价(万元):</div>
<div class="value">{{ projectDetail.project_currency }}</div>
</div>
<div class="data">
<div class="label">质量创优目标:</div>
<div class="value">{{ projectDetail.quality_target }}</div>
</div>
<div class="data">
<div class="label">安全管理目标:</div>
<div class="value">{{ projectDetail.safety_target }}</div>
</div>
<div class="data">
<div class="label">红色工地:</div>
<div class="value">{{ projectDetail.red_site ? "是" : "否" }}</div>
</div>
<div class="data">
<div class="label">附件表:</div>
<div class="value">
<span class="blue" @click="openPdf(projectDetail.red_site_file_url)">
{{ projectDetail.red_site_file }}
</span>
</div>
</div>
<div class="data">
<div class="label">设计文件审查机构:</div>
<div class="value">{{ projectDetail.censor_name }}</div>
</div>
<div class="data">
<div class="label">审查报告编号:</div>
<div class="value">{{ projectDetail.censor_report_no }}</div>
</div>
<div class="data">
<div class="label">图审单位资质等级:</div>
<div class="value">{{ projectDetail.censor_level }}</div>
</div>
<div class="data">
<div class="label">监理标段编号:</div>
<div class="value">{{ projectDetail.jl_segment_id }}</div>
</div>
<div class="data">
<div class="label">施工标段编号:</div>
<div class="value">{{ projectDetail.sg_segment_id }}</div>
</div>
<div class="data">
<div class="label">分拆单位数:</div>
<div class="value">{{ projectDetail.split_units }}</div>
</div>
<div class="data">
<div class="label">设计使用年限:</div>
<div class="value">{{ projectDetail.fix_year_text }}</div>
</div>
<div class="data">
<div class="label">工程用途:</div>
<div class="value">{{ projectDetail.proj_purpose }}</div>
</div>
<div class="data">
<div class="label">保险公司:</div>
<div class="value">{{ projectDetail.insurance_company }}</div>
</div>
<div class="data">
<div class="label">保险费:</div>
<div class="value">{{ projectDetail.insurance_premium }}</div>
</div>
<div class="data">
<div class="label">是否节能工程:</div>
<div class="value">{{ projectDetail.issave ? "是" : "否" }}</div>
</div>
<div class="data">
<div class="label">是否财政工程:</div>
<div class="value">{{ projectDetail.isfinance ? "是" : "否" }}</div>
</div>
<div class="data">
<div class="label">是否重点工程:</div>
<div class="value">{{ projectDetail.iskeypro ? "是" : "否" }}</div>
</div>
<div class="data">
<div class="label">工程监管类别:</div>
<div class="value">{{ projectDetail.supervise_kind }}</div>
</div>
<div class="data">
<div class="label">注册登记资料:</div>
<div class="value">{{ projectDetail.reg_data }}</div>
</div>
<div class="data">
<div class="label">是否有超危分部分项工程:</div>
<div class="value">{{ projectDetail.isdanger ? "是" : "否" }}</div>
</div>
<div class="data">
<div class="label">工程计划时间:</div>
<div class="value">
{{ projectDetail.start_date }}~{{ projectDetail.complete_date }}
</div>
</div>
</div>
<template
v-if="projectDetail.unitList && projectDetail.unitList.length > 0"
>
<div class="title">参建单位</div>
<div class="info">
<template v-for="unit in projectDetail.unitList">
<div class="data" :key="unit.id + 'project_name'">
<div class="label">{{ unit.unit_kind_title }}</div>
<div class="value">{{ unit.unit_name }}</div>
</div>
<div class="data" :key="unit.id + 'role_name'">
<div class="label">岗位名称:</div>
<div class="value">{{ unit.post_name }}</div>
</div>
<div class="data" :key="unit.id + 'contact'">
<div class="label">联系人:</div>
<div class="value">{{ unit.contacts }}</div>
</div>
</template>
</div>
</template>
</div>
</template>
<script>
import { getProjectDetail } from "@/api/index";
export default {
props: {
projectId: {
type: [Number, String],
default: "",
},
},
data() {
return {
projectDetail: {},
};
},
methods: {
getProjectDetail() {
getProjectDetail(25444).then((res) => {
this.projectDetail = res.data;
});
},
openPdf(url) {
window.open(url);
},
},
mounted() {
console.log(this.projectId);
this.getProjectDetail();
},
};
</script>
<style lang="less" scoped>
.project-info {
padding-top: 16px;
}
.title {
background: #0e4092;
line-height: 36px;
padding-left: 22px;
color: #fff;
font-size: 14px;
position: relative;
&::before {
content: "";
position: absolute;
width: 3px;
height: 16px;
background: #f99b2d;
left: 10px;
top: 10px;
}
}
.info {
background: #072c5d;
padding: 12px 20px;
margin-bottom: 10px;
display: flex;
flex-wrap: wrap;
.data {
width: calc(100% / 3);
display: flex;
justify-content: flex-start;
font-size: 14px;
line-height: 28px;
&.long {
width: calc(100% / 3 * 2);
}
.label {
color: rgba(189, 201, 214, 1);
}
.value {
color: #fff;
}
}
}
.blue {
color: #0178ff;
&:hover {
cursor: pointer;
}
}
</style>
\ No newline at end of file
This diff is collapsed.
<template>
<div class="dialog-body-container">
<el-form inline :model="searchForm" class="search-form">
<el-form-item label="时间:">
<el-date-picker
v-model="dateRange"
type="daterange"
start-placeholder="开始时间"
end-placeholder="结束时间"
value-format="yyyy-MM-dd"
@change="changeTime"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSearch">查询</el-button>
</el-form-item>
</el-form>
<DialogApiDataTable
:has-index="true"
ref="table"
:columns="columns"
:parameters="searchForm"
:api="api"
:path-id="projectId"
>
</DialogApiDataTable>
</div>
</template>
<script>
import { getWarningList } from "@/api/index";
export default {
name: "WarningMsg",
props: {
projectId: {
type: [String, Number],
default: "",
},
},
data() {
return {
searchForm: {},
columns: [
{ label: "预警时间", prop: "record_time" },
{ label: "设备编号", prop: "device_sn" },
{ label: "预警内容", prop: "warning_msg" },
],
dateRange: [],
api: getWarningList,
};
},
mounted() {},
methods: {
handleSearch() {
this.$refs.table.getData();
},
openPdf(url) {
window.open(url);
},
changeTime(tr) {
this.searchForm.start_time = tr[0] ? tr[0] : "";
this.searchForm.end_time = tr[1] ? tr[1] : "";
},
},
};
</script>
<style lang="less" scoped>
.search-form {
margin: 20px 0 10px 0;
}
.blue {
color: #0178ff;
&:hover {
cursor: pointer;
}
}
.dialog-body-container {
display: flex;
flex-direction: column;
height: 100%;
}
</style>
\ No newline at end of file
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
productionSourceMap: false,
css: {
loaderOptions: {
postcss: {
postcssOptions: {
plugins: [
require('postcss-plugin-px2rem')({
rootValue: 100,
mediaQuery: false, //(布尔值)允许在媒体查询中转换px。
minPixelValue: 0 //设置要替换的最小像素值(3px会被转rem)。 默认 0
}),
]
}
}
}
},
publicPath: process.env.NODE_ENV == 'production' ? './' : '/', // 二级根目录需要修改
devServer: {
port: 3000,
proxy: {
'/wisdom': {
target: 'http://192.168.0.57:8011/',
changeOrigin: true,
},
}
},
lintOnSave: true,
pluginOptions: {
"style-resources-loader": {
preProcessor: "less",
patterns: []
}
},
chainWebpack: (config) => {
config.module
.rule('css')
.test(/\.css$/)
.oneOf('vue')
.resourceQuery(/\?vue/)
.use('px2rem')
.loader('px2rem-loader')
.options({
remUnit: 100,
})
}
})
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment