Compare commits

...

11 Commits

Author SHA1 Message Date
DESKTOP-VMMLSOQ\wangzg 958177952f 增加倾斜摄影 2025-04-04 21:43:51 +08:00
DESKTOP-VMMLSOQ\wangzg a249052559 11111 2024-08-29 23:23:37 +08:00
DESKTOP-VMMLSOQ\wangzg 28471a4fef 11 2024-08-25 20:46:06 +08:00
wangzg fefd70a01a 11 2024-08-22 23:55:47 +08:00
wangzg 0f47c609e7 Merge branch 'v2' of https://gitee.com/wangzhigang11/fm-front into v2
# Conflicts:
#	README.md
#	pages/test.vue
#	pages/web3/index.vue
#	pages/wuzuzhi/environment.vue
#	pages/wuzuzhi/home.vue
#	pages/wuzuzhi/huanjingzhili.vue
#	pages/wuzuzhi/list.vue
2024-08-22 22:29:20 +08:00
DESKTOP-VMMLSOQ\wangzg 6616b60bf4 1111 2024-08-19 22:26:28 +08:00
DESKTOP-VMMLSOQ\wangzg 432199be72 111 2024-08-19 07:14:54 +08:00
DESKTOP-VMMLSOQ\wangzg 7da697bdc2 111 2024-08-07 23:44:13 +08:00
DESKTOP-VMMLSOQ\wangzg 6d2ae6196b 111 2024-08-06 22:30:41 +08:00
DESKTOP-VMMLSOQ\wangzg 790e9a7ef0 111 2024-08-06 00:17:35 +08:00
wangzg 25c5c9e95c 111 2024-07-03 10:31:16 +08:00
52 changed files with 13551 additions and 885 deletions

View File

@ -1,4 +1,4 @@
# school-front
# 朋义矿场一体化平台
## Build Setup
@ -41,41 +41,46 @@ https://1x.antdv.com/components/icon/
## 路由说明
登录页 /login
登录页 /login 对接完成
### 管理页
用户管理 /manager/user
角色管理 /manager/role
菜单管理 /manager/menu
设备管理 /manager/device
工序管理 /manager/organized
用户管理 /manager/user 对接完成
角色管理 /manager/role 对接完成
菜单管理 /manager/menu 对接完成
设备管理 /manager/device 对接完成
工序管理 /manager/organized 对接完成
### 用户端
首页 /home
#### 有组织
有组织排放 /youzuzhi/paifang 待联调
有组织排放统计 /youzuzhi/paifangtongji 待联调
有组织排放 /youzuzhi/paifang 缺少排放源清单接口
有组织排放统计 /youzuzhi/paifangtongji 待联调 接口暂无
#### 无组织
无组织排放 /wuzuzhi/paifang 待联调
洗车机管理 /wuzuzhi/xichejiguanli (已做)待联调
环境治理 /wuzuzhi/huanjingzhili 待联调
环卫巡航 /wuzuzhi/huanweixunhang (已做)待联调
无组织排放 /wuzuzhi/paifang 待联调 接口暂无
洗车机管理 /wuzuzhi/xichejiguanli 待联调 缺少导出接口 监控信息 运行信息
环境治理 /wuzuzhi/huanjingzhili 待联调 缺少 实时数据的接口
环卫巡航 /wuzuzhi/huanweixunhang 待联调
#### 清洁运输
清洁运输 /cleanTravel/home
厂区车辆台账 /cleanTravel/ledger
清洁运输趋势 /cleanTravel/trend
磅秤台账 /cleanTravel/bangcheng (已做)待联调
清洁运输 /cleanTravel/home 联调完成
厂区车辆台账 /cleanTravel/ledger 联调完成
清洁运输趋势 /cleanTravel/trend 待联调 /api/Transport/gettransport
磅秤台账 /cleanTravel/bangcheng 待联调 不要了
#### 视频广场
视频广场 /video/list 未做
访问地址

View File

@ -42,3 +42,85 @@
}
}
}
.event-none {
pointer-events: none;
}
.event-auto {
pointer-events: auto;
}
.bottom-btn {
position: absolute;
.event-auto;
width: 100%;
bottom: 0;
left: 0;
}
.custom-tab {
.ant-tabs-ink-bar {
background: rgba(120, 240, 253, 1);
}
.ant-tabs-nav .ant-tabs-tab-active {
color: #fff;
}
.ant-tabs-bar {
margin: 0;
}
.ant-tabs-nav {
color: #fff;
}
.ant-tabs-nav-wrap {
background: linear-gradient(90deg, rgba(0, 107, 207, 0.4) 0%, rgba(0, 128, 247, 0.08) 100%) !important;
}
.ant-tabs-nav-scroll {
background: linear-gradient(90deg, rgba(0, 107, 207, 0.4) 0%, rgba(0, 128, 247, 0.08) 100%) !important;
}
}
.visual_datepicker {
.ant-input {
background-color: rgba(5, 38, 93, 1);
color: #fff;
}
}
.visual_dropdown_cls {
.ant-calendar-today .ant-calendar-date {
color: #fff;
font-weight: bold;
border-color: #fff;
}
.ant-calendar-picker-container {
color: #fff;
}
.ant-calendar-input {
background-color: rgba(5, 38, 93, 1);
color: #fff;
}
.ant-calendar {
background-color: rgba(5, 38, 93, 1);
color: #fff;
border: 1px solid rgba(5, 38, 93, 0.5);
}
.ant-calendar-date, .ant-calendar-header .ant-calendar-prev-century-btn, .ant-calendar-header .ant-calendar-next-century-btn, .ant-calendar-header .ant-calendar-prev-decade-btn, .ant-calendar-header .ant-calendar-next-decade-btn, .ant-calendar-header .ant-calendar-prev-month-btn, .ant-calendar-header .ant-calendar-next-month-btn, .ant-calendar-header .ant-calendar-prev-year-btn, .ant-calendar-header .ant-calendar-next-year-btn, .ant-calendar-header .ant-calendar-century-select, .ant-calendar-header .ant-calendar-decade-select, .ant-calendar-header .ant-calendar-year-select, .ant-calendar-header .ant-calendar-month-select {
color: #fff !important;
}
.ant-calendar-range .ant-calendar-in-range-cell::before {
background-color: rgba(20, 38, 66, 0.3);
}
}
.h100 {
height: 100%;
}

View File

@ -1,9 +1,4 @@
<!--
* @Description: Description
* @ComponentName: BFC
* @Author: wangzhigang11
* @Date: 2023-05-10 18:59
-->
<template>
<div class="BFC">
<div v-if="showLeft" class="left" :style="curStyle">

View File

@ -1,9 +1,4 @@
<!--
* @Description: Description
* @ComponentName: FlexCol
* @Author: wangzhigang11
* @Date: 2023-05-10 13:42
-->
<template>
<div class="FlexCenter" :style="{height: cHeight}">
<slot></slot>

View File

@ -1,9 +1,4 @@
<!--
* @Description: Description
* @ComponentName: FlexCol
* @Author: wangzhigang11
* @Date: 2023-05-10 13:42
-->
<template>
<div class="FlexCol" :style="curStyle">
<slot></slot>

View File

@ -1,9 +1,4 @@
<!--
* @Description: Description
* @ComponentName: FlexCol
* @Author: wangzhigang11
* @Date: 2023-05-10 13:42
-->
<template>
<div class="FlexRow" :style="{height: cHeight}">
<slot></slot>

View File

