Browse Source

增加表报统计板块

develop
fuguobin 1 year ago
parent
commit
55ef106c14
  1. 13
      src/api/table/list.ts
  2. 15
      src/api/table/types.ts
  3. 12
      src/lang/en.ts
  4. 12
      src/lang/zh-cn.ts
  5. 13
      src/layout/components/AppMain.vue
  6. 12
      src/mock/routes.json
  7. 4
      src/types/auto-imports.d.ts
  8. 8
      src/views/dashboard/index.scss
  9. 13
      src/views/details/index.scss
  10. 3
      src/views/details/index.vue
  11. 76
      src/views/login/index.vue
  12. 9
      src/views/monitoring/devicemanage/index.scss
  13. 1
      src/views/monitoring/devicemanage/index.vue
  14. 71
      src/views/monitoring/screen/index.scss
  15. 56
      src/views/monitoring/screen/index.vue
  16. 14
      src/views/statistical/index.scss
  17. 144
      src/views/statistical/index.vue
  18. 2
      vite.config.ts

13
src/api/table/list.ts

@ -87,3 +87,16 @@ export function sendCtrl(data: any) {
data: data
});
}
/**
*
*
* @param queryParams
*/
export function dcBusiDayReport(queryParams: any) {
return request({
url: '/dc/dcBusiDayReport/list',
method: 'get',
params: queryParams
});
}

15
src/api/table/types.ts

@ -76,3 +76,18 @@ export interface extVo {
export interface RoleQuery {
time: string;
}
/**
*
*/
export interface StatVo {
adate: null;
aday: string;
amonth: string;
aparamcode: string;
auuid: string;
aval: number;
ayear: string;
devicName: string;
paramName: string;
}

12
src/lang/en.ts

@ -2,9 +2,9 @@ export default {
// 路由国际化
route: {
dashboard: 'Dashboard',
system:'System Management',
user:'User',
role:'Role',
system: 'System Management',
user: 'User',
role: 'Role'
},
// 登录页面国际化
login: {
@ -13,12 +13,14 @@ export default {
password: 'Password',
login: 'Login',
verifyCode: 'Verify Code',
copyright: 'All Rights Reserved.',
group: 'Luenmei Smart Energy Technology (Shenyang) Co., Ltd',
abbreviation: 'Luenmei Smart',
copyright: 'All Rights Reserved.'
},
// 导航栏国际化
navbar: {
dashboard: 'Dashboard',
logout: 'Logout',
document: 'Document',
document: 'Document'
}
};

12
src/lang/zh-cn.ts

@ -2,9 +2,9 @@ export default {
// 路由国际化
route: {
dashboard: '首页',
system:'系统管理',
user:'用户管理',
roel:'角色管理',
system: '系统管理',
user: '用户管理',
roel: '角色管理'
},
// 登录页面国际化
login: {
@ -13,12 +13,14 @@ export default {
password: '密码',
login: '登 录',
verifyCode: '验证码',
copyright: '版权所有',
group: '联美智慧能源科技(沈阳)有限公司',
abbreviation: '联美智慧',
copyright: '版权所有'
},
// 导航栏国际化
navbar: {
dashboard: '首页',
logout: '注销',
document: '项目文档',
document: '项目文档'
}
};

13
src/layout/components/AppMain.vue

@ -7,6 +7,7 @@
</keep-alive>
</transition>
</router-view>
<div class="copyright">Copyright © 2023 {{ $t('login.abbreviation') }} {{ $t('login.copyright') }}</div>
</section>
</template>
@ -25,9 +26,19 @@ const tagsViewStore = useTagsViewStore();
padding: 15px;
overflow: hidden;
background-color: var(--el-bg-color-page);
.copyright {
width: 100%;
height: 50px;
line-height: 50px;
text-align: center;
color: #9ca3af;
font-family: Arial;
font-size: 12px;
letter-spacing: 1px;
}
}
.fixed-header+.appContainer {
.fixed-header + .appContainer {
padding-top: 84px;
min-height: 100vh;
}

12
src/mock/routes.json

@ -35,6 +35,18 @@
"roles": ["biadmin"],
"keepAlive": true
}
},
{
"path": "/statistical",
"component": "statistical/index",
"name": "statistical",
"meta": {
"title": "报表统计",
"icon": "chart",
"hidden": false,
"roles": ["biadmin"],
"keepAlive": true
}
}
]
}

