|
@@ -1,154 +1,158 @@
|
|
|
<template>
|
|
<template>
|
|
|
- <div class="statistics-page bg">
|
|
|
|
|
- <header class="header">运行记录填报统计</header>
|
|
|
|
|
-
|
|
|
|
|
- <main class="statistics-content">
|
|
|
|
|
- <el-row :gutter="16" class="section-row">
|
|
|
|
|
- <el-col :span="24">
|
|
|
|
|
- <el-card class="chart-card filter-card panel" shadow="never">
|
|
|
|
|
- <div class="panel-title panel-title--md">
|
|
|
|
|
- <div class="icon-decorator">
|
|
|
|
|
- <span></span>
|
|
|
|
|
- <span></span>
|
|
|
|
|
- </div>
|
|
|
|
|
- 筛选条件
|
|
|
|
|
- </div>
|
|
|
|
|
- <el-form
|
|
|
|
|
- class="filter-form"
|
|
|
|
|
- :model="queryParams"
|
|
|
|
|
- ref="queryFormRef"
|
|
|
|
|
- :inline="true"
|
|
|
|
|
- label-width="68px">
|
|
|
|
|
- <el-form-item label="所属部门" prop="project_name">
|
|
|
|
|
- <el-tree-select
|
|
|
|
|
- v-model="queryParams.deptId"
|
|
|
|
|
- :data="deptList"
|
|
|
|
|
- :props="defaultProps"
|
|
|
|
|
- check-strictly
|
|
|
|
|
- node-key="id"
|
|
|
|
|
- filterable
|
|
|
|
|
- placeholder="请选择所在部门"
|
|
|
|
|
- clearable
|
|
|
|
|
- style="width: 180px" />
|
|
|
|
|
- </el-form-item>
|
|
|
|
|
- <el-form-item label="创建时间" prop="createTime">
|
|
|
|
|
- <el-date-picker
|
|
|
|
|
- v-model="queryParams.createTime"
|
|
|
|
|
- value-format="YYYY-MM-DD HH:mm:ss"
|
|
|
|
|
- type="daterange"
|
|
|
|
|
- :shortcuts="rangeShortcuts"
|
|
|
|
|
- start-placeholder="开始日期"
|
|
|
|
|
- end-placeholder="结束日期"
|
|
|
|
|
- :default-time="datePickerDefaultTime"
|
|
|
|
|
- class="!w-220px" />
|
|
|
|
|
- </el-form-item>
|
|
|
|
|
- <el-form-item class="filter-actions">
|
|
|
|
|
- <el-button class="action-btn" size="default" @click="handleQuery">
|
|
|
|
|
- <Icon icon="ep:search" class="mr-5px" /> 搜索
|
|
|
|
|
- </el-button>
|
|
|
|
|
- <el-button class="action-btn" size="default" @click="resetQuery">
|
|
|
|
|
- <Icon icon="ep:refresh" class="mr-5px" /> 重置
|
|
|
|
|
- </el-button>
|
|
|
|
|
- </el-form-item>
|
|
|
|
|
- </el-form>
|
|
|
|
|
- </el-card>
|
|
|
|
|
- </el-col>
|
|
|
|
|
- </el-row>
|
|
|
|
|
-
|
|
|
|
|
- <el-row :gutter="16" class="section-row">
|
|
|
|
|
- <el-col :span="12">
|
|
|
|
|
- <el-card class="chart-card panel" shadow="never">
|
|
|
|
|
- <div class="panel-title">
|
|
|
|
|
- <div class="icon-decorator">
|
|
|
|
|
- <span></span>
|
|
|
|
|
- <span></span>
|
|
|
|
|
- </div>
|
|
|
|
|
- 运行记录工单统计
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="metric-grid metric-grid--order">
|
|
|
|
|
- <button
|
|
|
|
|
- v-for="item in orderMetricCards"
|
|
|
|
|
- :key="item.key"
|
|
|
|
|
- type="button"
|
|
|
|
|
- class="metric-card"
|
|
|
|
|
- :style="{
|
|
|
|
|
- '--metric-accent': item.accent,
|
|
|
|
|
- '--metric-glow': item.glow,
|
|
|
|
|
- '--metric-progress': `${item.percent}%`
|
|
|
|
|
- }"
|
|
|
|
|
- @click="openFill(queryParams.deptId, item.status, queryParams.createTime)">
|
|
|
|
|
- <span class="metric-card__label">{{ item.label }}</span>
|
|
|
|
|
- <strong class="metric-card__value">
|
|
|
|
|
- <count-to
|
|
|
|
|
- class="metric-card__count"
|
|
|
|
|
- :start-val="0"
|
|
|
|
|
- :end-val="item.value"
|
|
|
|
|
- :duration="800"
|
|
|
|
|
- separator="" />
|
|
|
|
|
- </strong>
|
|
|
|
|
- <span class="metric-card__hint">{{ item.hint }}</span>
|
|
|
|
|
- <span class="metric-card__progress">
|
|
|
|
|
- <span></span>
|
|
|
|
|
- </span>
|
|
|
|
|
- </button>
|
|
|
|
|
- </div>
|
|
|
|
|
- </el-card>
|
|
|
|
|
- </el-col>
|
|
|
|
|
- <el-col :span="12">
|
|
|
|
|
- <el-card class="chart-card panel" shadow="never">
|
|
|
|
|
- <div class="panel-title">
|
|
|
|
|
- <div class="icon-decorator">
|
|
|
|
|
- <span></span>
|
|
|
|
|
- <span></span>
|
|
|
|
|
- </div>
|
|
|
|
|
- 运行记录设备统计
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="metric-grid metric-grid--device">
|
|
|
|
|
- <button
|
|
|
|
|
- v-for="item in deviceMetricCards"
|
|
|
|
|
- :key="item.key"
|
|
|
|
|
- type="button"
|
|
|
|
|
- class="metric-card"
|
|
|
|
|
- :style="{
|
|
|
|
|
- '--metric-accent': item.accent,
|
|
|
|
|
- '--metric-glow': item.glow,
|
|
|
|
|
- '--metric-progress': `${item.percent}%`
|
|
|
|
|
- }"
|
|
|
|
|
- @click="openForm(queryParams.deptId, item.status, queryParams.createTime)">
|
|
|
|
|
- <span class="metric-card__label">{{ item.label }}</span>
|
|
|
|
|
- <strong class="metric-card__value">
|
|
|
|
|
- <count-to
|
|
|
|
|
- class="metric-card__count"
|
|
|
|
|
- :start-val="0"
|
|
|
|
|
- :end-val="item.value"
|
|
|
|
|
- :duration="800"
|
|
|
|
|
- separator="" />
|
|
|
|
|
- </strong>
|
|
|
|
|
- <span class="metric-card__hint">{{ item.hint }}</span>
|
|
|
|
|
- <span class="metric-card__progress">
|
|
|
|
|
- <span></span>
|
|
|
|
|
- </span>
|
|
|
|
|
- </button>
|
|
|
|
|
- </div>
|
|
|
|
|
- </el-card>
|
|
|
|
|
- </el-col>
|
|
|
|
|
- </el-row>
|
|
|
|
|
-
|
|
|
|
|
- <el-row class="section-row trend-row">
|
|
|
|
|
- <el-col :span="24">
|
|
|
|
|
- <el-card class="chart-card trend-card panel" shadow="never">
|
|
|
|
|
- <div class="panel-title">
|
|
|
|
|
- <div class="icon-decorator">
|
|
|
|
|
- <span></span>
|
|
|
|
|
- <span></span>
|
|
|
|
|
- </div>
|
|
|
|
|
- 部门运行记录工单统计
|
|
|
|
|
- </div>
|
|
|
|
|
- <div ref="chartContainer" class="trend-chart"></div>
|
|
|
|
|
- </el-card>
|
|
|
|
|
- </el-col>
|
|
|
|
|
- </el-row>
|
|
|
|
|
- </main>
|
|
|
|
|
|
|
+ <div ref="wrapperRef" class="statistics-scale-wrapper bg absolute top-0 left-0 size-full z-10">
|
|
|
|
|
+ <div class="mx-a overflow-hidden" :style="targetWrapperStyle">
|
|
|
|
|
+ <div class="statistics-page bg" :style="targetAreaStyle">
|
|
|
|
|
+ <header class="header">运行记录填报统计</header>
|
|
|
|
|
+
|
|
|
|
|
+ <main class="statistics-content">
|
|
|
|
|
+ <el-row :gutter="16" class="section-row">
|
|
|
|
|
+ <el-col :span="24">
|
|
|
|
|
+ <el-card class="chart-card filter-card panel" shadow="never">
|
|
|
|
|
+ <div class="panel-title panel-title--md">
|
|
|
|
|
+ <div class="icon-decorator">
|
|
|
|
|
+ <span></span>
|
|
|
|
|
+ <span></span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ 筛选条件
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <el-form
|
|
|
|
|
+ class="filter-form"
|
|
|
|
|
+ :model="queryParams"
|
|
|
|
|
+ ref="queryFormRef"
|
|
|
|
|
+ :inline="true"
|
|
|
|
|
+ label-width="86px">
|
|
|
|
|
+ <el-form-item label="所属部门" prop="project_name">
|
|
|
|
|
+ <el-tree-select
|
|
|
|
|
+ v-model="queryParams.deptId"
|
|
|
|
|
+ :data="deptList"
|
|
|
|
|
+ :props="defaultProps"
|
|
|
|
|
+ check-strictly
|
|
|
|
|
+ node-key="id"
|
|
|
|
|
+ filterable
|
|
|
|
|
+ placeholder="请选择所在部门"
|
|
|
|
|
+ clearable
|
|
|
|
|
+ class="filter-control" />
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item label="创建时间" prop="createTime">
|
|
|
|
|
+ <el-date-picker
|
|
|
|
|
+ v-model="queryParams.createTime"
|
|
|
|
|
+ value-format="YYYY-MM-DD HH:mm:ss"
|
|
|
|
|
+ type="daterange"
|
|
|
|
|
+ :shortcuts="rangeShortcuts"
|
|
|
|
|
+ start-placeholder="开始日期"
|
|
|
|
|
+ end-placeholder="结束日期"
|
|
|
|
|
+ :default-time="datePickerDefaultTime"
|
|
|
|
|
+ class="filter-control filter-control--date" />
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item class="filter-actions">
|
|
|
|
|
+ <el-button class="action-btn" size="default" @click="handleQuery">
|
|
|
|
|
+ <Icon icon="ep:search" class="mr-5px" /> 搜索
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ <el-button class="action-btn" size="default" @click="resetQuery">
|
|
|
|
|
+ <Icon icon="ep:refresh" class="mr-5px" /> 重置
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ </el-form>
|
|
|
|
|
+ </el-card>
|
|
|
|
|
+ </el-col>
|
|
|
|
|
+ </el-row>
|
|
|
|
|
+
|
|
|
|
|
+ <el-row :gutter="16" class="section-row">
|
|
|
|
|
+ <el-col :span="12">
|
|
|
|
|
+ <el-card class="chart-card panel" shadow="never">
|
|
|
|
|
+ <div class="panel-title">
|
|
|
|
|
+ <div class="icon-decorator">
|
|
|
|
|
+ <span></span>
|
|
|
|
|
+ <span></span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ 运行记录工单统计
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="metric-grid metric-grid--order">
|
|
|
|
|
+ <button
|
|
|
|
|
+ v-for="item in orderMetricCards"
|
|
|
|
|
+ :key="item.key"
|
|
|
|
|
+ type="button"
|
|
|
|
|
+ class="metric-card"
|
|
|
|
|
+ :style="{
|
|
|
|
|
+ '--metric-accent': item.accent,
|
|
|
|
|
+ '--metric-glow': item.glow,
|
|
|
|
|
+ '--metric-progress': `${item.percent}%`
|
|
|
|
|
+ }"
|
|
|
|
|
+ @click="openFill(queryParams.deptId, item.status, queryParams.createTime)">
|
|
|
|
|
+ <span class="metric-card__label">{{ item.label }}</span>
|
|
|
|
|
+ <strong class="metric-card__value">
|
|
|
|
|
+ <count-to
|
|
|
|
|
+ class="metric-card__count"
|
|
|
|
|
+ :start-val="0"
|
|
|
|
|
+ :end-val="item.value"
|
|
|
|
|
+ :duration="800"
|
|
|
|
|
+ separator="" />
|
|
|
|
|
+ </strong>
|
|
|
|
|
+ <span class="metric-card__hint">{{ item.hint }}</span>
|
|
|
|
|
+ <span class="metric-card__progress">
|
|
|
|
|
+ <span></span>
|
|
|
|
|
+ </span>
|
|
|
|
|
+ </button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </el-card>
|
|
|
|
|
+ </el-col>
|
|
|
|
|
+ <el-col :span="12">
|
|
|
|
|
+ <el-card class="chart-card panel" shadow="never">
|
|
|
|
|
+ <div class="panel-title">
|
|
|
|
|
+ <div class="icon-decorator">
|
|
|
|
|
+ <span></span>
|
|
|
|
|
+ <span></span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ 运行记录设备统计
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="metric-grid metric-grid--device">
|
|
|
|
|
+ <button
|
|
|
|
|
+ v-for="item in deviceMetricCards"
|
|
|
|
|
+ :key="item.key"
|
|
|
|
|
+ type="button"
|
|
|
|
|
+ class="metric-card"
|
|
|
|
|
+ :style="{
|
|
|
|
|
+ '--metric-accent': item.accent,
|
|
|
|
|
+ '--metric-glow': item.glow,
|
|
|
|
|
+ '--metric-progress': `${item.percent}%`
|
|
|
|
|
+ }"
|
|
|
|
|
+ @click="openForm(queryParams.deptId, item.status, queryParams.createTime)">
|
|
|
|
|
+ <span class="metric-card__label">{{ item.label }}</span>
|
|
|
|
|
+ <strong class="metric-card__value">
|
|
|
|
|
+ <count-to
|
|
|
|
|
+ class="metric-card__count"
|
|
|
|
|
+ :start-val="0"
|
|
|
|
|
+ :end-val="item.value"
|
|
|
|
|
+ :duration="800"
|
|
|
|
|
+ separator="" />
|
|
|
|
|
+ </strong>
|
|
|
|
|
+ <span class="metric-card__hint">{{ item.hint }}</span>
|
|
|
|
|
+ <span class="metric-card__progress">
|
|
|
|
|
+ <span></span>
|
|
|
|
|
+ </span>
|
|
|
|
|
+ </button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </el-card>
|
|
|
|
|
+ </el-col>
|
|
|
|
|
+ </el-row>
|
|
|
|
|
+
|
|
|
|
|
+ <el-row class="section-row trend-row">
|
|
|
|
|
+ <el-col :span="24">
|
|
|
|
|
+ <el-card class="chart-card trend-card panel" shadow="never">
|
|
|
|
|
+ <div class="panel-title">
|
|
|
|
|
+ <div class="icon-decorator">
|
|
|
|
|
+ <span></span>
|
|
|
|
|
+ <span></span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ 部门运行记录工单统计
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div ref="chartContainer" class="trend-chart"></div>
|
|
|
|
|
+ </el-card>
|
|
|
|
|
+ </el-col>
|
|
|
|
|
+ </el-row>
|
|
|
|
|
+ </main>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
</div>
|
|
</div>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
@@ -169,6 +173,7 @@ import { CanvasRenderer } from 'echarts/renderers'
|
|
|
import { IotStatApi } from '@/api/pms/stat'
|
|
import { IotStatApi } from '@/api/pms/stat'
|
|
|
import CountTo from '@/components/count-to1.vue'
|
|
import CountTo from '@/components/count-to1.vue'
|
|
|
import { computed, ref, reactive, onMounted, onUnmounted } from 'vue'
|
|
import { computed, ref, reactive, onMounted, onUnmounted } from 'vue'
|
|
|
|
|
+import { DESIGN_HEIGHT, DESIGN_WIDTH } from '@/utils/kb'
|
|
|
import { defaultProps, handleTree } from '@/utils/tree'
|
|
import { defaultProps, handleTree } from '@/utils/tree'
|
|
|
import * as DeptApi from '@/api/system/dept'
|
|
import * as DeptApi from '@/api/system/dept'
|
|
|
import type { DeptVO } from '@/api/system/dept'
|
|
import type { DeptVO } from '@/api/system/dept'
|
|
@@ -192,6 +197,37 @@ const datePickerDefaultTime: [Date, Date] = [
|
|
|
dayjs().startOf('day').toDate(),
|
|
dayjs().startOf('day').toDate(),
|
|
|
dayjs().endOf('day').toDate()
|
|
dayjs().endOf('day').toDate()
|
|
|
]
|
|
]
|
|
|
|
|
+const wrapperRef = ref<HTMLDivElement>()
|
|
|
|
|
+const scale = ref(1)
|
|
|
|
|
+
|
|
|
|
|
+let resizeObserver: ResizeObserver | null = null
|
|
|
|
|
+let resizeRaf = 0
|
|
|
|
|
+
|
|
|
|
|
+const targetWrapperStyle = computed(() => ({
|
|
|
|
|
+ width: `${DESIGN_WIDTH * scale.value}px`,
|
|
|
|
|
+ height: `${DESIGN_HEIGHT * scale.value}px`
|
|
|
|
|
+}))
|
|
|
|
|
+
|
|
|
|
|
+const targetAreaStyle = computed(() => ({
|
|
|
|
|
+ '--kb-scale': scale.value,
|
|
|
|
|
+ width: `${DESIGN_WIDTH * scale.value}px`,
|
|
|
|
|
+ height: `${DESIGN_HEIGHT * scale.value}px`
|
|
|
|
|
+}))
|
|
|
|
|
+
|
|
|
|
|
+function updateScale() {
|
|
|
|
|
+ cancelAnimationFrame(resizeRaf)
|
|
|
|
|
+
|
|
|
|
|
+ resizeRaf = requestAnimationFrame(() => {
|
|
|
|
|
+ const wrapper = wrapperRef.value
|
|
|
|
|
+ if (!wrapper) return
|
|
|
|
|
+
|
|
|
|
|
+ const { clientWidth, clientHeight } = wrapper
|
|
|
|
|
+ if (!clientWidth || !clientHeight) return
|
|
|
|
|
+
|
|
|
|
|
+ scale.value = Math.min(clientWidth / DESIGN_WIDTH, clientHeight / DESIGN_HEIGHT)
|
|
|
|
|
+ nextTick(handleResize)
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
const getDefaultTimeRange = () => {
|
|
const getDefaultTimeRange = () => {
|
|
|
const end = dayjs()
|
|
const end = dayjs()
|
|
@@ -659,7 +695,12 @@ onMounted(async () => {
|
|
|
queryParams.deptId = useUserStore().getUser.deptId ?? null
|
|
queryParams.deptId = useUserStore().getUser.deptId ?? null
|
|
|
|
|
|
|
|
Object.assign(initialQueryParams, queryParams)
|
|
Object.assign(initialQueryParams, queryParams)
|
|
|
- window.addEventListener('resize', handleResize)
|
|
|
|
|
|
|
+ nextTick(updateScale)
|
|
|
|
|
+ resizeObserver = new ResizeObserver(updateScale)
|
|
|
|
|
+ if (wrapperRef.value) {
|
|
|
|
|
+ resizeObserver.observe(wrapperRef.value)
|
|
|
|
|
+ }
|
|
|
|
|
+ window.addEventListener('resize', updateScale)
|
|
|
|
|
|
|
|
getStats()
|
|
getStats()
|
|
|
getDevStats()
|
|
getDevStats()
|
|
@@ -667,7 +708,9 @@ onMounted(async () => {
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
onUnmounted(() => {
|
|
onUnmounted(() => {
|
|
|
- window.removeEventListener('resize', handleResize)
|
|
|
|
|
|
|
+ resizeObserver?.disconnect()
|
|
|
|
|
+ window.removeEventListener('resize', updateScale)
|
|
|
|
|
+ cancelAnimationFrame(resizeRaf)
|
|
|
chartInstance?.dispose()
|
|
chartInstance?.dispose()
|
|
|
chartInstance = null
|
|
chartInstance = null
|
|
|
})
|
|
})
|
|
@@ -676,30 +719,28 @@ onUnmounted(() => {
|
|
|
<style lang="scss" scoped>
|
|
<style lang="scss" scoped>
|
|
|
@import url('@/styles/kb.scss');
|
|
@import url('@/styles/kb.scss');
|
|
|
|
|
|
|
|
-.statistics-page {
|
|
|
|
|
- --kb-scale: 1;
|
|
|
|
|
|
|
+.statistics-scale-wrapper {
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
|
|
+.statistics-page {
|
|
|
display: flex;
|
|
display: flex;
|
|
|
- width: 100%;
|
|
|
|
|
- height: calc(
|
|
|
|
|
- 100vh - 20px - var(--top-tool-height) - var(--tags-view-height) - var(--app-footer-height)
|
|
|
|
|
- );
|
|
|
|
|
- min-height: 720px;
|
|
|
|
|
- overflow: auto;
|
|
|
|
|
|
|
+ overflow: hidden;
|
|
|
color: #24364f;
|
|
color: #24364f;
|
|
|
flex-direction: column;
|
|
flex-direction: column;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.statistics-content {
|
|
.statistics-content {
|
|
|
|
|
+ position: relative;
|
|
|
display: flex;
|
|
display: flex;
|
|
|
|
|
+ height: calc(100% - 52px * var(--kb-scale));
|
|
|
min-height: 0;
|
|
min-height: 0;
|
|
|
- padding: 16px 20px 20px;
|
|
|
|
|
- flex: 1;
|
|
|
|
|
|
|
+ padding: calc(44px * var(--kb-scale)) calc(20px * var(--kb-scale)) calc(20px * var(--kb-scale));
|
|
|
flex-direction: column;
|
|
flex-direction: column;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.section-row {
|
|
.section-row {
|
|
|
- margin-bottom: 14px;
|
|
|
|
|
|
|
+ margin-bottom: calc(14px * var(--kb-scale));
|
|
|
flex-shrink: 0;
|
|
flex-shrink: 0;
|
|
|
|
|
|
|
|
&:last-child {
|
|
&:last-child {
|
|
@@ -720,7 +761,7 @@ onUnmounted(() => {
|
|
|
overflow: hidden;
|
|
overflow: hidden;
|
|
|
background: linear-gradient(180deg, rgb(235 243 255 / 76%) 0%, rgb(221 233 251 / 58%) 100%);
|
|
background: linear-gradient(180deg, rgb(235 243 255 / 76%) 0%, rgb(221 233 251 / 58%) 100%);
|
|
|
border: 1px solid rgb(255 255 255 / 58%);
|
|
border: 1px solid rgb(255 255 255 / 58%);
|
|
|
- border-radius: 20px;
|
|
|
|
|
|
|
+ border-radius: calc(20px * var(--kb-scale));
|
|
|
box-shadow:
|
|
box-shadow:
|
|
|
inset 0 1px 0 rgb(255 255 255 / 72%),
|
|
inset 0 1px 0 rgb(255 255 255 / 72%),
|
|
|
0 18px 36px rgb(46 90 164 / 12%);
|
|
0 18px 36px rgb(46 90 164 / 12%);
|
|
@@ -740,40 +781,44 @@ onUnmounted(() => {
|
|
|
|
|
|
|
|
.filter-card {
|
|
.filter-card {
|
|
|
:deep(.el-card__body) {
|
|
:deep(.el-card__body) {
|
|
|
- padding-bottom: 6px;
|
|
|
|
|
|
|
+ padding-bottom: calc(6px * var(--kb-scale));
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.filter-form {
|
|
.filter-form {
|
|
|
display: flex;
|
|
display: flex;
|
|
|
flex-wrap: wrap;
|
|
flex-wrap: wrap;
|
|
|
- padding: 12px 16px 0;
|
|
|
|
|
- gap: 0 12px;
|
|
|
|
|
|
|
+ padding: calc(12px * var(--kb-scale)) calc(16px * var(--kb-scale)) 0;
|
|
|
|
|
+ gap: 0 calc(12px * var(--kb-scale));
|
|
|
|
|
|
|
|
:deep(.el-form-item) {
|
|
:deep(.el-form-item) {
|
|
|
- margin-bottom: 12px;
|
|
|
|
|
|
|
+ margin-bottom: calc(12px * var(--kb-scale));
|
|
|
align-items: center;
|
|
align-items: center;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
:deep(.el-form-item__label) {
|
|
:deep(.el-form-item__label) {
|
|
|
- height: 34px;
|
|
|
|
|
|
|
+ width: calc(86px * var(--kb-scale)) !important;
|
|
|
|
|
+ height: calc(34px * var(--kb-scale));
|
|
|
|
|
+ font-size: calc(14px * var(--kb-scale));
|
|
|
font-weight: 600;
|
|
font-weight: 600;
|
|
|
- line-height: 34px;
|
|
|
|
|
|
|
+ line-height: calc(34px * var(--kb-scale));
|
|
|
color: #03409b;
|
|
color: #03409b;
|
|
|
align-items: center;
|
|
align-items: center;
|
|
|
|
|
+ white-space: nowrap;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
:deep(.el-form-item__content) {
|
|
:deep(.el-form-item__content) {
|
|
|
align-items: center;
|
|
align-items: center;
|
|
|
- line-height: 34px;
|
|
|
|
|
|
|
+ line-height: calc(34px * var(--kb-scale));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
:deep(.el-input__wrapper),
|
|
:deep(.el-input__wrapper),
|
|
|
:deep(.el-select__wrapper) {
|
|
:deep(.el-select__wrapper) {
|
|
|
- min-height: 34px;
|
|
|
|
|
|
|
+ min-height: calc(34px * var(--kb-scale));
|
|
|
|
|
+ padding: 0 calc(11px * var(--kb-scale));
|
|
|
background: linear-gradient(180deg, rgb(255 255 255 / 92%) 0%, rgb(242 247 255 / 82%) 100%);
|
|
background: linear-gradient(180deg, rgb(255 255 255 / 92%) 0%, rgb(242 247 255 / 82%) 100%);
|
|
|
border: 1px solid rgb(255 255 255 / 88%);
|
|
border: 1px solid rgb(255 255 255 / 88%);
|
|
|
- border-radius: 8px;
|
|
|
|
|
|
|
+ border-radius: calc(8px * var(--kb-scale));
|
|
|
box-shadow:
|
|
box-shadow:
|
|
|
inset 0 1px 0 rgb(255 255 255 / 95%),
|
|
inset 0 1px 0 rgb(255 255 255 / 95%),
|
|
|
0 6px 12px rgb(152 181 230 / 12%);
|
|
0 6px 12px rgb(152 181 230 / 12%);
|
|
@@ -781,21 +826,33 @@ onUnmounted(() => {
|
|
|
|
|
|
|
|
:deep(.el-range-input),
|
|
:deep(.el-range-input),
|
|
|
:deep(.el-range-separator) {
|
|
:deep(.el-range-separator) {
|
|
|
|
|
+ font-size: calc(14px * var(--kb-scale));
|
|
|
color: #24364f;
|
|
color: #24364f;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+.filter-control {
|
|
|
|
|
+ width: calc(180px * var(--kb-scale));
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.filter-control--date {
|
|
|
|
|
+ width: calc(220px * var(--kb-scale));
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
.filter-actions {
|
|
.filter-actions {
|
|
|
- margin-left: 8px;
|
|
|
|
|
|
|
+ margin-left: calc(8px * var(--kb-scale));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.action-btn {
|
|
.action-btn {
|
|
|
- min-width: 88px;
|
|
|
|
|
|
|
+ height: calc(34px * var(--kb-scale));
|
|
|
|
|
+ min-width: calc(88px * var(--kb-scale));
|
|
|
|
|
+ padding: 0 calc(15px * var(--kb-scale));
|
|
|
|
|
+ font-size: calc(14px * var(--kb-scale));
|
|
|
font-weight: 600;
|
|
font-weight: 600;
|
|
|
color: #f5f9ff;
|
|
color: #f5f9ff;
|
|
|
background: linear-gradient(180deg, #83bcff 0%, #2f7ee9 58%, #1762d6 100%);
|
|
background: linear-gradient(180deg, #83bcff 0%, #2f7ee9 58%, #1762d6 100%);
|
|
|
border: 1px solid rgb(255 255 255 / 55%);
|
|
border: 1px solid rgb(255 255 255 / 55%);
|
|
|
- border-radius: 8px;
|
|
|
|
|
|
|
+ border-radius: calc(8px * var(--kb-scale));
|
|
|
box-shadow:
|
|
box-shadow:
|
|
|
inset 0 1px 0 rgb(255 255 255 / 58%),
|
|
inset 0 1px 0 rgb(255 255 255 / 58%),
|
|
|
0 4px 8px rgb(30 89 179 / 22%);
|
|
0 4px 8px rgb(30 89 179 / 22%);
|
|
@@ -810,9 +867,9 @@ onUnmounted(() => {
|
|
|
|
|
|
|
|
.metric-grid {
|
|
.metric-grid {
|
|
|
display: grid;
|
|
display: grid;
|
|
|
- min-height: 214px;
|
|
|
|
|
- padding: 12px 14px 16px;
|
|
|
|
|
- gap: 14px;
|
|
|
|
|
|
|
+ min-height: calc(214px * var(--kb-scale));
|
|
|
|
|
+ padding: calc(12px * var(--kb-scale)) calc(14px * var(--kb-scale)) calc(16px * var(--kb-scale));
|
|
|
|
|
+ gap: calc(14px * var(--kb-scale));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.metric-grid--order {
|
|
.metric-grid--order {
|
|
@@ -827,15 +884,15 @@ onUnmounted(() => {
|
|
|
position: relative;
|
|
position: relative;
|
|
|
display: flex;
|
|
display: flex;
|
|
|
min-width: 0;
|
|
min-width: 0;
|
|
|
- min-height: 168px;
|
|
|
|
|
- padding: 18px 18px 16px;
|
|
|
|
|
|
|
+ min-height: calc(168px * var(--kb-scale));
|
|
|
|
|
+ padding: calc(18px * var(--kb-scale)) calc(18px * var(--kb-scale)) calc(16px * var(--kb-scale));
|
|
|
overflow: hidden;
|
|
overflow: hidden;
|
|
|
text-align: left;
|
|
text-align: left;
|
|
|
cursor: pointer;
|
|
cursor: pointer;
|
|
|
background: linear-gradient(135deg, rgb(255 255 255 / 96%) 0%, rgb(239 246 255 / 88%) 100%),
|
|
background: linear-gradient(135deg, rgb(255 255 255 / 96%) 0%, rgb(239 246 255 / 88%) 100%),
|
|
|
radial-gradient(circle at 90% 12%, var(--metric-glow) 0%, rgb(255 255 255 / 0%) 38%);
|
|
radial-gradient(circle at 90% 12%, var(--metric-glow) 0%, rgb(255 255 255 / 0%) 38%);
|
|
|
border: 1px solid rgb(94 139 203 / 18%);
|
|
border: 1px solid rgb(94 139 203 / 18%);
|
|
|
- border-radius: 16px;
|
|
|
|
|
|
|
+ border-radius: calc(16px * var(--kb-scale));
|
|
|
box-shadow:
|
|
box-shadow:
|
|
|
inset 0 1px 0 rgb(255 255 255 / 92%),
|
|
inset 0 1px 0 rgb(255 255 255 / 92%),
|
|
|
0 10px 22px rgb(46 90 164 / 9%);
|
|
0 10px 22px rgb(46 90 164 / 9%);
|
|
@@ -850,10 +907,10 @@ onUnmounted(() => {
|
|
|
|
|
|
|
|
.metric-card::before {
|
|
.metric-card::before {
|
|
|
position: absolute;
|
|
position: absolute;
|
|
|
- top: 14px;
|
|
|
|
|
|
|
+ top: calc(14px * var(--kb-scale));
|
|
|
left: 0;
|
|
left: 0;
|
|
|
- width: 4px;
|
|
|
|
|
- height: calc(100% - 28px);
|
|
|
|
|
|
|
+ width: calc(4px * var(--kb-scale));
|
|
|
|
|
+ height: calc(100% - 28px * var(--kb-scale));
|
|
|
background: var(--metric-accent);
|
|
background: var(--metric-accent);
|
|
|
border-radius: 0 999px 999px 0;
|
|
border-radius: 0 999px 999px 0;
|
|
|
content: '';
|
|
content: '';
|
|
@@ -862,10 +919,10 @@ onUnmounted(() => {
|
|
|
|
|
|
|
|
.metric-card::after {
|
|
.metric-card::after {
|
|
|
position: absolute;
|
|
position: absolute;
|
|
|
- right: -28px;
|
|
|
|
|
- bottom: -42px;
|
|
|
|
|
- width: 116px;
|
|
|
|
|
- height: 116px;
|
|
|
|
|
|
|
+ right: calc(-28px * var(--kb-scale));
|
|
|
|
|
+ bottom: calc(-42px * var(--kb-scale));
|
|
|
|
|
+ width: calc(116px * var(--kb-scale));
|
|
|
|
|
+ height: calc(116px * var(--kb-scale));
|
|
|
pointer-events: none;
|
|
pointer-events: none;
|
|
|
background: radial-gradient(circle, var(--metric-glow) 0%, rgb(255 255 255 / 0%) 72%);
|
|
background: radial-gradient(circle, var(--metric-glow) 0%, rgb(255 255 255 / 0%) 72%);
|
|
|
content: '';
|
|
content: '';
|
|
@@ -879,7 +936,7 @@ onUnmounted(() => {
|
|
|
background: linear-gradient(135deg, rgb(255 255 255 / 100%) 0%, rgb(232 242 255 / 92%) 100%),
|
|
background: linear-gradient(135deg, rgb(255 255 255 / 100%) 0%, rgb(232 242 255 / 92%) 100%),
|
|
|
radial-gradient(circle at 90% 12%, var(--metric-glow) 0%, rgb(255 255 255 / 0%) 42%);
|
|
radial-gradient(circle at 90% 12%, var(--metric-glow) 0%, rgb(255 255 255 / 0%) 42%);
|
|
|
border-color: rgb(58 103 180 / 28%);
|
|
border-color: rgb(58 103 180 / 28%);
|
|
|
- transform: translateY(-4px);
|
|
|
|
|
|
|
+ transform: translateY(calc(-4px * var(--kb-scale)));
|
|
|
box-shadow:
|
|
box-shadow:
|
|
|
inset 0 1px 0 rgb(255 255 255 / 92%),
|
|
inset 0 1px 0 rgb(255 255 255 / 92%),
|
|
|
0 16px 28px rgb(41 89 164 / 16%);
|
|
0 16px 28px rgb(41 89 164 / 16%);
|
|
@@ -899,15 +956,15 @@ onUnmounted(() => {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.metric-card__label {
|
|
.metric-card__label {
|
|
|
- font-size: 14px;
|
|
|
|
|
|
|
+ font-size: calc(14px * var(--kb-scale));
|
|
|
font-weight: 700;
|
|
font-weight: 700;
|
|
|
color: #18345a;
|
|
color: #18345a;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.metric-card__value {
|
|
.metric-card__value {
|
|
|
- margin-top: 14px;
|
|
|
|
|
|
|
+ margin-top: calc(14px * var(--kb-scale));
|
|
|
font-family: YouSheBiaoTiHei, sans-serif;
|
|
font-family: YouSheBiaoTiHei, sans-serif;
|
|
|
- font-size: 38px;
|
|
|
|
|
|
|
+ font-size: calc(38px * var(--kb-scale));
|
|
|
font-weight: normal;
|
|
font-weight: normal;
|
|
|
line-height: 1;
|
|
line-height: 1;
|
|
|
color: var(--metric-accent);
|
|
color: var(--metric-accent);
|
|
@@ -931,16 +988,16 @@ onUnmounted(() => {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.metric-card__hint {
|
|
.metric-card__hint {
|
|
|
- margin-top: 8px;
|
|
|
|
|
- font-size: 12px;
|
|
|
|
|
|
|
+ margin-top: calc(8px * var(--kb-scale));
|
|
|
|
|
+ font-size: calc(12px * var(--kb-scale));
|
|
|
font-weight: 700;
|
|
font-weight: 700;
|
|
|
color: #536986;
|
|
color: #536986;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.metric-card__progress {
|
|
.metric-card__progress {
|
|
|
display: block;
|
|
display: block;
|
|
|
- height: 6px;
|
|
|
|
|
- margin-top: 14px;
|
|
|
|
|
|
|
+ height: calc(6px * var(--kb-scale));
|
|
|
|
|
+ margin-top: calc(14px * var(--kb-scale));
|
|
|
overflow: hidden;
|
|
overflow: hidden;
|
|
|
background: rgb(31 91 184 / 12%);
|
|
background: rgb(31 91 184 / 12%);
|
|
|
border-radius: 999px;
|
|
border-radius: 999px;
|
|
@@ -956,8 +1013,8 @@ onUnmounted(() => {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.trend-chart {
|
|
.trend-chart {
|
|
|
- min-height: 260px;
|
|
|
|
|
- padding: 8px 12px 14px;
|
|
|
|
|
|
|
+ min-height: calc(260px * var(--kb-scale));
|
|
|
|
|
+ padding: calc(8px * var(--kb-scale)) calc(12px * var(--kb-scale)) calc(14px * var(--kb-scale));
|
|
|
flex: 1;
|
|
flex: 1;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -968,31 +1025,4 @@ onUnmounted(() => {
|
|
|
:deep(.el-card) {
|
|
:deep(.el-card) {
|
|
|
--el-card-bg-color: transparent;
|
|
--el-card-bg-color: transparent;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
-@media (width <= 1366px) {
|
|
|
|
|
- .statistics-content {
|
|
|
|
|
- padding: 12px;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- .metric-grid {
|
|
|
|
|
- overflow-x: auto;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- .metric-grid--order,
|
|
|
|
|
- .metric-grid--device {
|
|
|
|
|
- grid-template-columns: repeat(4, minmax(132px, 1fr));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- .metric-card {
|
|
|
|
|
- min-height: 150px;
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-@media (width <= 1180px) {
|
|
|
|
|
- .metric-grid--order,
|
|
|
|
|
- .metric-grid--device {
|
|
|
|
|
- overflow-x: auto;
|
|
|
|
|
- grid-template-columns: repeat(4, minmax(140px, 1fr));
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
</style>
|
|
</style>
|