@ -1,5 +1,8 @@
<template>
<div class="map-container" ref="mapRef" id="mars3dContainer"></div>
<div class="map-wrapper">
<div class="bg event-none"></div>
<div class="map-container" ref="mapRef" id="mars3dContainer"></div>
</div>
</template>
<script>
@ -17,12 +20,6 @@ const mapLayerTypeToPointIcon = {
}
export default {
async asyncData({ $axios }) {
console.log('axios:', 1)
const { data } = await $axios.$get('http://101.43.201.20:5000/api/Home/view');
return { pageTitle: data.home.title }; // { data: '' }
},
name: "Map",
data () {
return {
@ -39,18 +36,23 @@ export default {
default: 'big'
}
},
mounted() {
this.$nextTick(() => {
if (this.$refs.mapRef) {
const win = window.top
this.$http.get('http://101.43.201.20:5000/api/Home/view').then(({ data }) => {
win.document.title = data.home.title
this.setTitle(data.home.title)
this.setInfo(data)
this.initMap(data.home.center)
})
watch: {
info: {
immediate: true,
deep: true,
handler (info) {
if (info) {
this.$nextTick(() => {
if (this.$refs.mapRef) {
this.initMap(info.home.center)
}
})
}
}
})
}
},
mounted() {
this.$evBus.$on('setVisibility', (layerType, show) => {
this.setVisibility(layerType, show)
})
@ -68,6 +70,7 @@ export default {
shisc: state => state.map.shisc,
wz: state => state.map.wz,
jkd: state => state.map.jkd,
info: state => state.system.info
})
},
methods: {
@ -77,7 +80,6 @@ export default {
const { lon, lat } = center
ms3dConfig.scene.center.lng = lon
ms3dConfig.scene.center.lat = lat
console.log('ms3dConfig:', ms3dConfig);
this.map = new mars3d.Map(this.$refs.mapRef, ms3dConfig)
this.map.on("load", () => {
Object.keys(mapLayerTypeToPointIcon).forEach(layerType => {
@ -208,6 +210,23 @@ export default {
</style>
<style scoped lang="less">
.map-wrapper {
width: 100%;
height: 100%;
position: absolute;
transform: translateX(-50%);
left: 50%;
top: 0;
z-index: 1;
.bg {
background: radial-gradient(transparent, rgba(3, 5, 51, 0.19), rgba(3, 5, 51, 0.68), #020433);
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
z-index: 2;
}
.map-container {
width: 100%;
height: 100%;
@ -217,4 +236,6 @@ export default {
top: 0;
z-index: 1;
}
}
</style>

View File

@ -1,9 +1,4 @@
<!--
* @Description: 内容
* @ComponentName: ModuleContent
* @Author: wangzhigang11
* @Date: 2023-05-06 18:30
-->
<template>
<div class="Content " :style="curStyle">
<div class="content-box" :style="{padding}" :class="{ noneEvent }">
@ -84,6 +79,7 @@ import {getSize} from "@/utils/tools";
overflow: hidden;
position: relative;
pointer-events: none;
z-index: 111;
.content-border {
}

View File

@ -1,9 +1,4 @@
<!--
* @Description: 内容
* @ComponentName: ModuleContent
* @Author: wangzhigang11
* @Date: 2023-05-06 18:30
-->
<template>
<div class="bg">
<slot></slot>
@ -21,7 +16,7 @@
.bg {
width: 100%;
box-sizing: border-box;
height: 100%;
height: 100vh;
box-sizing: border-box;
background: url('~/assets/images/new/大背景.png') center no-repeat;
background-size: 100% 100%;

View File

@ -1,9 +1,4 @@
<!--
* @description:
* @component: TabItem
* @author: wangzhigang11
* @date: 2023/11/9 11:12
-->
<template>
<div class="TabItem" :class="{ selected }" v-on="$listeners" v-bind="$attrs">
<slot></slot>

View File

@ -60,21 +60,28 @@ export default {
let xAxisName = []
let nameLengthMaxIndex = 0
let nameLength = 0
//name
for (const index in dataSource) {
let xAxisNameList = dataSource[index].map(item => item.name) || []
dataSource.forEach((arr = [], index) => {
let xAxisNameList = arr.map(item => item.name) || []
if (xAxisNameList.length > nameLength) {
nameLength = xAxisNameList.length
nameLengthMaxIndex = index
}
}
})
//namex
xAxisName = dataSource[nameLengthMaxIndex].map(item => item.name) || []
//y
let attrNames = Object.keys(dataSourceByAttrObj)
let seriesList = []
for (const index in dataSource) {
let yAxisDataSource = dataSource[index].map(item => item.value)
dataSource.forEach((arr = [], index) => {
let yAxisDataSource = arr.map(item => item.value)
let series = {
name: attrNames[index],
type: 'line',
@ -88,7 +95,9 @@ export default {
}
}
seriesList.push(series)
}
})
let option = {
color: color,
legend: {

View File

@ -13,6 +13,7 @@
v-decorator="[menuItem.key]"
:placeholder="menuItem.placeholder || ''"
v-else-if="menuItem.type === 'select'"
:dropdown-class-name="dropdownClassName"
>
<a-select-option :value="cItem.value" v-for="cItem in menuItem.children || []" :key="cItem.value">
{{ cItem.label }}
@ -20,7 +21,8 @@
</a-select>
<a-range-picker
:placeholder="menuItem.placeholder || ''" v-decorator="[menuItem.key]"
v-else-if="menuItem.type === 'dateRange'" format="YYYY-MM-DD"/>
v-else-if="menuItem.type === 'dateRange'" format="YYYY-MM-DD"
:dropdown-class-name="dropdownClassName" />
</a-form-item>
<a-form-item>
<a-button type="primary" html-type="submit" v-if="!hideSearch">查询</a-button>
@ -66,6 +68,7 @@
<a-select
v-decorator="gtDecorator(menuItem)"
:placeholder="menuItem.placeholder || ''"
:dropdown-class-name="dropdownClassName"
v-else-if="menuItem.type === 'select'"
v-bind="menuItem.props || {}"
>
@ -77,6 +80,7 @@
v-bind="menuItem.props || {}"
v-decorator="gtDecorator(menuItem)"
:placeholder="menuItem.placeholder || ''"
:dropdown-class-name="dropdownClassName"
allow-clear
:tree-data="menuItem.children"
tree-default-expand-all
@ -89,17 +93,24 @@
</a-select-option>
</a-tree-select>
<a-range-picker v-bind="menuItem.props || {}" v-decorator="gtDecorator(menuItem)"
v-else-if="menuItem.type === 'dateRange'" format="YYYY-MM-DD"/>
v-else-if="menuItem.type === 'dateRange'" format="YYYY-MM-DD" :dropdown-class-name="dropdownClassName" />
<a-date-picker style="width: 100%" v-decorator="gtDecorator(menuItem)" v-bind="menuItem.props || {}"
v-else-if="menuItem.type === 'date'" format="YYYY-MM-DD" :dropdown-class-name="dropdownClassName"/>
</a-form-item>
</a-form>
</a-modal>
</div>
</template>
<script>
import moment from "moment";
import { get } from 'lodash'
export default {
name: "user",
data() {
return {
cacheData: [],
isValidate: false,
tableDataSource: [],
form: this.$form.createForm(this, {name: `form_${new Date().valueOf()}`}),
@ -124,6 +135,11 @@ export default {
type: Object,
default: () => ({})
},
dropdownClassName: {
type: String,
default: ''
},
hideSearch: {
type: Boolean,
default: false
@ -155,6 +171,11 @@ export default {
type: Object,
default: () => ({})
},
customSearch: {
type: Function,
default: () => null
}
},
computed: {
searchItems() {
@ -179,8 +200,8 @@ export default {
this.handleSearch()
},
methods: {
viewDetails(data){
this.$emit('viewDetails',data)
viewDetails(data) {
this.$emit('viewDetails', data)
},
gtDecorator(menuItem) {
if (menuItem.rules) {
@ -252,21 +273,43 @@ export default {
reset() {
this.form.resetFields();
},
doSearch () {
if (this.customSearch) {
this.tableDataSource = this.customSearch(JSON.parse(JSON.stringify(this.cacheData)))
}
},
async handleSearch(e) {
e && e.preventDefault();
const rangeList = ['dateRange']
const values = this.form.getFieldsValue()
const {api, noPage, method} = this.apiConf.listApi
const searchValues = {}
for (const formItem of this.formItems.filter(item => item.isSearch)) {
if (rangeList.indexOf(formItem.type) >= 0) {
formItem.fields.forEach((field, index) => {
if (formItem.type.indexOf('date') >= 0) {
searchValues[field] = values[formItem.key] && values[formItem.key][index] && moment(values[formItem.key][index]).format('YYYY-MM-DD') || ''
}
})
} else {
searchValues[formItem.key] = values[formItem.key]
}
}
const {api, noPage, method, renderKey, after} = this.apiConf.listApi
const {data} = await this[`$${method}`](api, {
...values,
...searchValues,
pageSize: this.page.pageSize,
current: this.page.current,
})
if (noPage) {
this.page = false
this.tableDataSource = data
this.cacheData = renderKey ? get(data, renderKey) : data
this.tableDataSource = renderKey ? get(data, renderKey) : data
after && after(data)
} else {
this.page.total = data.total || 0
this.tableDataSource = data.items
this.cacheData = renderKey ? get(data, renderKey) : data.items
this.tableDataSource = renderKey ? get(data, renderKey) : data.items
after && after(data)
}
},
async handleOk() {

View File

@ -0,0 +1,60 @@
<template>
<div class="cusbutton" @click="$emit('click')" :class="{ flex, selected }">
<slot></slot>
</div>
</template>
<script>
export default {
name: "CusButton5",
props: {
flex: {
type: Boolean,
default: false
},
selected: {
type: Boolean,
default: false
}
}
}
</script>
<style scoped lang="less">
.cusbutton {
display: inline-block;
border-radius: 2.56px;
padding: 10px 13px;
/** 文本1 */
font-size: 16px;
font-weight: 400;
letter-spacing: 0px;
color: #fff;
text-align: center;
vertical-align: top;
cursor: pointer;
background: rgba(0, 128, 247, 0.2);
&.flex {
flex: 1;
}
&.selected {
background: rgba(0, 128, 247, 0.5);
}
&:hover {
background: rgba(0, 128, 247, 0.5);
}
}
</style>

View File

@ -1,9 +1,9 @@
<template>
<div class="cusdesc">
<div class="desc" v-for="(col, index) in columns" :key="index">
<div class="desc" v-for="(col, index) in columns" :key="index" :style="{ width: col.width || '50%' }">
<div class="desc-title">{{ col.title }}:</div>
<div class="desc-value">{{ data[col.key] }}</div>
<div class="desc-value">{{ data[col.key || col.dataIndex] }}</div>
</div>
</div>
</template>
@ -37,7 +37,11 @@ export default {
text-align: left;
vertical-align: top;
.desc {
width: 100%;
margin-top: 16px;
display: flex;
justify-content: flex-start;
align-items: center;
&:first-child {
margin-top: 0;
}

View File

@ -0,0 +1,61 @@
<template>
<div class="cusdesc">
<div class="desc" v-for="(col, index) in columns" :key="index">
<div class="desc-title">{{ col.title }}</div>
<div class="desc-value">{{ data[col.key || col.dataIndex] || defaultValue }}</div>
</div>
</div>
</template>
<script>
export default {
name: "CusDesc2",
props: {
columns: {
type: Array,
default: () => []
},
data: {
type: Object,
default: () => ({})
},
defaultValue: {
type: String,
default: ''
}
}
}
</script>
<style scoped lang="less">
.cusdesc {
width: 100%;
/** 文本1 */
font-size: 16px;
font-weight: 400;
letter-spacing: 0px;
line-height: 23.17px;
color: rgba(255, 255, 255, 1);
text-align: left;
vertical-align: top;
.desc {
width: 100%;
margin-top: 16px;
display: flex;
justify-content: space-between;
align-items: center;
height: 36px;
line-height: 36px;
background: rgba(1, 105, 216, 0.2);
border: 1px solid rgba(212, 230, 255, 0.1);
padding: 0 16px;
box-sizing: border-box;
&:first-child {
margin-top: 0;
}
}
}
</style>

View File

@ -1,8 +1,12 @@
<template>
<div class="custom-table">
<Curd v-bind="$attrs" v-on="$listeners"></Curd>
<div class="custom-table visual_datepicker">
<Curd v-bind="$attrs" v-on="$listeners" ref="curd" dropdown-class-name="visual_dropdown_cls">
<template slot="search-button" slot-scope="{ search }">
<slot name="search-button" v-bind:search="search"></slot>
</template>
</Curd>
</div>
</template>
<script>
@ -10,11 +14,27 @@ import Curd from "./Curd.vue";
export default {
name: "CustomTable",
components: {Curd}
components: {Curd},
methods : {
doSearch () {
this.$refs.curd.doSearch()
},
}
}
</script>
<style scoped lang="less">
.custom-table {
/deep/ .ant-form-item-label > label {
color: #fff !important;
}
/deep/ .ant-table-header {
background-color: transparent !important;
border-bottom: 0px ;
}
/deep/ .ant-table-fixed-header > .ant-table-content > .ant-table-scroll > .ant-table-body {
background-color: transparent !important;
}
/deep/ .ant-table-thead > tr > th {
background: linear-gradient(180deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0) 100%);
color: rgba(255, 255, 255, 1);

View File

@ -0,0 +1,24 @@
<template>
<div class="faguiang event-auto">
<slot></slot>
</div>
</template>
<script>
export default {
name: "Faguang"
}
</script>
<style scoped lang="less">
.faguiang {
padding: 28px 24px;
opacity: 1;
background: linear-gradient(180deg, rgba(0, 196, 255, 0) 0%, rgba(16, 134, 173, 0.2) 100%);
border: 1px solid rgba(224, 254, 255, 1);
box-shadow:inset 1px 1px 13px rgba(0, 191, 255, 0.96), 0px 0px 17px rgba(0, 170, 255, 0.69);
border-radius: 10px;
}
</style>

View File

@ -1,9 +1,4 @@
<!--
* @Description: 内容
* @ComponentName: ModuleContent
* @Author: wangzhigang11
* @Date: 2023-05-06 18:30
-->
<template>
<div class="Content " :style="curStyle">
<div class="content-header" :class="{ border }"></div>

View File

@ -0,0 +1,48 @@
<template>
<VueEcharts :options="options" autoresize style="width: 100%;height: 100%;"></VueEcharts>
</template>
<script>
import echartsMixin from "@/mixins/echarts.mixin";
export default {
name: "Pie2",
mixins: [echartsMixin],
data () {
return {
}
},
computed: {
options () {
return {
title: {
show: false
},
tooltip: {},
legend: {
top: 'bottom',
textStyle: {
color: '#fff'
}
},
series: [
{
name: this.title,
type: 'pie',
radius: ['0%', '50%'],
center: ['50%', '50%'],
// roseType: 'area',
itemStyle: {
borderRadius: 8
},
data: this.data
}
]
}
}
}
}
</script>
<style scoped>
</style>

View File

@ -5,7 +5,7 @@
<div class="progress-item" v-for="(item, index) in rate" :key="index">
<BFC>
<div class="percent" slot="right">
{{ item.val * 100 }}
{{ (item.val * 100).toFixed(0) }}
<div class="unit">%</div>
</div>
<div class="info" slot="center">

View File

@ -5,7 +5,17 @@
<div class="header-content">
<div class="time"><a-icon type="clock-circle" style="margin-right: 10px;" />{{ time }}</div>
<div class="tq">{{ tq }}</div>
<p class="_title">{{ title }}一体化平台</p>
<p class="_title" v-if="customTitle">{{ customTitle }}</p>
<p class="_title" v-else>{{ customTitle || title }}一体化平台</p>
<div class="back" v-if="showBack" @click="() => $router.go(-1)">
<a-icon type="arrow-left" /> 返回</div>
<div class="btn-box">
<div class="btn" :key="btn.key" v-for="btn in btns" @click="$emit('click', btn)">
{{ btn.title }}
</div>
</div>
</div>
</div>
</template>
@ -27,6 +37,20 @@ export default {
return ''
}
},
props: {
customTitle: {
type: String,
default: ''
},
showBack: {
type: Boolean,
default: false
},
btns: {
type: Array,
default: () => []
}
},
data () {
return {
time: moment().format('YYYY-MM-DD HH:mm:ss'),
@ -56,6 +80,42 @@ export default {
box-sizing: border-box;
padding-top: 5px;
position: relative;
.btn-box {
display: flex;
justify-content: center;
align-items: center;
margin-top: 20px;
position: absolute;
top: 30px;
left: 50%;
transform: translateX(-50%);
.btn {
height: 30px;
pointer-events: auto;
color: #fff;
padding: 5px 10px;
background-color: #1890ff;
cursor: pointer;
margin-left: 10px;
&:first-child {
margin-left: 0;
}
}
}
.back {
position: absolute;
right: 10px;
top: 40px;
opacity: 1;
font-size: 20px;
font-weight: 400;
letter-spacing: 0px;
line-height: 28.96px;
color: rgba(35, 209, 232, 1);
vertical-align: top;
cursor: pointer;
}
.time {
position: absolute;
left: 20px;

View File

@ -0,0 +1,45 @@
<template>
<div class="web2tit">
<slot></slot>
</div>
</template>
<script>
export default {
name: "Web5Title"
}
</script>
<style scoped lang="less">
.web2tit {
width: 100%;
height: 48px;
line-height: 48px;
border-bottom: 1px solid rgba(255, 255, 255, 0.4);
/** 文本1 */
font-size: 14px;
font-weight: 500;
letter-spacing: 0px;
color: rgba(255, 255, 255, 1);
text-align: left;
vertical-align: top;
background-size: 10px 16px;
box-sizing: border-box;
padding-left: 20px;
position: relative;
&::after {
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
display: table;
content: ' ';
width: 10px;
height: 10px;
opacity: 1;
border: 2px solid rgba(255, 255, 255, 1);
border-radius: 50%;
}
}
</style>

View File

@ -110,6 +110,19 @@ export const ms3dConfig = {
],
"show": true
},
{
"pid": 10,
"name": "倾斜摄影影像",
"type": "3dtiles",
"url": "http://101.43.201.20:666/tiles/tileset.json",
"position": {
"alt": 0 // 根据实际高度调整
},
"maximumScreenSpaceError": 1,
"dynamicScreenSpaceError": true,
"cullWithChildrenBounds": false,
"show": true
},
],
"layers": [
{

46
layouts/default.vue Normal file
View File

@ -0,0 +1,46 @@
<template>
<div>
<nuxt />
</div>
</template>
<script>
import { mapActions, mapState } from 'vuex'
export default {
name: "default",
computed: {
...mapState({
info: state => state.system.info
})
},
watch: {
'$route': {
immediate: true,
deep: true,
handler(to) {
if (to.path.indexOf('login') < 0) {
this.getViewData()
}
}
}
},
created() {
},
methods: {
...mapActions('system', ['setInfo']),
async getViewData () {
if (!this.info) {
const { data } = await this.$get('/api/Home/view');
this.setInfo(data)
}
}
}
}
</script>
<style scoped lang="less">
</style>

17
layouts/loginLayout.vue Normal file
View File

@ -0,0 +1,17 @@
<template>
<div>
<nuxt />
</div>
</template>
<script>
export default {
name: "LoginLayout"
}
</script>
<style scoped lang="less">
</style>

View File

@ -2,6 +2,10 @@ import {groupBy} from 'lodash'
export default {
props: {
title: {
type: String,
default: ''
},
data: {
type: Array,
default: () => []

View File

@ -1,205 +0,0 @@
import * as apis from '@/services/apis'
import { orderBy } from 'lodash'
import moment from "moment";
import {generateUUID} from "ant-design-vue/lib/vc-select/util";
const colors = [
'#00FEF6',
'#FF9811',
'#FF4D11',
'#529a58',
'#D58FFF',
'#0395F6',
'#d5b11e',
'#03f634',
'#d5391e',
'#f6ce03'
]
export default {
created() {
this.getData()
if (this.timer) {
clearInterval(this.timer)
this.timer = null
}
this.timer = setInterval(() => {
this.getData()
}, 5000)
},
beforeDestroy() {
if (this.timer) {
clearInterval(this.timer)
this.timer = null
}
},
data () {
return {
resourcesStatistics: {},
studentGradStatistics: [],
deviceStatistics: {},
accessStatistics: {},
classBrandStatistics: {},
studentAttendanceStatistics: {},
studentAttendanceStatisticsPie: [],
leaveStatistics: [],
gradeStatistics: [],
gradeStatisticsData: [],
accessInfo: [],
studentSexStatistics: {
men: {
total: 0,
percent: 0
},
women: {
total: 0,
percent: 0
}
}
}
},
methods: {
getData () {
this.getResourcesStatistics()
this.getStudentGradStatistics()
this.getStudentSexStatistics()
this.getDeviceStatistics()
this.getAccessStatistics()
this.getClassBrandStatistics()
this.getAccessInfo()
this.getStudentAttendanceStatistics()
this.getGradeStatistics()
this.getLeaveStatistics()
},
getPercent (num, total) {
if (num === 0) return 0
if (total === 0) return 100
return (num * 100 / total).toFixed(2)
},
// 获取教育资源
async getResourcesStatistics () {
const { data } = await apis.getResourcesStatistics()
this.resourcesStatistics = data || {}
},
// 各年级学生分布信息
async getStudentGradStatistics () {
const {data} = await apis.getStudentGradStatistics()
this.studentGradStatistics = (data || []).map((item, index) => {
return {
attr: '年级分布',
name: `${item.gradeIndex}年级`,
value: item.studentNumber,
color: colors[index]
}
})
},
// 性别分布
async getStudentSexStatistics () {
const { data } = await apis.getStudentSexStatistics()
const total = (data || []).reduce((a, b) => a + b.studentNumber || 0, 0)
const men = (data || []).filter(item => `${item.studentSex}` === '1').reduce((a, b) => a + b.studentNumber || 0, 0)
const women = (data || []).filter(item => `${item.studentSex}` === '2').reduce((a, b) => a + b.studentNumber || 0, 0)
this.studentSexStatistics = {
men: {
total: men,
percent: this.getPercent(men, total)
},
women: {
total: women,
percent: this.getPercent(women, total)
}
}
},
// 电子班牌概况
async getDeviceStatistics () {
const { data } = await apis.getDeviceStatistics()
this.deviceStatistics = data || {}
},
// 门禁出入人数
async getAccessStatistics () {
const { data } = await apis.getAccessStatistics()
this.accessStatistics = data || {}
},
async getClassBrandStatistics () {
const { data } = await apis.getClassBrandStatistics()
this.classBrandStatistics = data || {}
},
async getAccessInfo () {
const { data } = await apis.getAccessInfo()
this.accessInfo = (data || []).map(item => ({
...item,
uuid: generateUUID()
}))
},
async getStudentAttendanceStatistics () {
const { data } = await apis.getStudentAttendanceStatistics()
const _data = data || {}
this.studentAttendanceStatistics =_data
this.studentAttendanceStatisticsPie = [
{
attr: '考勤',
name: '出勤',
value: _data.studentAttendanceNumber || 0,
color: colors[0]
},
{
attr: '考勤',
name: '迟到',
value: _data.studentAttendanceLaterNumber || 0,
color: colors[1]
},
{
attr: '考勤',
name: '缺勤',
value: _data.studentAttendanceLossNumber || 0,
color: colors[2]
},
{
attr: '考勤',
name: '请假',
value: _data.studentAttendanceLeaveNumber || 0,
color: colors[3]
}
]
},
async getGradeStatistics () {
const { data } = await apis.getGradeStatistics()
this.gradeStatisticsData = data || []
this.getGradeStatisticsPieData()
},
getGradeStatisticsPieData () {
const item = this.gradeStatisticsData.find(item => `${item && item.gradeIndex}` === `${this.cls}`) || {}
this.gradeStatistics = orderBy((item.classStatisticsList || []).map((item, index) => ({
attr: '班级',
name: `${item.className }`,
value: item.studentNumber || 0,
color: colors[index]
})), ['name'], ['asc'])
},
async getLeaveStatistics () {
const { data } = await apis.getLeaveStatistics()
this.leaveStatistics = (data || []).map(item => {
return [
{
attr: '事假',
name: moment(item.leaveDate).format('MM/DD'),
value: item.businessLeavee || 0
},
{
attr: '病假',
name: moment(item.leaveDate).format('MM/DD'),
value: item.sickLeaveNumber || 0
}
]
}).flat(Infinity)
}
}
}

11575
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,4 @@
<!--
* @description:
* @component: index
* @author: wangzhigang11
* @date: 2023/8/21 19:30
-->
<template>
<div class="index">
<div :style="autoStyle" class="iframe-container">

View File

@ -1,98 +1,143 @@
<template>
<div>
<a-page-header
:ghost="false"
style="border-bottom: 1px solid rgb(235, 237, 240)"
title="磅秤台账"
@back="() => $router.go(-1)"
/>
<div class="type-button">
<div :class="['tabs-button',activeTabsButton == null?'active-tabs-button':'']" @click="tabsChange(null)">
全部
</div>
<div :class="['tabs-button',activeTabsButton == 1?'active-tabs-button':'']" @click="tabsChange(1)">
东门
</div>
<div :class="['tabs-button',activeTabsButton == 2?'active-tabs-button':'']" @click="tabsChange(2)">
东门
</div>
<div :class="['tabs-button',activeTabsButton == 3?'active-tabs-button':'']" @click="tabsChange(3)">
东门
</div>
<div :class="['tabs-button',activeTabsButton == 4?'active-tabs-button':'']" @click="tabsChange(4)">
东门
</div>
</div>
<new-bg>
<flex-col>
<system-title show-back custom-title="磅秤台账"/>
<ModuleContent padding="0px 20px 20px">
<flex-col>
<Butgroup2 class="type-button">
<cus-button :class="['tabs-button',activeTabsButton == null?'active-tabs-button':'']"
@click="tabsChange(null)">
全部
</cus-button>
<cus-button :class="['tabs-button',activeTabsButton == 1?'active-tabs-button':'']" @click="tabsChange(1)">
东门
</cus-button>
<cus-button :class="['tabs-button',activeTabsButton == 2?'active-tabs-button':'']" @click="tabsChange(2)">
东门
</cus-button>
<cus-button :class="['tabs-button',activeTabsButton == 3?'active-tabs-button':'']" @click="tabsChange(3)">
东门
</cus-button>
<cus-button :class="['tabs-button',activeTabsButton == 4?'active-tabs-button':'']" @click="tabsChange(4)">
东门
</cus-button>
</Butgroup2>
<Split num="10"></Split>
<ModuleContent2 bg padding="20px">
<a-row :gutter="16">
<a-col :span="18">
<CustomTable
hide-action
hide-search
hide-button
:columns="columns"
:api-conf="apiConf"
:form-items="formItems"
@edit="editHandler"
@viewDetails="viewDetails"
>
<template slot="search-button" slot-scope="{ search }">
<a-button type="primary" @click="exportList(search)">导出历史数据</a-button>
<Split num="10"></Split>
</template>
</CustomTable>
</a-col>
<a-col :span="6">
<flex-col>
<web3-title>驾驶人详情</web3-title>
<ModuleContent padding="0">
<flex-col>
<img :src="selectedRecord.imgUrl" alt="" class="car-preview">
<butgroup2>
<cus-button2 flex>进出场抓拍图</cus-button2>
<!-- <cus-button2>行驶证-正面</cus-button2>-->
<!-- <cus-button2>行驶证-反面</cus-button2>-->
<!-- <cus-button2>环保清单</cus-button2>-->
</butgroup2>
<ModuleContent padding="20px 27px" class="desc">
<cus-desc :data="selectedRecord" :columns="descColumns"></cus-desc>
</ModuleContent>
</flex-col>
<div class="data-info">
<div class="left-table">
<Curd
hide-action
hide-search
hide-button
:columns="columns"
:api-conf="apiConf"
:form-items="formItems"
@edit="editHandler"
@viewDetails="viewDetails"
>
<template slot="search-button" slot-scope="{ search }">
<a-button type="primary" @click="exportList(search)">导出历史数据</a-button>
</template>
</Curd>
</div>
<div class="right-details" v-if="isShowInfoDetails">
<div class="header-title">驾驶人详情</div>
</ModuleContent>
</flex-col>
<img src=""/>
<div class="group-button">
<div :class="['_button',activeButton == 1?'active_button':'']" @click="viewImgByType(1)">出入场抓拍图</div>
<div :class="['_button',activeButton == 2?'active_button':'']" @click="viewImgByType(2)">行驶证-正面</div>
<div :class="['_button',activeButton == 3?'active_button':'']" @click="viewImgByType(3)">行驶证-反面</div>
<div :class="['_button',activeButton == 4?'active_button':'']" @click="viewImgByType(4)">环保清单</div>
</div>
<div class="details-info">
<div class="details-info-item">
<div class="_title">排放标准</div>
<div class="_title">国0</div>
</div>
<div class="details-info-item">
<div class="_title">VIN</div>
<div class="_title">国0</div>
</div>
<div class="details-info-item">
<div class="_title">发动机号</div>
<div class="_title">国0</div>
</div>
<div class="details-info-item">
<div class="_title">注册日期</div>
<div class="_title">国0</div>
</div>
</div>
<div class="footer-button">
<Button type="primary" @click="closeDetails">关闭详情</Button>
</div>
</div>
</div>
</div>
</a-col>
</a-row>
</ModuleContent2>
</flex-col>
</ModuleContent>
</flex-col>
</new-bg>
</template>
<script>
import Curd from "../../components/smallCommon/Curd.vue";
import moment from 'moment'
import SystemTitle from "../../components/smallCommon/SystemTitle.vue";
import NewBg from "../../components/NewBg.vue";
import FlexCol from "../../components/FlexCol.vue";
import ModuleContent from "../../components/ModuleContent.vue";
import ModuleContent2 from "../../components/smallCommon/ModuleContent2.vue";
import CustomTable from "../../components/smallCommon/CustomTable.vue";
import Split from "../../components/Split.vue";
import Web3Title from "../../components/smallCommon/Web3Title.vue";
import CusDesc from "../../components/smallCommon/CusDesc.vue";
import CusButton2 from "../../components/smallCommon/CusButton2.vue";
import Butgroup2 from "../../components/smallCommon/butgroup2.vue";
import CusButton from "../../components/smallCommon/CusButton4.vue";
export default {
name: "user",
layout: "user",
components: {
CusButton,
Butgroup2, CusButton2, CusDesc,
Web3Title,
Split,
CustomTable,
ModuleContent2,
ModuleContent, FlexCol, NewBg, SystemTitle,
Curd
},
data() {
return {
isEdit: false,
roles: [],
descColumns: [
{
title: '车牌号',
dataIndex: 'carNumber',
width: '100%'
}, {
title: '车牌颜色',
dataIndex: 'carColorString',
width: '100%'
}, {
title: '车辆类型',
dataIndex: 'carType',
width: '100%'
}, {
title: '车辆类型',
dataIndex: 'carType',
width: '100%'
}, {
title: '排放等级',
dataIndex: 'effluent',
width: '100%'
}, {
title: 'VIN',
dataIndex: 'vin',
width: '100%'
}, {
title: '发动机号',
dataIndex: 'entryExitPictureUrl',
width: '100%'
}, {
title: '注册日期',
dataIndex: 'registrationDate',
width: '100%'
}
],
selectedRecord: {},
columns: [
{
dataIndex: 'outTime',
@ -127,14 +172,7 @@ export default {
dataIndex: 'createDateTime',
key: 'createDateTime',
title: '出厂日期'
},
{
title: '操作',
key: 'operation',
scopedSlots: {customRender: 'details'},
fixed: 'right',
width: 100
},
}
],
apiConf: {
listApi: {api: '/api/Ledger/list', method: 'get'},
@ -188,7 +226,7 @@ export default {
},
//
tabsChange(value){
tabsChange(value) {
this.activeTabsButton = value
}
@ -196,12 +234,18 @@ export default {
}
</script>
<style scoped lang="less">
.car-preview {
width: 100%;
height: 260px;
}
.desc {
background: rgba(24, 131, 201, 0.2);
border: 1px solid rgba(15, 81, 122, 1);
}
.type-button {
margin: 20px 300px;
display: flex;
flex-flow: row;
justify-content: space-between;
max-width: 70%;
.tabs-button {
height: 40px;

View File

@ -2,10 +2,9 @@
<template>
<new-bg>
<flex-col>
<system-title/>
<system-title show-back />
<ModuleContent padding="20px">
<flex-col>
<web2-title>清洁运输</web2-title>
<ModuleContent padding="0 20px 20px">
<BFC>
<div class="sou-suo-kuang" slot="right">
@ -27,9 +26,9 @@
<img :src="selectedRecord.imgUrl" alt="" class="car-preview">
<butgroup2>
<cus-button2 flex>进出场抓拍图</cus-button2>
<cus-button2>行驶证-正面</cus-button2>
<cus-button2>行驶证-反面</cus-button2>
<cus-button2>环保清单</cus-button2>
<!-- <cus-button2>行驶证-正面</cus-button2>-->
<!-- <cus-button2>行驶证-反面</cus-button2>-->
<!-- <cus-button2>环保清单</cus-button2>-->
</butgroup2>
<ModuleContent padding="20px 27px" class="desc">
<cus-desc :data="selectedRecord" :columns="descColumns"></cus-desc>
@ -75,7 +74,9 @@
hide-button
:columns="columns"
:api-conf="apiConf"
:tableProps="tableProps"
:table-props="tableProps"
:custom-search="customSearch"
ref="cusTable"
/>
</div>
@ -95,8 +96,7 @@
</cus-button>
<cus-button>
<nuxt-link to="/cleanTravel/bangcheng">磅秤台账</nuxt-link>
</cus-button>
<cus-button>门禁监控</cus-button>
</cus-button>
</butgroup>
</flex-col>
</ModuleContent>
@ -148,6 +148,7 @@ export default {
const self = this
return {
tableProps: {
scroll: {y: 500},
customRow (record) {
return {
on: {
@ -163,7 +164,7 @@ export default {
}
},
apiConf: {
listApi: { api: '/api/Transport/list', method: 'get' },
listApi: { api: '/api/Transport/list', method: 'get', noPage: true },
},
selectedRecord: {},
bgStr,
@ -178,19 +179,37 @@ export default {
dataSource: [],
descColumns: [
{
title: '设备掉线',
dataIndex: 'deviceName',
width: '33.333%'
},
{
title: '故障异常',
dataIndex: 'errorName',
width: '33.333%'
},
{
title: '异常报警',
dataIndex: 'errorImg',
width: '33.333%'
title: '车牌号',
dataIndex: 'carNumber',
width: '100%'
},{
title: '车牌颜色',
dataIndex: 'carColorString',
width: '100%'
},{
title: '车辆类型',
dataIndex: 'carType',
width: '100%'
},{
title: '车辆类型',
dataIndex: 'carType',
width: '100%'
},{
title: '排放等级',
dataIndex: 'effluent',
width: '100%'
},{
title: 'VIN',
dataIndex: 'vin',
width: '100%'
},{
title: '发动机号',
dataIndex: 'entryExitPictureUrl',
width: '100%'
},{
title: '注册日期',
dataIndex: 'registrationDate',
width: '100%'
}
],
columns: [
@ -200,34 +219,25 @@ export default {
title: '车牌号'
},
{
dataIndex: 'transportType',
key: 'transportType',
title: '类型',
customRender(transportType) {
if (transportType === 1) return '进厂'
return '出厂'
}
},
{
dataIndex: 'address',
key: 'address',
title: '进出厂位置'
},
{
dataIndex: 'registered',
key: 'registered',
title: '出/入厂位置'
},
{
dataIndex: 'goods',
key: 'goods',
title: '物料类型'
dataIndex: 'transportTypeString',
key: 'transportTypeString',
title: '进出厂方向'
},
{
dataIndex: 'effluent',
key: 'effluent',
title: '排放标准'
title: '排放等级'
},
{
dataIndex: 'carColorString',
key: 'carColorString',
title: '车牌颜色'
},
{
dataIndex: 'carType',
key: 'carType',
title: '车牌类型'
}
]
}
},
@ -236,17 +246,20 @@ export default {
title: state => state.system.title,
})
},
watch : {
searchCarNum () {
this.$nextTick(() => {
if (this.$refs.cusTable) {
this.$refs.cusTable.doSearch()
}
})
}
},
mounted() {
this.getCount()
this.getDataSource()
this.$nextTick(() => {
const win = window.top
this.$http.get('http://101.43.201.20:5000/api/Home/view').then(({data}) => {
win.document.title = data.home.title
this.setTitle(data.home.title)
this.setInfo(data)
})
if (this.$refs.module) {
const offsetHeight = this.$refs.module.$el.offsetHeight - 40
this.tableH = offsetHeight
@ -343,6 +356,11 @@ export default {
})
}
},
customSearch (data = []) {
if (!this.searchCarNum) return data
return data.filter(item => item.carNumber.indexOf(this.searchCarNum) >= 0)
}
}
}
</script>

View File

@ -1,41 +1,38 @@
<template>
<div>
<a-page-header
:ghost="false"
style="border-bottom: 1px solid rgb(235, 237, 240)"
title="厂区车辆台账"
@back="() => $router.go(-1)"
/>
<a-row :gutter="16">
<a-col :span="6">
<a-card title="运输车辆" size="small">
<p>card content</p>
</a-card>
</a-col>
<a-col :span="6">
<a-card title="国Ⅵ输车辆" size="small">
<p>card content</p>
</a-card>
</a-col>
<a-col :span="6">
<a-card title="非道路工程机械" size="small">
<p>card content</p>
</a-card>
</a-col>
<a-col :span="6">
<a-card title="燃油运输车辆" size="small">
<p>card content</p>
</a-card>
</a-col>
</a-row>
<new-bg>
<flex-col>
<system-title show-back/>
<ModuleContent padding="0px 20px 20px">
<web2-title>厂区车辆台账</web2-title>
<Split :height="16"></Split>
<div style="height: 144px;width: 100%;">
<ModuleContent2 bg bg-str :border="false">
<butgroup2 style="height: 100%;">
<ModuleContent2 bg bg-color border>
<miaoshu title="运输车辆" :value="headCount.t1" color="rgba(42, 207, 255, 1)"></miaoshu>
</ModuleContent2>
<ModuleContent2 bg bg-color border style="margin-left: 16px;">
<miaoshu title="国Ⅵ输车辆" :value="headCount.t2" color="rgba(255, 171, 87, 1)"></miaoshu>
</ModuleContent2>
<ModuleContent2 bg bg-color border style="margin-left: 16px;">
<miaoshu title="非道路工程机械" :value="headCount.t3" color="rgba(122, 175, 255, 1)"></miaoshu>
</ModuleContent2>
<ModuleContent2 bg bg-color border style="margin-left: 16px;">
<miaoshu title="燃油运输车辆" :value="headCount.t4" color="rgba(76, 243, 129, 1)"></miaoshu>
</ModuleContent2>
</butgroup2>
</ModuleContent2>
</div>
<a-divider />
<Curd
hide-action
<CustomTable
hide-search
hide-button
hide-action
:columns="columns"
:api-conf="apiConf"
:form-items="formItems"
@ -43,21 +40,41 @@
>
<template slot="search-button" slot-scope="{ search }">
<a-button type="primary" @click="exportList(search)">导出历史数据</a-button>
<Split height="10"></Split>
</template>
</Curd>
</div>
</CustomTable>
</ModuleContent>
</flex-col>
</new-bg>
</template>
<script>
import Curd from "../../components/smallCommon/Curd.vue";
import moment from 'moment'
import SystemTitle from "../../components/smallCommon/SystemTitle.vue";
import NewBg from "../../components/NewBg.vue";
import FlexCol from "../../components/FlexCol.vue";
import ModuleContent from "../../components/ModuleContent.vue";
import CustomTable from "../../components/smallCommon/CustomTable.vue";
import Miaoshu from "../../components/smallCommon/miaoshu.vue";
import ModuleContent2 from "../../components/smallCommon/ModuleContent2.vue";
import Butgroup2 from "../../components/smallCommon/butgroup2.vue";
import Split from "../../components/smallCommon/Split.vue";
import Web2Title from "../../components/smallCommon/Web2Title.vue";
export default {
name: "user",
layout: "user",
components: {
Web2Title,
Split,
Butgroup2, ModuleContent2, Miaoshu,
CustomTable,
ModuleContent,
FlexCol, NewBg, SystemTitle,
Curd
},
data () {
return {
headCount: {},
isEdit: false,
roles: [],
columns: [
@ -88,7 +105,7 @@ export default {
{
dataIndex: 'emissions',
key: 'emissions',
title: '燃油车'
title: '燃油车标准'
},
{
dataIndex: 'createDateTime',
@ -98,6 +115,7 @@ export default {
],
apiConf: {
listApi: { api: '/api/Ledger/list', method: 'get' },
addApi: {api: '/api/Ledger/add', method: 'post',}
}
}
},
@ -110,19 +128,68 @@ export default {
key: 'time',
label: '日期',
isSearch: true,
hide: true,
placeholder: ['请选择开始日期', '请选择结束日期'],
rules: [
{ required: true, message: '请选择时间范围' }
],
fields: ['startTime', 'endTime']
},
{
type: 'date',
key: 'outTime',
label: '日期',
placeholder: '请选择日期'
},
{
type: 'input',
key: 'carNum',
label: '车牌号',
placeholder: '请输入车牌号'
},
{
type: 'input',
key: 'carModel',
label: '车型',
placeholder: '请输入车型'
},
{
type: 'select',
key: 'newCar',
label: '新能源',
placeholder: '是否新能源',
children: [
{ label: '是', value: '是' },
{ label: '否', value: '否' },
]
},
{
type: 'select',
key: 'emissions',
label: '燃油车标准',
placeholder: '',
},
{
type: 'date',
key: 'createDateTime',
label: '出厂日期',
placeholder: '',
}
]
}
},
created() {
this.$get('/api/Ledger/HeaderCount').then(({data}) => {
this.headCount = data || {}
})
},
methods: {
add () {
},
editHandler (isEdit) {
this.isEdit = isEdit
},

View File

@ -1,101 +1,153 @@
<template>
<div>
<a-page-header
:ghost="false"
title="清洁运输+趋势"
@back="() => $router.go(-1)"
/>
<a-divider style="margin-top: 0;" />
<a-row :gutter="16">
<a-col :span="12">
<a-card>
<div slot="title">
运输总量: {{ yunshuzongliang }}
</div>
<new-bg>
<flex-col>
<system-title show-back/>
<ModuleContent padding="0px 20px 20px">
<FlexCol>
<Curd
hide-action
hide-search
hide-button
:columns="columns"
:api-conf="apiConf"
:form-items="formItems"
>
</Curd>
</a-card>
<web2-title>清洁运输+趋势</web2-title>
<Split height="16"/>
<ModuleContent2 :border="false" padding="0">
<a-row :gutter="16" class="h100">
<a-col :span="6" class="h100">
<ModuleContent2 :border="false" padding="0">
<FlexCol>
<web3-title>运输车辆占比</web3-title>
<ModuleContent2 :border="false" padding="0" height="43%">
<Pie2 :data="cheliangData" title="运输车辆"></Pie2>
</ModuleContent2>
<web3-title>运输量占比</web3-title>
<ModuleContent2 :border="false" padding="0">
<Pie2 :data="yunshuliangData" title="运输量"></Pie2>
</ModuleContent2>
</FlexCol>
</a-col>
<a-col :span="12">
<a-card title="国Ⅵ输车辆" size="small">
<p>card content</p>
</a-card>
</a-col>
</a-row>
</ModuleContent2>
</a-col>
<a-col :span="18" class="h100">
<CustomTable
hide-action
hide-button
:columns="columns"
:api-conf="apiConf"
:form-items="formItems"
>
<template slot="search-button" slot-scope="{ search }">
<a-button type="primary" @click="exportList(search)" style="margin-left: 10px;">导出</a-button>
<Split height="10"></Split>
</template>
</CustomTable>
</a-col>
</a-row>
</ModuleContent2>
</FlexCol>
</ModuleContent>
</flex-col>
</new-bg>
</div>
</template>
<script>
import Curd from "../../components/smallCommon/Curd.vue";
import moment from 'moment'
import SystemTitle from "@/components/smallCommon/SystemTitle.vue";
import NewBg from "@/components/NewBg.vue";
import FlexCol from "@/components/FlexCol.vue";
import ModuleContent from "@/components/ModuleContent.vue";
import CustomTable from "@/components/smallCommon/CustomTable.vue";
import Split from "@/components/smallCommon/Split.vue";
import Web2Title from "@/components/smallCommon/Web2Title.vue";
import ModuleContent2 from "@/components/smallCommon/ModuleContent2.vue";
import CustomDesc2 from "@/components/smallCommon/CusDesc2.vue";
import Web3Title from "@/components/smallCommon/Web3Title.vue";
import Pie2 from "@/components/smallCommon/Pie2.vue";
export default {
name: "user",
layout: "user",
components: {
Curd
Web3Title,
CustomDesc2, ModuleContent2,
Web2Title,
Split,
CustomTable,
ModuleContent, FlexCol, NewBg, SystemTitle,
Curd,
Pie2
},
data () {
data() {
const self = this
return {
cheliangData: [],
yunshuliangData: [],
yunshuzongliang: 0,
isEdit: false,
roles: [],
columns: [
{
dataIndex: 'outTime',
key: 'outTime',
title: '日期'
dataIndex: 'time',
key: 'time',
title: '通过时间'
},
{
dataIndex: 'carNum',
key: 'carNum',
dataIndex: 'carNumber',
key: 'carNumber',
title: '车牌号'
},
{
dataIndex: 'carModel',
key: 'carModel',
title: '车型'
dataIndex: 'carType',
key: 'carType',
title: '车牌类型'
},
{
dataIndex: 'newCar',
key: 'newCar',
title: '新能源',
customRender (text) {
if (text) return '是'
return '否'
}
dataIndex: 'carType',
key: 'carType',
title: '排放类型'
},
{
dataIndex: 'emissions',
key: 'emissions',
title: '燃油车'
dataIndex: 'weight',
key: 'weight',
title: '运输量'
},
{
dataIndex: 'createDateTime',
key: 'createDateTime',
title: '出厂日期'
dataIndex: 'carColor',
key: 'carColor',
title: '车牌颜色'
}
],
apiConf: {
listApi: { api: '/api/Transport/list', method: 'get' },
listApi: {api: '/api/Transport/gettransport', method: 'get', renderKey: 'item.cleans', after (data) {
self.cheliangData = [
{ name: '国五', value: data.item.v5Numer },
{ name: '国六', value: data.item.v6Number },
{ name: '电动', value: data.item.electricNumber },
{ name: '其他', value: data.item.otherNumber },
]
self.yunshuliangData = [
{ name: '国五', value: data.item.v5WeightNumber },
{ name: '国六', value: data.item.v6WeightNumber },
{ name: '电动', value: data.item.electricWeightNumber },
{ name: '其他', value: data.item.otherWeightNumber },
]
}},
}
}
},
computed: {
formItems () {
formItems() {
return [
{
type: 'dateRange',
key: 'time',
label: '日期',
isSearch: true,
hide: true,
placeholder: ['请选择开始日期', '请选择结束日期'],
rules: [
{required: true, message: '请选择时间范围'}
],
fields: ['startTime', 'endTime']
},
]
}
},
@ -104,18 +156,23 @@ export default {
},
methods: {
getyunshuzongliang () {
/*this.$get('/api/Transport/count').then(({ data }) => {
this.yunshuzongliang = data
})*/
getyunshuzongliang() {
},
editHandler (isEdit) {
editHandler(isEdit) {
this.isEdit = isEdit
},
exportList ({ time }) {
const [ start, end ] = time
exportList({time}) {
const [start, end] = time
const fmt = 'YYYY-MM-DD'
window.open(`http://101.43.201.20:5000/api/Ledger/export?start=${moment(start).format(fmt)}&end=${moment(end).format(fmt)}`, '_blank')
},
searchList (search) {
const [startTime, endTime] = search.time
this.$get('/api/Transport/gettransport', {
startTime: moment(startTime).format('YYYY-MM-DD'),
endTime: moment(endTime).format('YYYY-MM-DD'),
})
}
}

View File

@ -1,6 +1,10 @@
<!--峰煤监控系统-->
<template>
<new-bg>
<flex-col>
<system-title />
<div class="center-panel">
<Map type="middle" @pointClick="pointClick" />
</div>
@ -23,7 +27,12 @@
<ModuleContent padding="0" height="180">
<air-quality-trend-charts :data-source="airQualityTrendDataSource"/>
</ModuleContent>
<web3-title>设备报警信息汇总</web3-title>
<web3-title>
设备报警信息汇总
<template slot="action">
<a-button type="primary" @click="exportAlarmList">导出</a-button>
</template>
</web3-title>
<ModuleContent padding="0">
<peak-custom-table :table-title="columnsForTable" :data-source="dataSource" :limit-move-num="3"/>
</ModuleContent>
@ -37,8 +46,8 @@
清洁运输比例
<template slot="action">
<butgroup2 style="height: 20px;line-height: 20px;">
<cus-button4 @click="active = 'Yesterday'" :selected="active === 'Yesterday'">昨日</cus-button4>
<cus-button4 @click="active = 'LastWeek'" :selected="active === 'LastWeek'">上周</cus-button4>
<cus-button4 @click="active = 'yesterday'" :selected="active === 'yesterday'">昨日</cus-button4>
<cus-button4 @click="active = 'lastWeek'" :selected="active === 'lastWeek'">上周</cus-button4>
</butgroup2>
</template>
</web3-title>
@ -53,19 +62,26 @@
<ModuleContent padding="20px 0 0" height="140">
<div class="pf">
<div class="t">当前VOC的日排放量</div>
<div class="v">{{ todaypf.voc || 0 }}mg/m3</div>
<div class="v">{{ (todaypf.today?.voc || 0).superFixed(2) }}mg/m3</div>
</div><div class="pf">
<div class="t">当前CEMS的日排放量</div>
<div class="v">{{ todaypf.cems || 0 }}mg/m3</div>
<div class="v">{{ (todaypf.today?.cems || 0).superFixed(2) }}mg/m3</div>
</div>
</ModuleContent>
<web4-title>周排放量</web4-title>
<ModuleContent padding="0 ">
<peak-custom-table :table-title="columns2ForTable" :data-source="weekData" :limit-move-num="3"/>
<air-quality-trend-charts :data-source="weekData"/>
<!-- <peak-custom-table :table-title="columns2ForTable" :data-source="weekData" :limit-move-num="3"/>-->
</ModuleContent>
<web3-title>设备超标报警</web3-title>
<ModuleContent padding="0 20px 20px">
<web3-title>
设备超标报警
<template slot="action">
<a-button type="primary" @click="exportAlarmList">导出</a-button>
</template>
</web3-title>
<ModuleContent padding="0">
<peak-custom-table :table-title="columnsForChaobiao" :data-source="[]" :limit-move-num="3"/>
</ModuleContent>
</flex-col>
@ -97,6 +113,7 @@
</BFC>
</ModuleContent>
</flex-col>
</flex-col>
</new-bg>
</template>
@ -239,16 +256,30 @@ export default {
const week = this.todaypf.week || {}
const results = []
for (const weekKey in week) {
const row = {
// 线
for (const weekElement of week[weekKey]) {
if (weekElement && weekElement.Key) {
const row = {
attr:weekKey,
name: weekElement.Key,
value: weekElement.value || 0
}
results.push(row)
}
}
// table
/*const row = {
deviceName:weekKey,
}
if (!week[weekKey].length) continue
for (const weekElement of week[weekKey]) {
console.log(weekElement)
row[weekElement.Key] = weekElement.value
}
results.push(row)
results.push(row)*/
}
return results
}
@ -256,8 +287,31 @@ export default {
data () {
return {
mapTab: 'rl',
active: 'Yesterday',
active: 'yesterday',
columnsForChaobiao: [
{
title: '工序',
dataIndex: 'gx',
width: '16.66667%'
},{
title: '阈值',
dataIndex: 'yz',
width: '16.66667%'
},{
title: '超标值',
dataIndex: 'cbz',
width: '16.66667%'
},{
title: '设备名称',
dataIndex: 'sbmc',
width: '20%'
},{
title: '超标名称',
dataIndex: 'cbmc',
width: '20%'
},
],
columnsForTable: [
{
title: '设备名称',
@ -266,18 +320,22 @@ export default {
},
{
title: '报警时间',
dataIndex: 'CreateDateTime',
dataIndex: 'time',
width: '33.333%'
},
{
title: '报警内容',
dataIndex: 'AlertContent',
dataIndex: 'alarmName',
width: '33.333%'
},
]
}
},
methods: {
//
exportAlarmList () {
// todo
},
/**
* 图层构造器
* @param { object } props
@ -354,7 +412,9 @@ export default {
})
}
},
}
},
}
</script>

View File

@ -1,9 +1,4 @@
<!--
* @description:
* @component: index
* @author: wangzhigang11
* @date: 2023/8/21 19:30
-->
<template>
<div class="index">
<div :style="autoStyle" class="iframe-container">

View File

@ -42,6 +42,7 @@ function hasErrors(fieldsError) {
return Object.keys(fieldsError).some(field => fieldsError[field]);
}
export default {
layout: 'LoginLayout',
data() {
return {
hasErrors,

View File

@ -1,11 +1,23 @@
<script>
import SystemTitle from "../../components/smallCommon/SystemTitle.vue";
import NewBg from "../../components/NewBg.vue";
import FlexCol from "../../components/FlexCol.vue";
import ModuleContent from "../../components/ModuleContent.vue";
export default {
name: "list"
name: "list",
components: {ModuleContent, FlexCol, NewBg, SystemTitle}
}
</script>
<template>
<div class="list"></div>
<new-bg>
<flex-col>
<system-title show-back custom-title="视频广场" />
<ModuleContent padding="0px 20px 20px">
</ModuleContent>
</flex-col>
</new-bg>
</template>
<style scoped lang="less">

View File

@ -0,0 +1,30 @@
<template>
<div class="car-washer">
<a-page-header
:ghost="false"
style="border-bottom: 1px solid rgb(235, 237, 240)"
title="厂区车辆台账"
@back="() => $router.go(-1)"
/>
<a-row :gutter="16">
<a-col :span="3">
</a-col>
<a-col :span="12">
col-12
</a-col>
<a-col :span="3">
col-12
</a-col>
</a-row>
</div>
</template>
<script>
export default {
name: "list"
}
</script>
<style scoped lang="less">
</style>

View File

@ -5,11 +5,10 @@
<Map type="middle" @pointClick="pointClick" />
</div>
<flex-col class="main">
<system-title/>
<ModuleContent none-event padding="0 20px 20px">
<system-title show-back custom-title="环境治理"/>
<ModuleContent none-event padding="0 50px 20px">
<BFC>
<flex-col slot="left" width="412">
<web2-title>环境治理</web2-title>
<ModuleContent padding="20px 0" height="218">
<div class="video"></div>
</ModuleContent>
@ -75,7 +74,7 @@ import Split from "../../components/smallCommon/Split.vue";
import CusButton3 from "../../components/smallCommon/CusButton3.vue";
export default {
name: "PeakCoalMonitoring",
name: "environment",
components: {
CusButton3,
Split,
@ -177,12 +176,6 @@ export default {
mounted() {
this.$nextTick(() => {
const win = window.top
this.$http.get('http://101.43.201.20:5000/api/Home/view').then(({data}) => {
win.document.title = data.home.title
this.setTitle(data.home.title)
this.setInfo(data)
})
if (this.$refs.module) {
const offsetHeight = this.$refs.module.$el.offsetHeight - 40
this.tableH = offsetHeight

View File

@ -1,38 +1,36 @@
<template>
<div class="huanweixunhang">
<a-page-header
:ghost="false"
style="border-bottom: 1px solid rgb(235, 237, 240)"
title="环卫巡航"
@back="() => $router.go(-1)"
/>
<template><new-bg>
<flex-col>
<system-title show-back custom-title="环卫巡航" />
<ModuleContent padding="0px 20px 20px">
<div class="_map">
<Map></Map>
</div>
</div>
</ModuleContent>
</flex-col>
</new-bg>
</template>
<script>
import Map from "../../components/Map.vue";
import SystemTitle from "../../components/smallCommon/SystemTitle.vue";
import NewBg from "../../components/NewBg.vue";
import FlexCol from "../../components/FlexCol.vue";
import ModuleContent from "../../components/ModuleContent.vue";
export default {
name: "huanweixunhang",
components: {
ModuleContent,
FlexCol, NewBg, SystemTitle,
Map
}
}
</script>
<style scoped lang="less">
.huanweixunhang {
height: 100vh;
display: flex;
flex-flow: column;
._map {
height: 0;
flex: 1;
position: relative;
}
._map {
width: 100%;
height: 100%;
position: relative;
}
</style>

View File

@ -1,34 +1,111 @@
<template>
<div class="paifang">
<a-page-header
:ghost="false"
style="border-bottom: 1px solid rgb(235, 237, 240)"
title="无组织排放"
@back="() => $router.go(-1)"
/>
<new-bg>
<flex-col>
<system-title show-back/>
<Map></Map>
<ModuleContent padding="0px 50px 20px" class="event-none" none-event>
<web2-title>无组织排放</web2-title>
<a-row :gutter="16" style="height: calc(100% - 62px);margin-top: 16px;">
<a-col :span="5" style="height: 100%;">
<div class="con" style="height: 100%;display: flex;flex-direction: column; width: 100%;">
<web3-title>设备数量统计</web3-title>
<Split height="10"></Split>
<ModuleContent2 :border="false" height="30%" padding="0">
<custom-desc2 default-value="0" :data="tongji" :columns="descColumns"></custom-desc2>
</ModuleContent2>
<web3-title>报警类型数据分析</web3-title>
<Split height="10"></Split>
<ModuleContent2 :border="false" padding="0">
</ModuleContent2>
</div>
</a-col>
<a-col span="14">
<butgroup :bg="false">
<cus-button5>干雾点位置</cus-button5>
<cus-button5>TSP点位</cus-button5>
<cus-button5>微站点位</cus-button5>
<cus-button5>雾炮点位</cus-button5>
<cus-button5>雾桩点位</cus-button5>
<cus-button5>洗车机点位</cus-button5>
</butgroup>
</a-col>
<a-col :span="5" class="event-auto" style="height: 100%;">
<FlexCol>
<ModuleContent2 :border="false" padding="0">
</ModuleContent2>
<web3-title>项目介绍</web3-title>
<Split height="10"></Split>
<ModuleContent2 :border="false" padding="0">
</ModuleContent2>
</FlexCol>
</a-col>
</a-row>
<butgroup class="bottom-btn">
<cus-button>
<nuxt-link to="/wuzuzhi/xichejiguanli">洗车机管理</nuxt-link>
</cus-button>
<cus-button>
<nuxt-link to="/wuzuzhi/huanjingzhili">环境治理</nuxt-link>
</cus-button>
<cus-button>
<nuxt-link to="/wuzuzhi/huanweixunhang">环卫巡航</nuxt-link>
</cus-button>
</butgroup>
</ModuleContent>
<a-row :gutter="16">
<a-col :span="18">
<Map></Map>
</a-col>
<a-col :span="6">
<a-card title="国Ⅵ输车辆" size="small">
<p>card content</p>
</a-card>
</a-col>
</a-row>
</div>
</flex-col>
</new-bg>
</template>
<script>
import Map from "../../components/Map.vue";
import SystemTitle from "../../components/smallCommon/SystemTitle.vue";
import NewBg from "../../components/NewBg.vue";
import FlexCol from "../../components/FlexCol.vue";
import ModuleContent from "../../components/ModuleContent.vue";
import Butgroup from "../../components/smallCommon/butgroup.vue";
import CusButton from "../../components/smallCommon/CusButton.vue";
import Web3Title from "../../components/smallCommon/Web3Title.vue";
import ModuleContent2 from "../../components/smallCommon/ModuleContent2.vue";
import Split from "../../components/smallCommon/Split.vue";
import CusDesc from "../../components/smallCommon/CusDesc.vue";
import Web2Title from "../../components/smallCommon/Web2Title.vue";
import CustomDesc2 from "../../components/smallCommon/CusDesc2.vue";
import CusButton3 from "../../components/smallCommon/CusButton3.vue";
import CusButton5 from "../../components/smallCommon/CusButton5.vue";
export default {
name: "paifang",
components: {
CusButton5,
CusButton3,
CustomDesc2,
Web2Title,
CusDesc,
Split,
ModuleContent2,
Web3Title,
CusButton, Butgroup,
ModuleContent,
FlexCol, NewBg, SystemTitle,
Map
},
data () {
return {
tongji: {},
descColumns: [
{ title: '设备数量', key: 'total' },
{ title: '运行设备数量', key: 'total' },
{ title: '设备异常数量', key: 'total' },
{ title: '关闭设备数量', key: 'total' },
]
}
}
}
</script>

View File

@ -1,104 +1,106 @@
<template>
<div class="xichejiguanli">
<a-page-header
:ghost="false"
style="border-bottom: 1px solid rgb(235, 237, 240)"
title="洗车机管理"
@back="() => $router.go(-1)"
/>
<div class="_body">
<div class="left-list">
<new-bg>
<flex-col>
<system-title show-back/>
<Map></Map>
<ModuleContent padding="0px 50px 20px" class="event-none" none-event>
<web2-title>洗车机管理</web2-title>
<Split height="16"></Split>
<a-row :gutter="16" style="height: calc(100% - 62px);">
<a-col :span="5" style="height: 100%;">
<FlexCol>
<ModuleContent2 bg height="490">
<FlexCol>
<web3-title>洗车机列表</web3-title>
<Split height="10"></Split>
<ModuleContent2 :border="false" padding="0">
<div :class="['car-washing-machine-tabs',activeCarTabs ==1?'active-car-washing-machine-tabs':'']"
@click="carChange(1)">
<div class="rank-num">1</div>
<div class="car-washing-machine-name">西门洗车</div>
<div class="state-icon">
正常
<div :class="['car-washing-machine-tabs',activeCarTabs ==1?'active-car-washing-machine-tabs':'']"
@click="carChange(1)">
<div class="rank-num">1</div>
<div class="car-washing-machine-name">西门洗车</div>
<div class="state-icon">
正常
</div>
</div>
</div>
</div>
</ModuleContent2>
</FlexCol>
<div :class="['car-washing-machine-tabs',activeCarTabs ==2?'active-car-washing-machine-tabs':'']"
@click="carChange(2)">
<div class="rank-num">1</div>
<div class="car-washing-machine-name">西门洗车</div>
<div class="state-icon">
正常
</div>
</div>
</ModuleContent2>
<ModuleContent2 bg>
<FlexCol>
<web3-title>历史记录</web3-title>
<Split height="10"></Split>
<ModuleContent2 :border="false" padding="0">
<CustomTable
hide-action
hide-search
hide-button
:columns="columns"
:api-conf="apiConf"
:form-items="formItems"
@edit="editHandler"
>
<template slot="search-button" slot-scope="{ search }">
<a-button type="primary" @click="exportList(search)">导出历史数据</a-button>
<Split height="10"></Split>
</template>
</CustomTable>
</ModuleContent2>
</FlexCol>
</ModuleContent2>
</FlexCol>
<div :class="['car-washing-machine-tabs',activeCarTabs ==3?'active-car-washing-machine-tabs':'']"
@click="carChange(3)">
<div class="rank-num">1</div>
<div class="car-washing-machine-name">西门洗车</div>
<div class="state-icon">
正常
</div>
</div>
</div>
</a-col>
<a-col :span="5" :offset="14" style="height: 100%;">
<FlexCol>
<ModuleContent2 bg>
<FlexCol>
<web3-title>洗车机视频</web3-title>
<Split height="10"></Split>
<ModuleContent2 padding="0" :border="false" height="300px" >
<div class="center-content">
<div class="map-content">
<Map></Map>
</div>
<div class="table-content">
<Curd
hide-action
hide-search
hide-button
:columns="columns"
:api-conf="apiConf"
:form-items="formItems"
@edit="editHandler"
>
<template slot="search-button" slot-scope="{ search }">
<a-button type="primary" @click="exportList(search)">导出历史数据</a-button>
</template>
</Curd>
</div>
</div>
</ModuleContent2>
<web3-title>洗车机运行信息</web3-title>
<Split height="10"></Split>
<ModuleContent2 padding="0" :border="false">
<div class="right-content">
<div class="_title">洗车机视频</div>
<div class="car-wash-video">
</div>
</ModuleContent2>
</FlexCol>
<div class="_title">洗车机运行信息</div>
<div class="car-run-info">
<div class="_title" style="text-align: center;">xxx洗车机</div>
<div class="details-info">
<div class="details-info-item">
<div class="_title">运行状态</div>
<div class="_title">正常</div>
</div>
<div class="details-info-item">
<div class="_title">冲洗压力</div>
<div class="_title">500KPA</div>
</div>
<div class="details-info-item">
<div class="_title">冲洗电流</div>
<div class="_title">50A</div>
</div>
<div class="details-info-item">
<div class="_title">冲洗电压</div>
<div class="_title">500KV</div>
</div>
</div>
</div>
</div>
</div>
</div>
</ModuleContent2>
</FlexCol>
</a-col>
</a-row>
</ModuleContent>
</flex-col>
</new-bg>
</template>
<script>
import Map from "../../components/Map.vue";
import Curd from "../../components/smallCommon/Curd.vue";
import moment from "moment/moment";
import SystemTitle from "../../components/smallCommon/SystemTitle.vue";
import NewBg from "../../components/NewBg.vue";
import FlexCol from "../../components/FlexCol.vue";
import ModuleContent from "../../components/ModuleContent.vue";
import Web3Title from "../../components/smallCommon/Web3Title.vue";
import Split from "../../components/smallCommon/Split.vue";
import ModuleContent2 from "../../components/smallCommon/ModuleContent2.vue";
import CustomTable from "../../components/smallCommon/CustomTable.vue";
import Web2Title from "../../components/smallCommon/Web2Title.vue";
export default {
name: "xichejiguanli",
components: {
Web2Title,
CustomTable,
ModuleContent2,
Split,
Web3Title,
ModuleContent,
FlexCol, NewBg, SystemTitle,
Map,
Curd
},
@ -165,6 +167,18 @@ export default {
}
</script>
<style scoped lang="less">
.map-content {
height: 400px;
width: 100%;
position: relative;
}
.table-content {
flex: 1;
padding-top: 10px;
}
.xichejiguanli {
height: 100vh;
display: flex;
@ -214,25 +228,7 @@ export default {
}
}
.center-content {
flex: 1;
margin: 0 10px;
border: 1px solid #e8e8e8;
border-radius: 10px;
display: flex;
flex-flow: column;
.map-content {
height: 400px;
width: 100%;
position: relative;
}
.table-content {
flex: 1;
padding-top: 10px;
}
}
.right-content {
width: 300px;

View File

@ -1,94 +1,171 @@
<template>
<div class="paifang" style="height: 100vh;overflow: hidden">
<a-page-header
:ghost="false"
style="border-bottom: 1px solid rgb(235, 237, 240)"
title="有组织排放"
@back="() => $router.go(-1)"
/>
<a-row :gutter="16">
<a-col :span="6">
<a-card title="全厂有组织排放源" size="small">
<p>card content</p>
</a-card>
</a-col>
<a-col :span="6">
<a-card title="全厂重要排放源" size="small">
<p>card content</p>
</a-card>
</a-col>
<a-col :span="6">
<a-card title="当前区域排放源" size="small">
<p>card content</p>
</a-card>
</a-col>
<a-col :span="6">
<a-card title="当前区域其中重要排放源" size="small">
<p>card content</p>
</a-card>
</a-col>
</a-row>
<a-row style="height: calc(100% - 147px);margin-top: 16px;" :gutter="16">
<a-col :span="6" style="height: 100%;">
<a-card title="工序步骤" size="small">
<a-button type="primary" block>
Primary
</a-button>
<a-button type="primary" block class="mt16">
Primary
</a-button>
<a-button type="primary" block class="mt16">
Primary
</a-button>
<a-button type="primary" block class="mt16">
Primary
</a-button>
<a-button type="primary" block class="mt16">
Primary
</a-button>
<a-button type="primary" block class="mt16">
Primary
</a-button>
<new-bg>
<flex-col>
<system-title @click="changeTab" show-back/>
<Map></Map>
<ModuleContent padding="0px 50px 20px" class="event-none" none-event>
<web2-title>有组织排放</web2-title>
<a-row style="margin-top: 16px;" :gutter="16" class="event-none">
<a-col :span="17">
<div style="height: 112px;width: 100%;" class="event-auto">
<ModuleContent2 :border="false" padding="0">
<butgroup2 style="height: 100%;">
<ModuleContent2 bg bg-color border>
<miaoshu title="全厂有组织排放源" :value="count.comeCount" color="rgba(42, 207, 255, 1)"></miaoshu>
</ModuleContent2>
</a-card>
</a-col>
<a-col :span="12" style="height: 100%;">
<div style="height: 100%;position: relative">
<Map></Map>
</div>
</a-col>
<a-col :span="6" style="height: 100%;">
<a-table :columns="columns" :data-source="data" />
</a-col>
</a-row>
</div>
<ModuleContent2 bg bg-color border style="margin-left: 16px;">
<miaoshu title="全厂重要排放源" :value="count.outCount" color="rgba(255, 171, 87, 1)"></miaoshu>
</ModuleContent2>
<ModuleContent2 bg bg-color border style="margin-left: 16px;">
<miaoshu title="当前区域排放源" :value="count.inCount" color="rgba(122, 175, 255, 1)"></miaoshu>
</ModuleContent2>
<ModuleContent2 bg bg-color border style="margin-left: 16px;">
<miaoshu title="当前区域其中重要排放源" :value="count.addCount" color="rgba(76, 243, 129, 1)"></miaoshu>
</ModuleContent2>
</butgroup2>
</ModuleContent2>
<div class="gongxu-wrapper event-auto">
<web3-title>工序步骤</web3-title>
<div class="gongxu-box">
<div class="gongxu-item" v-for="item in gongxu" :key="item.id">
{{ item.name }}
</div>
</div>
</div>
</div>
</a-col>
<a-col :span="7">
<faguang class="custom-tab">
<a-tabs default-active-key="1" class="custom-tab">
<a-tab-pane key="1" tab="VOC">
<web3-title>排放源清单</web3-title>
<a-table :columns="columns" :data-source="data"/>
</a-tab-pane>
<a-tab-pane key="2" tab="CEMS" force-render>
<web3-title>排放源清单</web3-title>
<a-table :columns="columns" :data-source="data"/>
</a-tab-pane>
</a-tabs>
</faguang>
</a-col>
</a-row>
<butgroup class="bottom-btn">
<cus-button>
<nuxt-link to="/youzuzhi/paifangtongji">环保排放统计</nuxt-link>
<nuxt-link to="">DCS</nuxt-link>
<nuxt-link to="">日报周报月报</nuxt-link>
</cus-button>
</butgroup>
</ModuleContent>
</flex-col>
</new-bg>
</template>
<script>
import Map from "../../components/Map.vue";
import NewBg from "../../components/NewBg.vue";
import SystemTitle from "../../components/smallCommon/SystemTitle.vue";
import FlexCol from "../../components/FlexCol.vue";
import ModuleContent from "../../components/ModuleContent.vue";
import Butgroup2 from "../../components/smallCommon/butgroup2.vue";
import Miaoshu from "../../components/smallCommon/miaoshu.vue";
import ModuleContent2 from "../../components/smallCommon/ModuleContent2.vue";
import Web3Title from "../../components/smallCommon/Web3Title.vue";
import CusButton from "../../components/smallCommon/CusButton.vue";
import Butgroup from "../../components/smallCommon/butgroup.vue";
import Web2Title from "../../components/smallCommon/Web2Title.vue";
import Faguang from "../../components/smallCommon/Faguang.vue";
export default {
name: "paifang",
components: {
Faguang,
Web2Title,
Butgroup, CusButton,
Web3Title,
ModuleContent2, Miaoshu, Butgroup2,
ModuleContent,
FlexCol,
SystemTitle,
NewBg,
Map
},
data () {
data() {
return {
btns: [
{ title: 'VOC', key: '1' },
{ title: 'CEMS', key: '2' },
],
count: {},
data: [],
gongxu: [],
columns: [
{ title: '名词', key: 'name' },
{ title: 'NO', key: 'NO' },
{ title: 'SO2', key: 'SO2' },
{ title: 'TSP', key: 'TSP' },
{title: '名词', key: 'name'},
{title: 'NO', key: 'NO'},
{title: 'SO2', key: 'SO2'},
{title: 'TSP', key: 'TSP'},
]
}
},
mounted() {
this.getData(1)
},
methods: {
changeTab ({ key }) {
this.getData(key)
},
getData (deviceType) {
this.$get('/api/Organized/listanddevice', {
organizedType: 1,
deviceType: deviceType
}).then(({data}) => {
this.gongxu = data || []
})
}
}
}
</script>
<style scoped lang="less">
.mt16 {
.mt16 {
margin-top: 16px;
}
.gongxu-wrapper {
width: 132px;
max-height: 500px;
margin-top: 16px;
}
.gongxu-box {
height: calc(100% - 48px);
overflow-y: auto;
.gongxu-item {
cursor: pointer;
color: #fff;
border-bottom: 1px solid rgba(238, 238, 238, 0.54);
width: 132px;
height: 48px;
opacity: 1;
background: rgba(0, 128, 247, 0.5);
box-sizing: border-box;
margin-top: 16px;
line-height: 48px;
/** 文本1 */
font-size: 18px;
font-weight: 400;
letter-spacing: 0px;
color: rgba(255, 255, 255, 1);
text-align: center;
vertical-align: top;
&.selected, &:hover {
background: rgba(7, 65, 119, 0.98);
font-weight: 500;
color: rgba(45, 205, 255, 1);
}
}
}
</style>

View File

@ -1,37 +1,46 @@
<template>
<div class="paifangtongji" style="height: 100vh;overflow: hidden">
<a-page-header
:ghost="false"
style="border-bottom: 1px solid rgb(235, 237, 240)"
title="有组织排放统计"
@back="() => $router.go(-1)"
/>
<a-row :gutter="16">
<a-col :span="18">
</a-col>
<a-col :span="6">
<a-table :columns="columns" :data-source="data" />
</a-col>
</a-row>
</div>
<new-bg>
<flex-col>
<system-title show-back />
<ModuleContent padding="0px 20px 20px">
<web2-title>有组织排放统计</web2-title>
<split num="16"></split>
<a-tabs default-active-key="1" class="custom-tab">
<a-tab-pane key="1" tab="总体排放">
<a-table :columns="columns" :data-source="data"/>
</a-tab-pane>
<a-tab-pane key="2" tab="VOC">
<a-table :columns="columns" :data-source="data"/>
</a-tab-pane>
<a-tab-pane key="3" tab="CEMS" force-render>
<a-table :columns="columns" :data-source="data"/>
</a-tab-pane>
</a-tabs>
</ModuleContent>
</flex-col>
</new-bg>
</template>
<script>
import FlexCol from "../../components/FlexCol.vue";
import SystemTitle from "../../components/smallCommon/SystemTitle.vue";
import NewBg from "../../components/NewBg.vue";
import ModuleContent from "../../components/ModuleContent.vue";
import Web2Title from "../../components/smallCommon/Web2Title.vue";
import Web3Title from "../../components/smallCommon/Web3Title.vue";
import Split from "../../components/Split.vue";
export default {
name: "paifangtongji",
data () {
components: {Split, Web3Title, Web2Title, ModuleContent, NewBg, SystemTitle, FlexCol},
data() {
return {
data: [],
columns: [
{ title: '名词', key: 'name' },
{ title: 'NO', key: 'NO' },
{ title: 'SO2', key: 'SO2' },
{ title: 'TSP', key: 'TSP' },
{title: '名词', key: 'name'},
{title: 'NO', key: 'NO'},
{title: 'SO2', key: 'SO2'},
{title: 'TSP', key: 'TSP'},
]
}
}

View File

@ -1,10 +1,12 @@
import axios from 'axios' //引用axios
import { message } from 'ant-design-vue';
import Vue from 'vue'
import checkTypes from "../utils/checkTypes";
axios.defaults.withcredentials =true
// create an axios instance
const service = axios.create({
baseURL: process.env.NODE_ENV === 'development' ? '' : 'http://101.43.201.20:5000', // 所有异步请求都加上/api,nginx转发到后端Springboot
// baseURL: process.env.NODE_ENV === 'development' ? '' : 'http://101.43.201.20:5000', // 所有异步请求都加上/api,nginx转发到后端Springboot
baseURL: '', // 所有异步请求都加上/api,nginx转发到后端Springboot
timeout: 5000 // request timeout
})
@ -23,7 +25,9 @@ service.interceptors.request.use(
service.interceptors.response.use(
response => {
const res = response.data //res is my own data
if (!checkTypes.isObject(res)) {
return { data: res }
}
if (`${res.code}` === '0') {
return res
} else {

View File

@ -1,4 +1,4 @@
import Vue from 'vue'
import '@/utils/systemToolExtend'
Vue.prototype.$evBus = new Vue()

View File

@ -5,7 +5,7 @@ import { message } from 'ant-design-vue';
const service = axios.create({
baseURL: '', // 所有异步请求都加上/api,nginx转发到后端Springboot
withCredentials: true, // send cookies when cross-domain requests
timeout: 5000 // request timeout
timeout: 50000 // request timeout
})
// request interceptor

View File

@ -1,6 +1,7 @@
import { notification } from 'ant-design-vue'
export const state = {
title: '',
info: {}
info: null
}
export const mutations = {
@ -15,8 +16,18 @@ export const mutations = {
export const actions = {
setTitle ({ commit }, title) {
commit('setTitle', title)
document.title = title
},
setInfo ({ commit }, info) {
setInfo ({ commit, dispatch }, info) {
commit('setInfo', info)
dispatch('setTitle', info.home?.title || '')
if (info?.alerts) {
notification.error({
message: '温馨提示',
description: info?.alerts[0].alarmName,
onClick: () => { },
});
}
}
}

View File

@ -1,47 +1,217 @@
const XLSX = require('xlsx');
const fs = require('fs');
// 读取xlsx文件
const workbook = XLSX.readFile('./test.xlsx');
// 读取特定的worksheet默认第一个worksheet
const worksheet = workbook.Sheets['Sheet2'];
// 将worksheet转换为JSON对象
const jsonData = XLSX.utils.sheet_to_json(worksheet);
function dmsToDecimal(degrees, minutes, seconds) {
return degrees + minutes / 60 + seconds / 3600;
}
const c1 = [
'张子藤',
'刘嘉文',
'徐嘉豪',
'刘家泽',
'徐雅渲',
'张子悦',
'王奕萱',
'王卓然',
'云安琪',
'宁梓豪',
'崔晨岳',
'王紫涵',
'邢雨梵',
'程诗尧',
'特穆伦',
'姜智皓',
'梁芯蕊',
'李婕冉',
'李奕宣',
'郜梓涵',
'霍梓祺',
'吴若帆',
'韩熙莀',
'张宸雅',
'薛安琪',
'杜宇墨',
'杨宸赫',
'杨润泽',
'杨亿晨',
'银泽诚',
'姜锦岳',
'邵璟瑄',
'邢伊晨',
'赵家甫',
'孟昱杰',
'王亚萱',
'李睿辰',
'王一',
'庞毅阳',
'石浩栋',
'张佑宁',
'刘昊辰',
'郭馨瑶',
'张屹凯',
'陈琳',
'汪子翔',
'李苒',
'田昕',
'苏子琪',
'云索朵丽玛',
'马嘉铎',
'冯杰',
]
const results = []
for (const jsonDatum of jsonData) {
const location = jsonDatum['经纬度']
const [lat, lon] = location.split(' ')
let latStr = lat.replace(/\°|\'|["(N|E)]/g, '@')
let lonStr = lon.replace(/\°|\'|["(N|E)]/g, '@')
const [latDegrees, latMinutes, latSeconds] = latStr.split('@')
const [longDegrees, longMinutes, longSeconds] = lonStr.split('@')
const latitude = dmsToDecimal(parseInt(latDegrees), parseInt(latMinutes), parseInt(latSeconds));
const longitude = dmsToDecimal(parseInt(longDegrees), parseInt(longMinutes),parseInt( longSeconds));
results.push( {
longitude,
latitude
})
}
const c2 = ['安子涵',
'白明倧',
'陈颢元',
'陈诗菡',
'崔槿雯',
'崔伟宸',
'单铭竹',
'董轩宁',
'杜凌赫',
'冯婧',
'傅越琦',
'富钰涵',
'富振凯',
'高浚恺',
'韩梓钰',
'霍博臣',
'贾剀歆',
'贾梓墨',
'姜舒萌',
'李殿雍',
'李嘉祺',
'李水阳',
'李婉瑜',
'李宇晴',
'李子璐',
'刘牧格',
'刘一铭',
'刘亦凡',
'鲁屹',
'吕辰溪',
'马嘉锴',
'牛菡钰',
'邵逸凡',
'孙子懿',
'王楚喻',
'王轲纶',
'王若欣',
'王劭伊',
'王新雅',
'王鑫甫',
'王鑫妤',
'王艺博',
'王逸辰',
'王泽',
'魏宇彬',
'魏庄惠',
'吴浩轩',
'张佳荣',
'张茗禹',
'张若熙',
'张纹菲',
'张亦扬',
'张云睿',
'张泽昊',
'朱益楷',]
// 文件内容
const content = JSON.stringify(results, null, 2)
const b1 =
[
'王卓然',
'郜梓源',
'邵璟瑄',
'姜锦岳',
'冯杰',
'李苒',
'张子悦',
'汪子翔',
'王紫涵',
'郭馨瑶',
'杜宇墨',
'银泽诚',
'陈琳',
'石浩栋',
'张佑宁',
'云安琪',
'宁梓豪',
'刘家泽',
'张宸雅',
'云索朵丽玛',
'霍梓祺',
'刘嘉文',
'韩熙莀',
'特穆伦',
'徐嘉豪',
'苏子琪',
'徐雅渲',
'杨宸赫',
'马嘉铎',
'李睿辰',
'姜智皓',
'杨亿晨',
'王亚萱',
'张屹凯',
'王奕萱',
'庞毅阳',
'邢雨梵',
'杨润泽',
'孟昱杰',
'刘昊辰',
'王一',
'李婕冉',
'李睿辰妈妈',
'田昕',
'薛安琪',
'李奕宣',
'李奕宣爸爸',
'程诗尧',
]
// 文件路径
const filePath = './output.json';
// 写入文件
fs.writeFile(filePath, content, 'utf8', function(err) {
if (err) {
return console.log(err);
}
console.log('文件已保存');
});
const b2 = [
'王泽',
'李宇晴',
'张云睿',
'魏庄惠',
'张亦扬',
'刘牧格',
'张纹菲',
'邵逸凡',
'安子涵',
'朱益楷',
'张泽昊',
'张佳荣',
'牛菡钰',
'崔伟宸',
'王逸辰',
'李殿雍',
'陈颢元',
'孙子懿',
'刘一铭',
'贾剀歆',
'崔槿雯',
'韩梓钰',
'魏宇彬',
'高浚恺',
'吕辰溪',
'王轲纶',
'杜凌赫',
'王艺博',
'张若熙',
'李水阳',
'霍博臣',
'鲁屹',
'李子璐',
'冯婧',
'王鑫甫、妤',
'贾芓墨',
'傅越琦',
'马嘉锴',
'王劭伊',
'五劭伊',
'李婉瑜',
'王新雅',
'富钰涵',
'王楚喻',
]
console.log('四一班:', c1.filter(name => !b1.includes(name)))
console.log('四六班:', c2.filter(name => !b2.includes(name)))

View File

@ -1,9 +1,4 @@
/**
* @Description: 工具类
* @ComponentName: tools
* @Author: wangzhigang11
* @Date: 2022-08-08 14:30
*/
// 开始动画
export const raf =
window.requestAnimationFrame ||

155
utils/systemToolExtend.js Normal file
View File

@ -0,0 +1,155 @@
/**
* @Description: 扩展基类原型方法
* @ComponentName: System.tools
* @Author: wangzhigang11
* @Date: 2022-06-24 19:35
*/
/**
* 扩展基类原型方法已载入全局基类可直接调用
* @module common/systemToolExtend
* @Author: wangzhigang11
* @Date: 2022-07-19 14:07
*/
import checkTypes from "@/utils/checkTypes";
const ArrayPrototype = Array.prototype
const NumberPrototype = Number.prototype
const StringPrototype = String.prototype
const FilePrototype = File.prototype
/**
* 根据内容结果获取列表中的内容项
* @function
* @param { string } code 编码
* @param { string } itemKey 列表项中的筛选项 默认为value
* @example
* const arr1 = [ { label: 'xxx', value: 1 }, { label: 'yyy', value: 2 } ]
* arr1.getItemByCode(1) // -> { label: 'xxx', value: 1 }
* * const arr2 = [ { a: '1', b: 2 }, { a: '3', b: 4 } ]
* arr2.getItemByCode(1, 'a') // -> { a: '1', b: 2 }
* @returns {object}
*/
ArrayPrototype.getItemByCode = function (code, itemKey = 'value') {
if (!checkTypes.isArray(this)) return {}
for (const item of this) {
if (`${item[itemKey]}` === `${code}`) return item
}
return {}
}
/**
* 根据逗号分割的内容获取结果
* @param { string[] } code 需要查找的内容
* @param { string } code 需要查找的内容
* @param { object } option 查找的配置
* @param { string } option.label 查找结果字符串的映射字段
* @param { string } option.key 查找结果的键的映射字段
* @param { string } option.separator 分割符默认为','
* @param { string } option.emptyText 查找结果无效时显示的内容
* @example
* const arr = [{id: 1, name: '小红'}, [id: 3, name: '小明']]
* arr.getLabelByCodes('1,3', { label: 'name', key: 'id' }) // => '小红,小明'
* arr.getLabelByCodes('1,3', { label: 'name', key: 'id', separator: '/' }) // => '小红/小明'
* @returns {string}
*/
ArrayPrototype.getLabelByCodes = function (code, option = {}) {
if (!checkTypes.isArray(this)) return ''
const curCode = checkTypes.isNumber(code) && code === 0 ? '0' : code || ''
let filterCode = []
if (checkTypes.isArray(code)) {
filterCode = code.filter(item => !!item)
} else {
filterCode = `${curCode}`.split(',').filter(item => !!item)
}
return filterCode.map(itemCode => {
return this.getItemByCode(itemCode, option.key || 'value')[option.label || 'label'] || ''
}).filter(item => item !== '').join(option.separator || ',') || option.emptyText || ''
}
ArrayPrototype.getIndexByCode = function (code, itemKey = 'value') {
return this.findIndex(cur => cur[itemKey] === code)
}
ArrayPrototype.hasCode = function (code, key = 'value') {
const filter = this.findIndex(item => item[key] === code)
return filter >= 0
}
/**
* 数据处理工具保留小数点后几位并添加单位
* @function superFixed
* @private
* @param { number} len 保留位数
* @param { string } unit 单位
* @example
* const test = 1
* test.superFixed(2) // => 1.00
* test.superFixed(2, '个') // => '1.00个'
* @returns {string|number}
*/
NumberPrototype.superFixed = function (len = 0, unit = '') {
return (this || 0).toFixed(len) + unit
}
/**
* 数据处理工具保留小数点后几位并添加单位
* @function superFixed
* @param { number} len 保留位数
* @param { string } unit 单位
* @example
* const test1 = '1'
* test1.superFixed(2) // => 1.00
* test1.superFixed(2) // => 1.00
* const test2 = 1
* test2.superFixed(2) // => 1.00
* test2.superFixed(2, '个') // => '1.00个'
* @returns {string|number}
*/
StringPrototype.superFixed = function (len = 0, unit = '') {
// 如果是数字型字符串 返回保留后的
if (/^[-\+]?[\d]*\.?[\d]*$/.test(this)) return Number(this).superFixed(len, unit)
// 如果是其他字符串,返回本身
return this
}
function base64ToBlob(base64) {
const parts = base64.split(';base64,');
const contentType = parts[0].split(':')[1];
const raw = window.atob(parts[1]);
const rawLength = raw.length;
const uInt8Array = new Uint8Array(rawLength);
for (let i = 0; i < rawLength; ++i) {
uInt8Array[i] = raw.charCodeAt(i);
}
return new Blob([uInt8Array], {type: contentType});
}
StringPrototype.toFile = function () {
// 使用Base64字符串创建一个File对象
return new File([base64ToBlob(this)], `file_${new Date().valueOf()}`, {
type: 'image/png',
})
}
/**
* 文件转base64
* @param {boolean} splitHeader 是否需要切掉base64头
* @example
* file.toBase64() // => 'image/jpeg;base64,VFZSSmVrMVVTWG8lM0Q='
* file.toBase64(true) // => 'VFZSSmVrMVVTWG8lM0Q='
* @returns {string}
*/
FilePrototype.toBase64 = function (splitHeader = false) {
return new Promise((resolve, reject) => {
const fileReader = new FileReader()
fileReader.readAsDataURL(this)
fileReader.onload = (e) => {
let base64Str = e.target.result
if (splitHeader) {
base64Str = base64Str.substr(base64Str.indexOf(',') + 1)
}
resolve(base64Str)
}
})
}

9
webpack.config.js Normal file
View File

@ -0,0 +1,9 @@
const path = require('path');
module.exports = {
resolve: {
alias: {
'@': path.resolve(__dirname, './'),
}
}
};