4
src/types/auto-imports.d.ts

@ -5,6 +5,8 @@ declare global {
const ElForm: typeof import('element-plus/es')['ElForm']
const ElMessage: typeof import('element-plus/es')['ElMessage']
const ElMessageBox: typeof import('element-plus/es')['ElMessageBox']
const ElNotification: typeof import('element-plus/es')['ElNotification']
const NEllipsis: typeof import('naive-ui')['NEllipsis']
const asyncComputed: typeof import('@vueuse/core')['asyncComputed']
const autoResetRef: typeof import('@vueuse/core')['autoResetRef']
const computed: typeof import('vue')['computed']
@ -274,6 +276,8 @@ declare module 'vue' {
readonly ElForm: UnwrapRef<typeof import('element-plus/es')['ElForm']>
readonly ElMessage: UnwrapRef<typeof import('element-plus/es')['ElMessage']>
readonly ElMessageBox: UnwrapRef<typeof import('element-plus/es')['ElMessageBox']>
readonly ElNotification: UnwrapRef<typeof import('element-plus/es')['ElNotification']>
readonly NEllipsis: UnwrapRef<typeof import('naive-ui')['NEllipsis']>
readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']>
readonly autoResetRef: UnwrapRef<typeof import('@vueuse/core')['autoResetRef']>
readonly computed: UnwrapRef<typeof import('vue')['computed']>

8
src/views/dashboard/index.scss

@ -38,18 +38,18 @@
padding: 16px;
border-radius: 8px;
color: #fff;
h3{
h3 {
font-size: 18px;
margin: 0;
}
.data{
.data {
display: flex;
justify-content: space-between;
margin-top: 10px;
.iconfont{
.iconfont {
font-size: 22px;
}
span{
span {
font-size: 28px;
}
}

13
src/views/details/index.scss

@ -1,5 +1,5 @@
.details {
padding: 1.5rem;
padding: 1.5rem 1.5rem 0 1.5rem;
.header {
margin-bottom: 1.5rem;
}
@ -32,7 +32,7 @@
.comparisonInfo {
.stackedLine {
width: 100%;
height: 68vh;
height: 66vh;
font-size: 1.4rem;
text-align: center;
color: #606266;
@ -40,4 +40,13 @@
}
}
}
.copyright {
height: 30px;
line-height: 30px;
text-align: center;
color: #9ca3af;
font-family: Arial;
font-size: 12px;
letter-spacing: 1px;
}
}

3
src/views/details/index.vue

@ -102,6 +102,7 @@
<div ref="stackedRef" class="stackedLine">暂无数据</div>
</div>
</el-card>
<div class="copyright">Copyright © 2023 {{ $t('login.abbreviation') }} {{ $t('login.copyright') }}</div>
</div>
</template>
<script lang="ts" setup>
@ -120,7 +121,7 @@ const router = useRouter();
const route = useRoute();
const searchRef = ref<FormInstance>();
const defaultTime = new Date(2000, 1, 1, 12, 0, 0); // '12:00:00'
const defaultTime: [Date, Date] = [new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 12, 0, 0)];
// const multipleLimit = ref(0);
const parameterLimit = ref(0);
const deptId = ref(0);

76
src/views/login/index.vue

@ -11,8 +11,14 @@
<div class="icon">
<i class="iconfont icon-user"></i>
</div>
<el-input class="flex-1" ref="username" name="username" size="large" v-model="loginData.username"
:placeholder="$t('login.username')" />
<el-input
class="flex-1"
ref="username"
name="username"
size="large"
v-model="loginData.username"
:placeholder="$t('login.username')"
/>
</el-form-item>
<el-tooltip content="Caps lock is On" placement="right" :disabled="isCapslock === false">
@ -20,8 +26,16 @@
<div class="icon">
<i class="iconfont icon-lock"></i>
</div>
<el-input class="flex-1" name="password" type="password" size="large" v-model="loginData.password"
:placeholder="$t('login.password')" show-password @keyup="checkCapslock" />
<el-input
class="flex-1"
name="password"
type="password"
size="large"
v-model="loginData.password"
:placeholder="$t('login.password')"
show-password
@keyup="checkCapslock"
/>
</el-form-item>
</el-tooltip>
@ -41,13 +55,21 @@
</el-button>
</el-form>
</div>
<video class="video" :style="resizeStyle" autoplay loop muted v-on:canplay="onCanplay" v-if="settingsStore.showVideo">
<video
class="video"
:style="resizeStyle"
autoplay
loop
muted
v-on:canplay="onCanplay"
v-if="settingsStore.showVideo"
>
<source src="../../assets/images/login-bg.mp4" type="video/mp4" />
</video>
<div class="videoCover" v-if="!videoCanPlay && settingsStore.showVideo">
<img :style="resizeStyle" src="../../assets/images/login-bg.png" alt="视频封面">
<img :style="resizeStyle" src="../../assets/images/login-bg.png" alt="视频封面" />
</div>
<div class="copyright">Copyright © 2023 Luenmei {{ $t('login.copyright') }}</div>
<div class="copyright">Copyright © 2023 {{ $t('login.group') }} {{ $t('login.copyright') }}</div>
</div>
</template>
@ -64,13 +86,13 @@ const settingsStore = useSettingsStore();
const userStore = useUserStore();
const route = useRoute();
const loginForm = ref(ElForm);
const isCapslock = ref(false);//
const resizeStyle = ref()//
const videoCanPlay = ref(false)
const isCapslock = ref(false); //
const resizeStyle = ref(); //
const videoCanPlay = ref(false);
const loginData = ref<LoginData>({
username: '',
password: '',
password: ''
// verifyCode: ''
});
@ -100,19 +122,19 @@ onMounted(() => {
// getCaptcha();
resizeStyle.value = {
height: '100vh',
width: '100vw',
}
width: '100vw'
};
});
function onCanplay() {
//
videoCanPlay.value = true
videoCanPlay.value = true;
}
window.addEventListener('resize', () => {
//
resizeFun()
})
resizeFun();
});
//
// function getCaptcha() {
@ -151,29 +173,29 @@ function loginClick() {
function resizeFun() {
//
const windowWidth = document.body.clientWidth
const windowHeight = document.body.clientHeight
const windowAspectRatio = windowHeight / windowWidth
let videoWidth
let videoHeight
const windowWidth = document.body.clientWidth;
const windowHeight = document.body.clientHeight;
const windowAspectRatio = windowHeight / windowWidth;
let videoWidth;
let videoHeight;
if (windowAspectRatio < 0.5625) {
videoWidth = windowWidth
videoHeight = videoWidth * 0.5625
videoWidth = windowWidth;
videoHeight = videoWidth * 0.5625;
resizeStyle.value = {
height: windowWidth * 0.5625 + 'px',
width: windowWidth + 'px',
'margin-bottom': (windowHeight - videoHeight) / 2 + 'px',
'margin-left': 'initial'
}
};
} else {
videoHeight = windowHeight
videoWidth = videoHeight / 0.5625
videoHeight = windowHeight;
videoWidth = videoHeight / 0.5625;
resizeStyle.value = {
height: windowHeight + 'px',
width: windowHeight / 0.5625 + 'px',
'margin-left': (windowWidth - videoWidth) / 2 + 'px',
'margin-bottom': 'initial'
}
};
}
}
</script>

9
src/views/monitoring/devicemanage/index.scss

@ -709,6 +709,15 @@
background-color: transparent;
}
}
.copyright {
height: 25px;
line-height: 25px;
text-align: center;
color: #9ca3af;
font-family: Arial;
font-size: 12px;
letter-spacing: 1px;
}
}
.dark {

1
src/views/monitoring/devicemanage/index.vue

@ -11,6 +11,7 @@
<Main :sidebarHeight="sidebarHeight" />
</div>
</section>
<div class="copyright">Copyright © 2023 {{ $t('login.abbreviation') }} {{ $t('login.copyright') }}</div>
</div>
</template>
<script lang="ts" setup>

71
src/views/monitoring/screen/index.scss

@ -73,6 +73,16 @@
-webkit-transform: rotate(180deg);
transition: transform 0.5s;
}
.copyright {
width: 100%;
height: 25px;
line-height: 25px;
text-align: center;
color: #9ca3af;
font-family: Arial;
font-size: 12px;
letter-spacing: 1px;
}
}
.panelBtn.left {
@ -162,7 +172,7 @@
.sidebar {
width: 12%;
height: calc(100vh - 95px - 30px); //屏幕高度-头部header高度-底部高度
height: calc(100vh - 95px - 50px); //屏幕高度-头部header高度-底部高度
flex-shrink: 0;
border: 1px solid var(--vxe-table-border-color);
padding: 10px 0;
@ -323,7 +333,7 @@
// --vxe-table-border-color: none;
// --vxe-font-color: #5beff9;
// --vxe-table-header-font-color: #ffffffb3;
// border: 1px solid #0d55b0;
// border: 1px solid var(--vxe-font-color);
// box-shadow: inset 0px 0px 10px 0px rgb(36, 90, 124);
:deep(.vxe-table) {
@ -339,7 +349,7 @@
font-weight: 800;
color: #eee;
background-color: #1169c0;
// border: 1px solid rgba(12, 80, 166, 1) !important;
// border: 1px solid var(--vxe-font-color) !important;
border-left: none !important;
.vxe-resizable.is--line:before {
@ -362,7 +372,9 @@
font-weight: 500;
.tableCellClass {
background-color: #f2f3f5;
// border-bottom: 1px solid #265a89 !important;
// border-bottom: 1px solid var(--vxe-font-color) !important;
// border-right: 1px solid var(--vxe-font-color) !important;
// border-right-color: var(--vxe-font-color) !important;
.vxe-cell {
font-family: 'AlibabaPuHuiTiRegular';
// color: #b1e3ff;
@ -627,7 +639,7 @@
background-color: #a8a8a8;
}
.tableGrid :-webkit-scrollbar-thumb:active {
.tableGrid ::-webkit-scrollbar-thumb:active {
background-color: #787878;
}
@ -639,7 +651,11 @@
}
// .cardClass {
.showTree {
.treeCard {
.showTree {
height: 50vh;
overflow: auto;
.weight {
display: flex;
align-items: center;
@ -649,21 +665,48 @@
margin-right: 2px;
}
}
}
.treeBtn {
}
.treeBtn {
margin-top: 20px;
text-align: right;
.n-button {
margin-left: 10px;
}
}
}
/*滚动条整体部分*/
.showTree::-webkit-scrollbar {
width: 8px;
height: 8px;
}
.treeCard {
.showTree {
height: 50vh;
overflow: auto;
/*滚动条的轨道*/
.showTree::-webkit-scrollbar-track {
background-color: transparent;
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
border-radius: 8px;
}
/*滚动条里面的小方块,能向上向下移动*/
.showTree::-webkit-scrollbar-thumb {
background-color: rgb(147, 147, 153, 0.5);
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
border-radius: 8px;
}
.showTree::-webkit-scrollbar-thumb:hover {
background-color: #a8a8a8;
}
.showTree:-webkit-scrollbar-thumb:active {
background-color: #787878;
}
/*边角,即两个滚动条的交汇处*/
.showTree::-webkit-scrollbar-corner {
background-color: transparent;
}
}

56
src/views/monitoring/screen/index.vue

@ -1,8 +1,13 @@
<template>
<div ref="screenRef" class="screen">
<section ref="titleRef" class="header">
<Header :titleData="titleData" :settingShow="true" :warningShow="true" @showModalClick="showModalClick"
@returnClick="returnClick" />
<Header
:titleData="titleData"
:settingShow="true"
:warningShow="true"
@showModalClick="showModalClick"
@returnClick="returnClick"
/>
<!-- <div class="title">
<h3>{{ titleData }}</h3>
</div>
@ -74,12 +79,13 @@
</div>
<div class="panelBtn" :class="menuShow ? 'left' : 'right'" @click="panelClick">
<i class="iconfont icon-arrow-up" :class="!panelShow ? 'up' : 'down'"></i>
<div class="copyright">Copyright © 2023 {{ $t('login.abbreviation') }} {{ $t('login.copyright') }}</div>
<!-- <n-button type="info" size="tiny" ghost @click="panelClick">按钮</n-button> -->
</div>
</div>
</template>
<script lang="ts" setup>
import { useRoute, useRouter, onBeforeRouteLeave } from "vue-router";
import { useRoute, useRouter, onBeforeRouteLeave } from 'vue-router';
// import { useDateFormat, useNow } from '@vueuse/core';
// import { Filter, Maximize, Settings, Power } from '@vicons/tabler';
import Header from '../components/header.vue';
@ -87,12 +93,12 @@ import Menu from '../components/menu.vue';
import Main from './components/main.vue';
import InfoPanel from './components/infoPanel.vue';
import ShowTree from './components/showTree.vue';
import useStorage from '@/utils/useStorage'
import useStorage from '@/utils/useStorage';
import socket from '@/utils/socket';
const sessionStorageIns = useStorage('sessionStorage');
const route = useRoute()
const router = useRouter()
const route = useRoute();
const router = useRouter();
// import calendar from '@/utils/lunar';
// const currentTime = useDateFormat(useNow(), 'YYYY-MM-DD HH:mm:ss');
// const lunarDay: any = calendar.solarToLunar(
@ -106,18 +112,18 @@ const showModal = ref(false);
const screenRef = ref<HTMLElement>();
const titleRef = ref<HTMLElement>();
const sidebar = ref<HTMLElement>();
const sidebarHeight = ref()
const sidebarHeight = ref();
const headerData = ref([]);
const mainWidth = ref(87)
const titleData = ref('')
const menuShow = ref(true)
const panelShow = ref(false)
const panelHeight = ref(0)
const mainWidth = ref(87);
const titleData = ref('');
const menuShow = ref(true);
const panelShow = ref(false);
const panelHeight = ref(0);
onMounted(() => {
// titleRef.value?.clientHeight; //
const offsetHeight = sidebar.value?.offsetHeight; //
sidebarHeight.value = offsetHeight === undefined ? 0 : offsetHeight - panelHeight.value
sidebarHeight.value = offsetHeight === undefined ? 0 : offsetHeight - panelHeight.value;
// menuShow.value=localStorage.getItem('menuShow')===undefined?true:JSON.parse(localStorage.getItem('menuShow'));
// console.log("sidebar:", sidebar.value?.offsetHeight)
});
@ -125,22 +131,22 @@ onMounted(() => {
window.addEventListener('resize', () => {
//
const offsetHeight = sidebar.value?.offsetHeight; //
sidebarHeight.value = offsetHeight === undefined ? 0 : offsetHeight - panelHeight.value
console.log("监听sidebar:", sidebar.value?.offsetHeight)
sidebarHeight.value = offsetHeight === undefined ? 0 : offsetHeight - panelHeight.value;
console.log('监听sidebar:', sidebar.value?.offsetHeight);
});
onBeforeRouteLeave((to, from) => {
//
console.log("onBeforeRouteLeave--", to.path, from.path)
console.log('onBeforeRouteLeave--', to.path, from.path);
if (to.path != from.path) {
console.log('离开页面');
socket.close(false)
socket.close(false);
}
})
});
function tableMenuData(data: any) {
//
titleData.value = data[0].deptName
titleData.value = data[0].deptName;
}
function tableHeaderData(data: any) {
@ -163,22 +169,22 @@ function cancelClick() {
function returnClick(val: string) {
//
router.replace("/dashboard")
router.replace('/dashboard');
}
function menuIsShow() {
//
menuShow.value = !menuShow.value
mainWidth.value = menuShow.value ? 87 : 100
menuShow.value = !menuShow.value;
mainWidth.value = menuShow.value ? 87 : 100;
sessionStorageIns.setUseStorage('menuShow', menuShow.value);
}
function panelClick() {
//
panelShow.value = !panelShow.value
panelHeight.value = panelShow.value ? 300 : 0
panelShow.value = !panelShow.value;
panelHeight.value = panelShow.value ? 300 : 0;
const offsetHeight = sidebar.value?.offsetHeight; //
sidebarHeight.value = offsetHeight === undefined ? 0 : offsetHeight - panelHeight.value
sidebarHeight.value = offsetHeight === undefined ? 0 : offsetHeight - panelHeight.value;
sessionStorageIns.setUseStorage('panelShow', panelShow.value);
}

14
src/views/statistical/index.scss

@ -0,0 +1,14 @@
.statisticalContainer {
.search {
margin-bottom: 15px;
.el-form-item--default {
margin-bottom: 0;
}
}
.statistical {
.statPagination {
justify-content: right;
margin-top: 15px;
}
}
}

144
src/views/statistical/index.vue

@ -0,0 +1,144 @@
<template>
<div class="statisticalContainer">
<section class="search">
<el-card shadow="always">
<el-form
ref="searchFormRef"
:model="searchForm"
:rules="rules"
:inline="true"
label-width="120px"
class="searchForm"
status-icon
>
<el-form-item label="时间" prop="qDate">
<el-date-picker
v-model="searchForm.qDate"
type="date"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
placeholder="请选择时间"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm(searchFormRef)">查询</el-button>
<el-button @click="resetForm(searchFormRef)">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</section>
<section class="statistical">
<el-card shadow="always">
<el-table class="statTable" :data="statData" border style="width: 100%">
<el-table-column prop="devicName" label="设备名" align="center" />
<el-table-column prop="paramName" label="参数名" align="center" />
<el-table-column prop="aval" label="均值" align="center" />
<el-table-column prop="aday" label="日" align="center" />
<el-table-column prop="amonth" label="月" align="center" />
</el-table>
<el-pagination
class="statPagination"
:page-sizes="[10, 20, 30, 40, 50]"
layout="sizes, prev, pager, next"
background
:total="statPage.total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</el-card>
</section>
</div>
</template>
<script lang="ts" setup>
import type { FormInstance, FormRules, TableColumnCtx } from 'element-plus';
import { useDateFormat, useNow } from '@vueuse/core';
import { dcBusiDayReport } from '@/api/table/list';
import { StatVo } from '@/api/table/types';
interface searchForm {
qDate: string;
}
interface SpanMethodProps {
row: StatVo;
column: TableColumnCtx<StatVo>;
rowIndex: number;
columnIndex: number;
}
const searchFormRef = ref<FormInstance>();
const searchForm = reactive<searchForm>({
qDate: ''
});
const rules = reactive<FormRules<searchForm>>({
qDate: [
{
type: 'date',
required: true,
message: '请选择时间',
trigger: 'change'
}
]
});
const today = useDateFormat(useNow(), 'YYYY-MM-DD');
const statData = ref<StatVo[]>([]);
const statPage = reactive({
total: 0,
pageNum: 1,
pageSize: 10
});
onMounted(() => {
searchForm.qDate = today.value;
getDayReport();
});
function getDayReport() {
//
const params = {
qDate: searchForm.qDate,
pageNum: statPage.pageNum,
pageSize: statPage.pageSize
};
dcBusiDayReport(params).then((res: any) => {
if (res.code === 200) {
statData.value = res.rows;
statPage.total = res.total;
}
});
}
const handleSizeChange = (val: number) => {
statPage.pageSize = val;
getDayReport();
};
const handleCurrentChange = (val: number) => {
statPage.pageNum = val;
getDayReport();
};
const submitForm = async (formEl: FormInstance | undefined) => {
if (!formEl) return;
await formEl.validate((valid, fields) => {
if (valid) {
getDayReport();
} else {
console.log('error submit!', fields);
}
});
};
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return;
formEl.resetFields();
searchForm.qDate = today.value;
getDayReport();
};
</script>
<style lang="scss" scoped>
@import './index.scss';
</style>

2
vite.config.ts

@ -45,7 +45,7 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
hmr: true, //配置HMR
proxy: {
'/dev-api': {
// target: 'http://172.1.2.6:9010/', //本地接口地址
// target: 'http://172.1.2.132:9010/', //本地接口地址
// target: 'http://172.1.2.158:9010/', //本地接口地址
target: 'http://10.10.10.56:9010/', //线上测试接口地址
changeOrigin: true,

Loading…
Cancel
Save