|
@@ -1,25 +1,21 @@
|
|
|
<script lang="ts" setup>
|
|
<script lang="ts" setup>
|
|
|
import * as echarts from 'echarts'
|
|
import * as echarts from 'echarts'
|
|
|
-import { kanbanApi } from '@/api/pms/qhse/index'
|
|
|
|
|
-import { IotDangerApi, IotMeasureCertApi, IotInstrumentApi } from '@/api/pms/qhse/index'
|
|
|
|
|
-import { useUserStore } from '@/store/modules/user'
|
|
|
|
|
-
|
|
|
|
|
-const userStore = useUserStore()
|
|
|
|
|
import {
|
|
import {
|
|
|
AlarmClock,
|
|
AlarmClock,
|
|
|
Checked,
|
|
Checked,
|
|
|
|
|
+ Clock,
|
|
|
CollectionTag,
|
|
CollectionTag,
|
|
|
DataAnalysis,
|
|
DataAnalysis,
|
|
|
DocumentChecked,
|
|
DocumentChecked,
|
|
|
Files,
|
|
Files,
|
|
|
Flag,
|
|
Flag,
|
|
|
Histogram,
|
|
Histogram,
|
|
|
- Clock,
|
|
|
|
|
- Opportunity,
|
|
|
|
|
Odometer,
|
|
Odometer,
|
|
|
Postcard,
|
|
Postcard,
|
|
|
Warning
|
|
Warning
|
|
|
} from '@element-plus/icons-vue'
|
|
} from '@element-plus/icons-vue'
|
|
|
|
|
+import { kanbanApi, IotDangerApi, IotInstrumentApi, IotMeasureCertApi } from '@/api/pms/qhse/index'
|
|
|
|
|
+import { useUserStore } from '@/store/modules/user'
|
|
|
import {
|
|
import {
|
|
|
ANIMATION,
|
|
ANIMATION,
|
|
|
CHART_RENDERER,
|
|
CHART_RENDERER,
|
|
@@ -29,6 +25,8 @@ import {
|
|
|
THEME,
|
|
THEME,
|
|
|
createTooltip
|
|
createTooltip
|
|
|
} from '@/utils/kb'
|
|
} from '@/utils/kb'
|
|
|
|
|
+import { DICT_TYPE, getBoolDictOptions, getStrDictOptions } from '@/utils/dict'
|
|
|
|
|
+import { formatDate } from '@/utils/formatTime'
|
|
|
|
|
|
|
|
defineOptions({
|
|
defineOptions({
|
|
|
name: 'PmsQhseKanban'
|
|
name: 'PmsQhseKanban'
|
|
@@ -42,6 +40,10 @@ type PermitStat = {
|
|
|
|
|
|
|
|
type SafeDayMap = Record<string, number>
|
|
type SafeDayMap = Record<string, number>
|
|
|
|
|
|
|
|
|
|
+type SummaryTabValue = 'home' | 'certificate'
|
|
|
|
|
+
|
|
|
|
|
+const userStore = useUserStore()
|
|
|
|
|
+
|
|
|
const wrapperRef = ref<HTMLDivElement>()
|
|
const wrapperRef = ref<HTMLDivElement>()
|
|
|
const hazardChartRef = ref<HTMLDivElement>()
|
|
const hazardChartRef = ref<HTMLDivElement>()
|
|
|
const safeDayChartRef = ref<HTMLDivElement>()
|
|
const safeDayChartRef = ref<HTMLDivElement>()
|
|
@@ -54,14 +56,17 @@ let resizeRaf = 0
|
|
|
let hazardChart: echarts.ECharts | null = null
|
|
let hazardChart: echarts.ECharts | null = null
|
|
|
let safeDayChart: echarts.ECharts | null = null
|
|
let safeDayChart: echarts.ECharts | null = null
|
|
|
let socChart: echarts.ECharts | null = null
|
|
let socChart: echarts.ECharts | null = null
|
|
|
-const summaryTabs = [
|
|
|
|
|
- { label: '首页', value: 'home' },
|
|
|
|
|
- { label: '证书信息', value: 'report' }
|
|
|
|
|
-] as const
|
|
|
|
|
-const activeSummaryTab = ref<(typeof summaryTabs)[number]['value']>('home')
|
|
|
|
|
|
|
+
|
|
|
|
|
+const summaryTabs: Array<{ label: string; value: SummaryTabValue }> = [
|
|
|
|
|
+ { label: '首页看板', value: 'home' },
|
|
|
|
|
+ { label: '证书信息', value: 'certificate' }
|
|
|
|
|
+]
|
|
|
|
|
+const activeSummaryTab = ref<SummaryTabValue>('home')
|
|
|
const summaryDate = ref('2026-06-02')
|
|
const summaryDate = ref('2026-06-02')
|
|
|
|
|
|
|
|
-const pageTitle = 'QHSE管理看板'
|
|
|
|
|
|
|
+const pageTitle = computed(() =>
|
|
|
|
|
+ activeSummaryTab.value === 'certificate' ? '证书信息看板' : 'QHSE管理看板'
|
|
|
|
|
+)
|
|
|
|
|
|
|
|
const summaryCards = ref([
|
|
const summaryCards = ref([
|
|
|
{
|
|
{
|
|
@@ -88,11 +93,10 @@ const summaryCards = ref([
|
|
|
glow: 'rgba(255, 90, 98, 0.26)',
|
|
glow: 'rgba(255, 90, 98, 0.26)',
|
|
|
icon: Warning
|
|
icon: Warning
|
|
|
},
|
|
},
|
|
|
-
|
|
|
|
|
{
|
|
{
|
|
|
title: '特种人员持证率',
|
|
title: '特种人员持证率',
|
|
|
value: 0,
|
|
value: 0,
|
|
|
- note: 'Warn:3',
|
|
|
|
|
|
|
+ note: 'Warn: 0',
|
|
|
accent: '#f2b800',
|
|
accent: '#f2b800',
|
|
|
glow: 'rgba(242, 184, 0, 0.22)',
|
|
glow: 'rgba(242, 184, 0, 0.22)',
|
|
|
icon: Postcard
|
|
icon: Postcard
|
|
@@ -106,7 +110,7 @@ const summaryCards = ref([
|
|
|
icon: DataAnalysis
|
|
icon: DataAnalysis
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
- title: '作业许可数量',
|
|
|
|
|
|
|
+ title: '作业许可证数量',
|
|
|
value: 0,
|
|
value: 0,
|
|
|
note: '',
|
|
note: '',
|
|
|
accent: '#4f8dff',
|
|
accent: '#4f8dff',
|
|
@@ -128,13 +132,13 @@ const riskZones = ref([
|
|
|
{ title: '', desc: '危化库 / 试压区 / 配电房', color: '#ff5b61', value: 0 }
|
|
{ title: '', desc: '危化库 / 试压区 / 配电房', color: '#ff5b61', value: 0 }
|
|
|
])
|
|
])
|
|
|
|
|
|
|
|
-const permitStats: PermitStat[] = [
|
|
|
|
|
|
|
+const permitStats = ref<PermitStat[]>([
|
|
|
{ label: '个人防护', value: 18, color: '#4f8dff' },
|
|
{ label: '个人防护', value: 18, color: '#4f8dff' },
|
|
|
{ label: '规范操作', value: 26, color: '#43c7ca' },
|
|
{ label: '规范操作', value: 26, color: '#43c7ca' },
|
|
|
{ label: '规范指挥', value: 12, color: '#ffb14a' },
|
|
{ label: '规范指挥', value: 12, color: '#ffb14a' },
|
|
|
{ label: '人员位置', value: 9, color: '#ff7a7a' },
|
|
{ label: '人员位置', value: 9, color: '#ff7a7a' },
|
|
|
{ label: '作业场所', value: 15, color: '#8d8cff' }
|
|
{ label: '作业场所', value: 15, color: '#8d8cff' }
|
|
|
-]
|
|
|
|
|
|
|
+])
|
|
|
|
|
|
|
|
const qualificationWarnings = ref([
|
|
const qualificationWarnings = ref([
|
|
|
{ label: '证件过期', value: 0, accent: '#ff7a7a' },
|
|
{ label: '证件过期', value: 0, accent: '#ff7a7a' },
|
|
@@ -211,81 +215,54 @@ function updateScale() {
|
|
|
if (!clientWidth || !clientHeight) return
|
|
if (!clientWidth || !clientHeight) return
|
|
|
|
|
|
|
|
scale.value = Math.min(clientWidth / DESIGN_WIDTH, clientHeight / DESIGN_HEIGHT)
|
|
scale.value = Math.min(clientWidth / DESIGN_WIDTH, clientHeight / DESIGN_HEIGHT)
|
|
|
|
|
+
|
|
|
|
|
+ nextTick(() => {
|
|
|
|
|
+ resizeHazardChart()
|
|
|
|
|
+ resizeSafeDayChart()
|
|
|
|
|
+ resizeSocChart()
|
|
|
|
|
+ })
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-const staticData = ref({})
|
|
|
|
|
|
|
+const staticData = ref<any>({})
|
|
|
|
|
+const safeDay = ref<SafeDayMap>({})
|
|
|
|
|
+const summaryPanel = ref<any>(null)
|
|
|
|
|
+const total = ref(0)
|
|
|
|
|
+const instrumentExpired = ref(0)
|
|
|
|
|
+
|
|
|
async function getStatic() {
|
|
async function getStatic() {
|
|
|
const res = await IotDangerApi.getDangerStatistics(userStore.user.deptId)
|
|
const res = await IotDangerApi.getDangerStatistics(userStore.user.deptId)
|
|
|
- staticData.value = res.classify
|
|
|
|
|
|
|
+ staticData.value = res.classify || []
|
|
|
|
|
|
|
|
- riskZones.value.forEach((zone, index: number) => {
|
|
|
|
|
- zone.value = staticData.value[index].count
|
|
|
|
|
- zone.title = `${staticData.value[index].classify}区`
|
|
|
|
|
|
|
+ riskZones.value.forEach((zone, index) => {
|
|
|
|
|
+ const item = staticData.value[index]
|
|
|
|
|
+ if (!item) return
|
|
|
|
|
+ zone.value = item.count || 0
|
|
|
|
|
+ zone.title = `${item.classify}区`
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-let expired = ref(0)
|
|
|
|
|
-let warn = ref(0)
|
|
|
|
|
async function getCertStatic() {
|
|
async function getCertStatic() {
|
|
|
const res = await IotMeasureCertApi.getIotMeasureCertStatistics(userStore.user.deptId)
|
|
const res = await IotMeasureCertApi.getIotMeasureCertStatistics(userStore.user.deptId)
|
|
|
- expired.value = res.expired
|
|
|
|
|
- warn.value = res.warn
|
|
|
|
|
-
|
|
|
|
|
- qualificationWarnings.value[0].value = expired.value
|
|
|
|
|
- qualificationWarnings.value[1].value = warn.value
|
|
|
|
|
|
|
+ qualificationWarnings.value[0].value = res.expired || 0
|
|
|
|
|
+ qualificationWarnings.value[1].value = res.warn || 0
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-onMounted(() => {
|
|
|
|
|
- supportsZoom.value = typeof CSS !== 'undefined' && CSS.supports?.('zoom', '1') === true
|
|
|
|
|
- nextTick(updateScale)
|
|
|
|
|
- resizeObserver = new ResizeObserver(updateScale)
|
|
|
|
|
- if (wrapperRef.value) {
|
|
|
|
|
- resizeObserver.observe(wrapperRef.value)
|
|
|
|
|
- }
|
|
|
|
|
- initHazardChart()
|
|
|
|
|
- initSafeDayChart()
|
|
|
|
|
- initSocChart()
|
|
|
|
|
- window.addEventListener('resize', updateScale)
|
|
|
|
|
- window.addEventListener('resize', resizeHazardChart)
|
|
|
|
|
- window.addEventListener('resize', resizeSafeDayChart)
|
|
|
|
|
- window.addEventListener('resize', resizeSocChart)
|
|
|
|
|
-})
|
|
|
|
|
-
|
|
|
|
|
-onUnmounted(() => {
|
|
|
|
|
- resizeObserver?.disconnect()
|
|
|
|
|
- window.removeEventListener('resize', updateScale)
|
|
|
|
|
- window.removeEventListener('resize', resizeHazardChart)
|
|
|
|
|
- window.removeEventListener('resize', resizeSafeDayChart)
|
|
|
|
|
- window.removeEventListener('resize', resizeSocChart)
|
|
|
|
|
- cancelAnimationFrame(resizeRaf)
|
|
|
|
|
- destroyHazardChart()
|
|
|
|
|
- destroySafeDayChart()
|
|
|
|
|
- destroySocChart()
|
|
|
|
|
-})
|
|
|
|
|
-
|
|
|
|
|
-// 仪器
|
|
|
|
|
-let total = ref(0)
|
|
|
|
|
-let instrumentExpired = ref(0)
|
|
|
|
|
-const getList = async () => {
|
|
|
|
|
- try {
|
|
|
|
|
- const data = await IotInstrumentApi.getInstrumentList({
|
|
|
|
|
- pageNo: 1,
|
|
|
|
|
- pageSize: 10,
|
|
|
|
|
- deptId: userStore.user.deptId
|
|
|
|
|
- })
|
|
|
|
|
- total.value = data.total
|
|
|
|
|
-
|
|
|
|
|
- const res = await IotInstrumentApi.getInstrumentStatistics(userStore.user.deptId)
|
|
|
|
|
|
|
+async function getInstrumentOverview() {
|
|
|
|
|
+ const listData = await IotInstrumentApi.getInstrumentList({
|
|
|
|
|
+ pageNo: 1,
|
|
|
|
|
+ pageSize: 10,
|
|
|
|
|
+ deptId: userStore.user.deptId
|
|
|
|
|
+ })
|
|
|
|
|
+ total.value = listData.total || 0
|
|
|
|
|
|
|
|
- instrumentExpired.value = res.expired
|
|
|
|
|
|
|
+ const statData = await IotInstrumentApi.getInstrumentStatistics(userStore.user.deptId)
|
|
|
|
|
+ instrumentExpired.value = statData.expired || 0
|
|
|
|
|
|
|
|
- bottomCards.value[1].lines = [
|
|
|
|
|
- `在用: ${total.value}台`,
|
|
|
|
|
- `待检: ${instrumentExpired.value}台(重点关注)`
|
|
|
|
|
- ]
|
|
|
|
|
- } finally {
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ bottomCards.value[1].lines = [
|
|
|
|
|
+ `在用: ${total.value}台`,
|
|
|
|
|
+ `待检: ${instrumentExpired.value}台(重点关注)`
|
|
|
|
|
+ ]
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function getHazardChartOption(): echarts.EChartsOption {
|
|
function getHazardChartOption(): echarts.EChartsOption {
|
|
@@ -314,12 +291,8 @@ function getHazardChartOption(): echarts.EChartsOption {
|
|
|
xAxis: {
|
|
xAxis: {
|
|
|
type: 'category',
|
|
type: 'category',
|
|
|
data: hazardBars.value.map((item) => item.label),
|
|
data: hazardBars.value.map((item) => item.label),
|
|
|
- axisLine: {
|
|
|
|
|
- show: false
|
|
|
|
|
- },
|
|
|
|
|
- axisTick: {
|
|
|
|
|
- show: false
|
|
|
|
|
- },
|
|
|
|
|
|
|
+ axisLine: { show: false },
|
|
|
|
|
+ axisTick: { show: false },
|
|
|
axisLabel: {
|
|
axisLabel: {
|
|
|
color: '#5b6f8f',
|
|
color: '#5b6f8f',
|
|
|
fontSize: 16,
|
|
fontSize: 16,
|
|
@@ -330,12 +303,8 @@ function getHazardChartOption(): echarts.EChartsOption {
|
|
|
},
|
|
},
|
|
|
yAxis: {
|
|
yAxis: {
|
|
|
type: 'value',
|
|
type: 'value',
|
|
|
- axisLine: {
|
|
|
|
|
- show: false
|
|
|
|
|
- },
|
|
|
|
|
- axisTick: {
|
|
|
|
|
- show: false
|
|
|
|
|
- },
|
|
|
|
|
|
|
+ axisLine: { show: false },
|
|
|
|
|
+ axisTick: { show: false },
|
|
|
axisLabel: {
|
|
axisLabel: {
|
|
|
color: '#8a9bb5',
|
|
color: '#8a9bb5',
|
|
|
fontSize: 13,
|
|
fontSize: 13,
|
|
@@ -364,21 +333,13 @@ function getHazardChartOption(): echarts.EChartsOption {
|
|
|
}
|
|
}
|
|
|
})),
|
|
})),
|
|
|
barWidth: 70,
|
|
barWidth: 70,
|
|
|
-
|
|
|
|
|
- backgroundStyle: {
|
|
|
|
|
- color: 'rgba(31, 91, 184, 0.06)',
|
|
|
|
|
- borderRadius: 0
|
|
|
|
|
- },
|
|
|
|
|
label: {
|
|
label: {
|
|
|
show: true,
|
|
show: true,
|
|
|
position: 'top',
|
|
position: 'top',
|
|
|
color: '#3c5f96',
|
|
color: '#3c5f96',
|
|
|
fontSize: 16,
|
|
fontSize: 16,
|
|
|
fontWeight: 700,
|
|
fontWeight: 700,
|
|
|
- fontFamily: FONT_FAMILY,
|
|
|
|
|
- formatter(params: any) {
|
|
|
|
|
- return `${params.value}`
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ fontFamily: FONT_FAMILY
|
|
|
},
|
|
},
|
|
|
emphasis: {
|
|
emphasis: {
|
|
|
itemStyle: {
|
|
itemStyle: {
|
|
@@ -392,9 +353,7 @@ function getHazardChartOption(): echarts.EChartsOption {
|
|
|
|
|
|
|
|
function initHazardChart() {
|
|
function initHazardChart() {
|
|
|
if (!hazardChartRef.value) return
|
|
if (!hazardChartRef.value) return
|
|
|
- if (hazardChart) {
|
|
|
|
|
- hazardChart.dispose()
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ hazardChart?.dispose()
|
|
|
hazardChart = echarts.init(hazardChartRef.value, undefined, {
|
|
hazardChart = echarts.init(hazardChartRef.value, undefined, {
|
|
|
renderer: CHART_RENDERER
|
|
renderer: CHART_RENDERER
|
|
|
})
|
|
})
|
|
@@ -402,8 +361,7 @@ function initHazardChart() {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function updateHazardChart() {
|
|
function updateHazardChart() {
|
|
|
- if (!hazardChart) return
|
|
|
|
|
- hazardChart.setOption(getHazardChartOption(), true)
|
|
|
|
|
|
|
+ hazardChart?.setOption(getHazardChartOption(), true)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function resizeHazardChart() {
|
|
function resizeHazardChart() {
|
|
@@ -411,16 +369,12 @@ function resizeHazardChart() {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function destroyHazardChart() {
|
|
function destroyHazardChart() {
|
|
|
- if (hazardChart) {
|
|
|
|
|
- hazardChart.dispose()
|
|
|
|
|
- hazardChart = null
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ hazardChart?.dispose()
|
|
|
|
|
+ hazardChart = null
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function getSafeDayEntries() {
|
|
function getSafeDayEntries() {
|
|
|
- const safeDayMap = (safeDay.value ?? {}) as SafeDayMap
|
|
|
|
|
-
|
|
|
|
|
- return Object.entries(safeDayMap)
|
|
|
|
|
|
|
+ return Object.entries(safeDay.value || {})
|
|
|
.map(([label, value]) => ({
|
|
.map(([label, value]) => ({
|
|
|
label,
|
|
label,
|
|
|
value: Number(value) || 0
|
|
value: Number(value) || 0
|
|
@@ -455,12 +409,8 @@ function getSafeDayChartOption(): echarts.EChartsOption {
|
|
|
}),
|
|
}),
|
|
|
xAxis: {
|
|
xAxis: {
|
|
|
type: 'value',
|
|
type: 'value',
|
|
|
- axisLine: {
|
|
|
|
|
- show: false
|
|
|
|
|
- },
|
|
|
|
|
- axisTick: {
|
|
|
|
|
- show: false
|
|
|
|
|
- },
|
|
|
|
|
|
|
+ axisLine: { show: false },
|
|
|
|
|
+ axisTick: { show: false },
|
|
|
axisLabel: {
|
|
axisLabel: {
|
|
|
color: '#263854',
|
|
color: '#263854',
|
|
|
fontSize: 12,
|
|
fontSize: 12,
|
|
@@ -476,12 +426,8 @@ function getSafeDayChartOption(): echarts.EChartsOption {
|
|
|
yAxis: {
|
|
yAxis: {
|
|
|
type: 'category',
|
|
type: 'category',
|
|
|
data: entries.map((item) => item.label),
|
|
data: entries.map((item) => item.label),
|
|
|
- axisLine: {
|
|
|
|
|
- show: false
|
|
|
|
|
- },
|
|
|
|
|
- axisTick: {
|
|
|
|
|
- show: false
|
|
|
|
|
- },
|
|
|
|
|
|
|
+ axisLine: { show: false },
|
|
|
|
|
+ axisTick: { show: false },
|
|
|
axisLabel: {
|
|
axisLabel: {
|
|
|
color: '#16263d',
|
|
color: '#16263d',
|
|
|
fontSize: 14,
|
|
fontSize: 14,
|
|
@@ -505,12 +451,6 @@ function getSafeDayChartOption(): echarts.EChartsOption {
|
|
|
{ offset: 0, color: '#78a0ec' },
|
|
{ offset: 0, color: '#78a0ec' },
|
|
|
{ offset: 1, color: '#6a90dd' }
|
|
{ offset: 1, color: '#6a90dd' }
|
|
|
])
|
|
])
|
|
|
- },
|
|
|
|
|
- emphasis: {
|
|
|
|
|
- itemStyle: {
|
|
|
|
|
- shadowBlur: 16,
|
|
|
|
|
- shadowColor: 'rgba(106, 144, 221, 0.34)'
|
|
|
|
|
- }
|
|
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
]
|
|
]
|
|
@@ -519,9 +459,7 @@ function getSafeDayChartOption(): echarts.EChartsOption {
|
|
|
|
|
|
|
|
function initSafeDayChart() {
|
|
function initSafeDayChart() {
|
|
|
if (!safeDayChartRef.value) return
|
|
if (!safeDayChartRef.value) return
|
|
|
- if (safeDayChart) {
|
|
|
|
|
- safeDayChart.dispose()
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ safeDayChart?.dispose()
|
|
|
safeDayChart = echarts.init(safeDayChartRef.value, undefined, {
|
|
safeDayChart = echarts.init(safeDayChartRef.value, undefined, {
|
|
|
renderer: CHART_RENDERER
|
|
renderer: CHART_RENDERER
|
|
|
})
|
|
})
|
|
@@ -529,8 +467,7 @@ function initSafeDayChart() {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function updateSafeDayChart() {
|
|
function updateSafeDayChart() {
|
|
|
- if (!safeDayChart) return
|
|
|
|
|
- safeDayChart.setOption(getSafeDayChartOption(), true)
|
|
|
|
|
|
|
+ safeDayChart?.setOption(getSafeDayChartOption(), true)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function resizeSafeDayChart() {
|
|
function resizeSafeDayChart() {
|
|
@@ -538,10 +475,8 @@ function resizeSafeDayChart() {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function destroySafeDayChart() {
|
|
function destroySafeDayChart() {
|
|
|
- if (safeDayChart) {
|
|
|
|
|
- safeDayChart.dispose()
|
|
|
|
|
- safeDayChart = null
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ safeDayChart?.dispose()
|
|
|
|
|
+ safeDayChart = null
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function getSocChartOption(): echarts.EChartsOption {
|
|
function getSocChartOption(): echarts.EChartsOption {
|
|
@@ -594,27 +529,22 @@ function getSocChartOption(): echarts.EChartsOption {
|
|
|
length: 10,
|
|
length: 10,
|
|
|
length2: 8
|
|
length2: 8
|
|
|
},
|
|
},
|
|
|
- data: permitStats.map((item) => ({
|
|
|
|
|
|
|
+ data: permitStats.value.map((item) => ({
|
|
|
name: item.label,
|
|
name: item.label,
|
|
|
value: item.value,
|
|
value: item.value,
|
|
|
itemStyle: {
|
|
itemStyle: {
|
|
|
color: item.color
|
|
color: item.color
|
|
|
}
|
|
}
|
|
|
- })),
|
|
|
|
|
- emphasis: {
|
|
|
|
|
- scale: true,
|
|
|
|
|
- scaleSize: 6
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ }))
|
|
|
}
|
|
}
|
|
|
],
|
|
],
|
|
|
graphic: [
|
|
graphic: [
|
|
|
{
|
|
{
|
|
|
type: 'text',
|
|
type: 'text',
|
|
|
- left: '28.8%',
|
|
|
|
|
|
|
+ left: '29%',
|
|
|
top: '43%',
|
|
top: '43%',
|
|
|
style: {
|
|
style: {
|
|
|
text: 'SOC卡',
|
|
text: 'SOC卡',
|
|
|
-
|
|
|
|
|
fill: '#6b7f9c',
|
|
fill: '#6b7f9c',
|
|
|
fontSize: 18,
|
|
fontSize: 18,
|
|
|
fontWeight: 700,
|
|
fontWeight: 700,
|
|
@@ -627,8 +557,7 @@ function getSocChartOption(): echarts.EChartsOption {
|
|
|
top: '50%',
|
|
top: '50%',
|
|
|
textAlign: 'center',
|
|
textAlign: 'center',
|
|
|
style: {
|
|
style: {
|
|
|
- text: `${permitStats.reduce((sum, item) => sum + item.value, 0)}`,
|
|
|
|
|
-
|
|
|
|
|
|
|
+ text: `${permitStats.value.reduce((sum, item) => sum + item.value, 0)}`,
|
|
|
fill: '#114a9b',
|
|
fill: '#114a9b',
|
|
|
fontSize: 30,
|
|
fontSize: 30,
|
|
|
fontWeight: 700,
|
|
fontWeight: 700,
|
|
@@ -641,9 +570,7 @@ function getSocChartOption(): echarts.EChartsOption {
|
|
|
|
|
|
|
|
function initSocChart() {
|
|
function initSocChart() {
|
|
|
if (!socChartRef.value) return
|
|
if (!socChartRef.value) return
|
|
|
- if (socChart) {
|
|
|
|
|
- socChart.dispose()
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ socChart?.dispose()
|
|
|
socChart = echarts.init(socChartRef.value, undefined, {
|
|
socChart = echarts.init(socChartRef.value, undefined, {
|
|
|
renderer: CHART_RENDERER
|
|
renderer: CHART_RENDERER
|
|
|
})
|
|
})
|
|
@@ -655,71 +582,147 @@ function resizeSocChart() {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function destroySocChart() {
|
|
function destroySocChart() {
|
|
|
- if (socChart) {
|
|
|
|
|
- socChart.dispose()
|
|
|
|
|
- socChart = null
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-const getKanban = async () => {
|
|
|
|
|
- const data = await kanbanApi.getKanban()
|
|
|
|
|
- return data
|
|
|
|
|
|
|
+ socChart?.dispose()
|
|
|
|
|
+ socChart = null
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function formatPercent(numerator: number, denominator: number) {
|
|
function formatPercent(numerator: number, denominator: number) {
|
|
|
if (!denominator || Number.isNaN(denominator)) {
|
|
if (!denominator || Number.isNaN(denominator)) {
|
|
|
return '0%'
|
|
return '0%'
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
return `${((numerator / denominator) * 100).toFixed(1)}%`
|
|
return `${((numerator / denominator) * 100).toFixed(1)}%`
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-const summaryPanel = ref<any>(null)
|
|
|
|
|
-const safeDay = ref<SafeDayMap>({})
|
|
|
|
|
-onMounted(async () => {
|
|
|
|
|
- summaryPanel.value = await getKanban()
|
|
|
|
|
-
|
|
|
|
|
- // summaryCards.value[0].value = summaryPanel.value.danger
|
|
|
|
|
- // summaryCards.value[1].value = summaryPanel.value.monthHazard
|
|
|
|
|
- // summaryCards.value[2].value = formatPercent(
|
|
|
|
|
- // summaryPanel.value.totalHazard - summaryPanel.value.todoHazard,
|
|
|
|
|
- // summaryPanel.value.totalHazard
|
|
|
|
|
- // )
|
|
|
|
|
- // summaryCards.value[3].value = summaryPanel.value.ptwCount
|
|
|
|
|
|
|
+async function loadHomeBoard() {
|
|
|
|
|
+ summaryPanel.value = await kanbanApi.getKanban()
|
|
|
|
|
+
|
|
|
summaryCards.value[3].value = formatPercent(
|
|
summaryCards.value[3].value = formatPercent(
|
|
|
summaryPanel.value.totdalCert - summaryPanel.value.expiredCert,
|
|
summaryPanel.value.totdalCert - summaryPanel.value.expiredCert,
|
|
|
summaryPanel.value.totdalCert
|
|
summaryPanel.value.totdalCert
|
|
|
)
|
|
)
|
|
|
|
|
+ summaryCards.value[3].note = `Warn: ${summaryPanel.value.warnCert || 0}`
|
|
|
|
|
|
|
|
- summaryCards.value[3].note = `Warn: ${summaryPanel.value.warnCert}`
|
|
|
|
|
|
|
+ hazardBars.value[0].value = summaryPanel.value.totalHazard || 0
|
|
|
|
|
+ hazardBars.value[1].value =
|
|
|
|
|
+ (summaryPanel.value.totalHazard || 0) - (summaryPanel.value.todoHazard || 0)
|
|
|
|
|
+ hazardBars.value[2].value = summaryPanel.value.todoHazard || 0
|
|
|
|
|
|
|
|
- hazardBars.value[0].value = summaryPanel.value.totalHazard
|
|
|
|
|
- hazardBars.value[1].value = summaryPanel.value.totalHazard - summaryPanel.value.todoHazard
|
|
|
|
|
- hazardBars.value[2].value = summaryPanel.value.todoHazard
|
|
|
|
|
|
|
+ safeDay.value = (await kanbanApi.getSafeDay(userStore.getUser.deptId)) || {}
|
|
|
|
|
|
|
|
- try {
|
|
|
|
|
- safeDay.value = (await kanbanApi.getSafeDay(userStore.getUser.deptId)) || {}
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- console.log(error)
|
|
|
|
|
|
|
+ await Promise.all([getStatic(), getCertStatic(), getInstrumentOverview()])
|
|
|
|
|
+
|
|
|
|
|
+ nextTick(() => {
|
|
|
|
|
+ updateHazardChart()
|
|
|
|
|
+ updateSafeDayChart()
|
|
|
|
|
+ resizeHazardChart()
|
|
|
|
|
+ resizeSafeDayChart()
|
|
|
|
|
+ resizeSocChart()
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const certLoading = ref(false)
|
|
|
|
|
+const certTableData = ref<any[]>([])
|
|
|
|
|
+const certTotal = ref(0)
|
|
|
|
|
+const certQueryParams = reactive({
|
|
|
|
|
+ pageNo: 1,
|
|
|
|
|
+ pageSize: 10,
|
|
|
|
|
+ type: undefined as string | undefined,
|
|
|
|
|
+ classify: undefined as string | undefined,
|
|
|
|
|
+ userName: '',
|
|
|
|
|
+ expired: undefined as string | undefined
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+function formatDateCorrectly(timestamp: any) {
|
|
|
|
|
+ if (!timestamp) return ''
|
|
|
|
|
+ let time = Number(timestamp)
|
|
|
|
|
+ if (time < 10000000000) {
|
|
|
|
|
+ time = time * 1000
|
|
|
}
|
|
}
|
|
|
|
|
+ return formatDate(time).substring(0, 10)
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- try {
|
|
|
|
|
- getStatic()
|
|
|
|
|
- getCertStatic()
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- console.log(error)
|
|
|
|
|
|
|
+function getCertificateTypeText(type: string) {
|
|
|
|
|
+ const map: Record<string, string> = {
|
|
|
|
|
+ personal: '个人证书',
|
|
|
|
|
+ organization: '组织证书',
|
|
|
|
|
+ other: '其他'
|
|
|
}
|
|
}
|
|
|
|
|
+ return map[type] || type
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
|
|
+async function getCertificateBoardList() {
|
|
|
|
|
+ certLoading.value = true
|
|
|
try {
|
|
try {
|
|
|
- await getList()
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- console.log(error)
|
|
|
|
|
|
|
+ const data = await IotMeasureCertApi.getIotMeasureCertPage({
|
|
|
|
|
+ ...certQueryParams,
|
|
|
|
|
+ deptId: userStore.user.deptId,
|
|
|
|
|
+ type: 'organization'
|
|
|
|
|
+ })
|
|
|
|
|
+ certTableData.value = data.list || []
|
|
|
|
|
+ certTotal.value = data.total || 0
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ certLoading.value = false
|
|
|
}
|
|
}
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- nextTick(() => {
|
|
|
|
|
- updateHazardChart()
|
|
|
|
|
- updateSafeDayChart()
|
|
|
|
|
- })
|
|
|
|
|
|
|
+function handleCertificateQuery() {
|
|
|
|
|
+ certQueryParams.pageNo = 1
|
|
|
|
|
+ getCertificateBoardList()
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function resetCertificateQuery() {
|
|
|
|
|
+ certQueryParams.pageNo = 1
|
|
|
|
|
+ certQueryParams.pageSize = 10
|
|
|
|
|
+ certQueryParams.type = undefined
|
|
|
|
|
+ certQueryParams.classify = undefined
|
|
|
|
|
+ certQueryParams.userName = ''
|
|
|
|
|
+ certQueryParams.expired = undefined
|
|
|
|
|
+ getCertificateBoardList()
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+watch(
|
|
|
|
|
+ () => activeSummaryTab.value,
|
|
|
|
|
+ async (value) => {
|
|
|
|
|
+ if (value === 'certificate') {
|
|
|
|
|
+ await getCertificateBoardList()
|
|
|
|
|
+ } else {
|
|
|
|
|
+ nextTick(() => {
|
|
|
|
|
+ resizeHazardChart()
|
|
|
|
|
+ resizeSafeDayChart()
|
|
|
|
|
+ resizeSocChart()
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+)
|
|
|
|
|
+
|
|
|
|
|
+onMounted(async () => {
|
|
|
|
|
+ supportsZoom.value = typeof CSS !== 'undefined' && CSS.supports?.('zoom', '1') === true
|
|
|
|
|
+ nextTick(updateScale)
|
|
|
|
|
+ resizeObserver = new ResizeObserver(updateScale)
|
|
|
|
|
+ if (wrapperRef.value) {
|
|
|
|
|
+ resizeObserver.observe(wrapperRef.value)
|
|
|
|
|
+ }
|
|
|
|
|
+ initHazardChart()
|
|
|
|
|
+ initSafeDayChart()
|
|
|
|
|
+ initSocChart()
|
|
|
|
|
+ window.addEventListener('resize', updateScale)
|
|
|
|
|
+ window.addEventListener('resize', resizeHazardChart)
|
|
|
|
|
+ window.addEventListener('resize', resizeSafeDayChart)
|
|
|
|
|
+ window.addEventListener('resize', resizeSocChart)
|
|
|
|
|
+
|
|
|
|
|
+ await loadHomeBoard()
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+onUnmounted(() => {
|
|
|
|
|
+ resizeObserver?.disconnect()
|
|
|
|
|
+ window.removeEventListener('resize', updateScale)
|
|
|
|
|
+ window.removeEventListener('resize', resizeHazardChart)
|
|
|
|
|
+ window.removeEventListener('resize', resizeSafeDayChart)
|
|
|
|
|
+ window.removeEventListener('resize', resizeSocChart)
|
|
|
|
|
+ cancelAnimationFrame(resizeRaf)
|
|
|
|
|
+ destroyHazardChart()
|
|
|
|
|
+ destroySafeDayChart()
|
|
|
|
|
+ destroySocChart()
|
|
|
})
|
|
})
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
@@ -728,6 +731,7 @@ onMounted(async () => {
|
|
|
<div class="mx-a overflow-hidden" :style="targetWrapperStyle">
|
|
<div class="mx-a overflow-hidden" :style="targetWrapperStyle">
|
|
|
<div id="qhse-kanban" class="bg qhse-board" :style="targetAreaStyle">
|
|
<div id="qhse-kanban" class="bg qhse-board" :style="targetAreaStyle">
|
|
|
<header class="header">{{ pageTitle }}</header>
|
|
<header class="header">{{ pageTitle }}</header>
|
|
|
|
|
+
|
|
|
<div class="summary-toolbar">
|
|
<div class="summary-toolbar">
|
|
|
<div class="summary-toolbar__tabs">
|
|
<div class="summary-toolbar__tabs">
|
|
|
<button
|
|
<button
|
|
@@ -740,7 +744,8 @@ onMounted(async () => {
|
|
|
{{ tab.label }}
|
|
{{ tab.label }}
|
|
|
</button>
|
|
</button>
|
|
|
</div>
|
|
</div>
|
|
|
- <div class="summary-toolbar__date">
|
|
|
|
|
|
|
+
|
|
|
|
|
+ <div v-if="activeSummaryTab === 'home'" class="summary-toolbar__date">
|
|
|
<span class="summary-toolbar__date-label">日期:</span>
|
|
<span class="summary-toolbar__date-label">日期:</span>
|
|
|
<el-date-picker
|
|
<el-date-picker
|
|
|
v-model="summaryDate"
|
|
v-model="summaryDate"
|
|
@@ -752,7 +757,8 @@ onMounted(async () => {
|
|
|
class="summary-toolbar__picker" />
|
|
class="summary-toolbar__picker" />
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
- <div class="board-body">
|
|
|
|
|
|
|
+
|
|
|
|
|
+ <div v-if="activeSummaryTab === 'home'" class="board-body">
|
|
|
<section class="panel summary-panel kb-stage-card kb-stage-card--1">
|
|
<section class="panel summary-panel kb-stage-card kb-stage-card--1">
|
|
|
<div class="panel-title">
|
|
<div class="panel-title">
|
|
|
<span class="icon-decorator"><span></span><span></span></span>
|
|
<span class="icon-decorator"><span></span><span></span></span>
|
|
@@ -780,9 +786,9 @@ onMounted(async () => {
|
|
|
<div class="summary-card__label">{{ card.title }}</div>
|
|
<div class="summary-card__label">{{ card.title }}</div>
|
|
|
<div class="summary-tile__meta">
|
|
<div class="summary-tile__meta">
|
|
|
<span class="summary-tile__value">{{ card.value }}</span>
|
|
<span class="summary-tile__value">{{ card.value }}</span>
|
|
|
- <span class="summary-tile__note" :style="{ color: card.accent }">{{
|
|
|
|
|
- card.note
|
|
|
|
|
- }}</span>
|
|
|
|
|
|
|
+ <span class="summary-tile__note" :style="{ color: card.accent }">
|
|
|
|
|
+ {{ card.note }}
|
|
|
|
|
+ </span>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
</article>
|
|
</article>
|
|
@@ -801,7 +807,6 @@ onMounted(async () => {
|
|
|
<div class="risk-card__title">
|
|
<div class="risk-card__title">
|
|
|
<span class="risk-card__dot" :style="{ background: zone.color }"></span>
|
|
<span class="risk-card__dot" :style="{ background: zone.color }"></span>
|
|
|
<span :style="{ color: zone.color }">{{ zone.title }}</span>
|
|
<span :style="{ color: zone.color }">{{ zone.title }}</span>
|
|
|
- <!-- <span class="risk-card__count">{{ zone.value }}</span> -->
|
|
|
|
|
<CountTo
|
|
<CountTo
|
|
|
:duration="2600"
|
|
:duration="2600"
|
|
|
:end-val="zone.value"
|
|
:end-val="zone.value"
|
|
@@ -813,6 +818,7 @@ onMounted(async () => {
|
|
|
</div>
|
|
</div>
|
|
|
</section>
|
|
</section>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+
|
|
|
<div class="left-column">
|
|
<div class="left-column">
|
|
|
<section class="panel board-panel kb-stage-card kb-stage-card--2">
|
|
<section class="panel board-panel kb-stage-card kb-stage-card--2">
|
|
|
<div class="panel-title">
|
|
<div class="panel-title">
|
|
@@ -863,9 +869,7 @@ onMounted(async () => {
|
|
|
:end-val="item.value"
|
|
:end-val="item.value"
|
|
|
:start-val="0"
|
|
:start-val="0"
|
|
|
:style="{ color: item.accent }" />
|
|
:style="{ color: item.accent }" />
|
|
|
-
|
|
|
|
|
- <span v-if="item.label === '证件过期'" class="pl-2">人</span>
|
|
|
|
|
- <span v-else>人(需复审)</span>
|
|
|
|
|
|
|
+ <span class="pl-2">人</span>
|
|
|
</strong>
|
|
</strong>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
@@ -896,33 +900,133 @@ onMounted(async () => {
|
|
|
<div class="bottom-card__title">{{ card.title }}</div>
|
|
<div class="bottom-card__title">{{ card.title }}</div>
|
|
|
</div>
|
|
</div>
|
|
|
<div class="bottom-card__content">
|
|
<div class="bottom-card__content">
|
|
|
- <template v-if="card.title !== '安全检测'">
|
|
|
|
|
- <p v-for="line in card.lines" :key="line">{{ line }}</p>
|
|
|
|
|
- </template>
|
|
|
|
|
- <template v-else>
|
|
|
|
|
- <p>
|
|
|
|
|
- <span>在用:</span>
|
|
|
|
|
- <CountTo
|
|
|
|
|
- :duration="2600"
|
|
|
|
|
- :end-val="total"
|
|
|
|
|
- :start-val="0"
|
|
|
|
|
- :style="{ color: card.accent }" />
|
|
|
|
|
- <span class="pl-2">台</span>
|
|
|
|
|
- </p>
|
|
|
|
|
- <p>
|
|
|
|
|
- <span>待检:</span>
|
|
|
|
|
- <CountTo
|
|
|
|
|
- :duration="2600"
|
|
|
|
|
- :end-val="instrumentExpired"
|
|
|
|
|
- :start-val="0"
|
|
|
|
|
- :style="{ color: '#ff7a7a' }" />
|
|
|
|
|
- <span class="pl-2">台(重点关注)</span>
|
|
|
|
|
- </p>
|
|
|
|
|
- </template>
|
|
|
|
|
|
|
+ <p v-for="line in card.lines" :key="line">{{ line }}</p>
|
|
|
</div>
|
|
</div>
|
|
|
</article>
|
|
</article>
|
|
|
</section>
|
|
</section>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+
|
|
|
|
|
+ <div v-else class="certificate-board">
|
|
|
|
|
+ <section class="panel certificate-filter-panel">
|
|
|
|
|
+ <div class="certificate-filters">
|
|
|
|
|
+ <!-- <div class="certificate-filter-item">
|
|
|
|
|
+ <span class="certificate-filter-item__label">证书类型</span>
|
|
|
|
|
+ <el-select
|
|
|
|
|
+ v-model="certQueryParams.type"
|
|
|
|
|
+ clearable
|
|
|
|
|
+ placeholder="请选择证书类型"
|
|
|
|
|
+ class="certificate-filter-item__control">
|
|
|
|
|
+ <el-option label="个人证书" value="personal" />
|
|
|
|
|
+ <el-option label="组织证书" value="organization" />
|
|
|
|
|
+ <el-option label="其他" value="other" />
|
|
|
|
|
+ </el-select>
|
|
|
|
|
+ </div> -->
|
|
|
|
|
+
|
|
|
|
|
+ <div class="certificate-filter-item">
|
|
|
|
|
+ <span class="certificate-filter-item__label">证书类别</span>
|
|
|
|
|
+ <el-select
|
|
|
|
|
+ v-model="certQueryParams.classify"
|
|
|
|
|
+ clearable
|
|
|
|
|
+ placeholder="证书类别"
|
|
|
|
|
+ class="certificate-filter-item__control">
|
|
|
|
|
+ <el-option
|
|
|
|
|
+ v-for="dict in getStrDictOptions(DICT_TYPE.PERSON_CERT).concat(
|
|
|
|
|
+ getStrDictOptions(DICT_TYPE.ORG_CERT)
|
|
|
|
|
+ )"
|
|
|
|
|
+ :key="dict.value"
|
|
|
|
|
+ :label="dict.label"
|
|
|
|
|
+ :value="dict.value" />
|
|
|
|
|
+ </el-select>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="certificate-filter-item">
|
|
|
|
|
+ <span class="certificate-filter-item__label">所属人</span>
|
|
|
|
|
+ <el-input
|
|
|
|
|
+ v-model="certQueryParams.userName"
|
|
|
|
|
+ placeholder="输入所属人"
|
|
|
|
|
+ class="certificate-filter-item__control" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="certificate-filter-item">
|
|
|
|
|
+ <span class="certificate-filter-item__label">是否过期</span>
|
|
|
|
|
+ <el-select
|
|
|
|
|
+ v-model="certQueryParams.expired"
|
|
|
|
|
+ clearable
|
|
|
|
|
+ placeholder="请选择是否过期"
|
|
|
|
|
+ class="certificate-filter-item__control">
|
|
|
|
|
+ <el-option
|
|
|
|
|
+ v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
|
|
|
|
|
+ :key="dict.value"
|
|
|
|
|
+ :label="dict.label"
|
|
|
|
|
+ :value="dict.value" />
|
|
|
|
|
+ </el-select>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="certificate-filter-actions">
|
|
|
|
|
+ <el-button type="primary" @click="handleCertificateQuery">查询</el-button>
|
|
|
|
|
+ <el-button @click="resetCertificateQuery">重置</el-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </section>
|
|
|
|
|
+
|
|
|
|
|
+ <section class="panel certificate-table-panel">
|
|
|
|
|
+ <el-table
|
|
|
|
|
+ :loading="certLoading"
|
|
|
|
|
+ :data="certTableData"
|
|
|
|
|
+ height="100%"
|
|
|
|
|
+ class="certificate-table">
|
|
|
|
|
+ <el-table-column label="序号" width="80" align="center">
|
|
|
|
|
+ <template #default="scope">
|
|
|
|
|
+ {{ (certQueryParams.pageNo - 1) * certQueryParams.pageSize + scope.$index + 1 }}
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+
|
|
|
|
|
+ <el-table-column label="证书类型" align="center" min-width="120">
|
|
|
|
|
+ <template #default="scope">
|
|
|
|
|
+ {{ getCertificateTypeText(scope.row.type) }}
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+
|
|
|
|
|
+ <el-table-column label="证书类别" align="center" min-width="140">
|
|
|
|
|
+ <template #default="scope">
|
|
|
|
|
+ <dict-tag
|
|
|
|
|
+ v-if="scope.row.type === 'organization'"
|
|
|
|
|
+ :type="DICT_TYPE.ORG_CERT"
|
|
|
|
|
+ :value="scope.row.classify" />
|
|
|
|
|
+ <dict-tag v-else :type="DICT_TYPE.PERSON_CERT" :value="scope.row.classify" />
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+
|
|
|
|
|
+ <el-table-column label="证书名称" prop="certName" align="center" min-width="160" />
|
|
|
|
|
+ <el-table-column label="所属人" prop="userName" align="center" min-width="100" />
|
|
|
|
|
+ <el-table-column label="所在部门" prop="deptName" align="center" min-width="140" />
|
|
|
|
|
+ <el-table-column label="颁发机构" prop="certOrg" align="center" min-width="220" />
|
|
|
|
|
+ <el-table-column
|
|
|
|
|
+ label="证书标准"
|
|
|
|
|
+ prop="certStandard"
|
|
|
|
|
+ align="center"
|
|
|
|
|
+ min-width="140" />
|
|
|
|
|
+ <el-table-column label="颁发时间" align="center" min-width="120">
|
|
|
|
|
+ <template #default="scope">
|
|
|
|
|
+ {{ formatDateCorrectly(scope.row.certIssue) }}
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="有效期" align="center" min-width="120">
|
|
|
|
|
+ <template #default="scope">
|
|
|
|
|
+ {{ formatDateCorrectly(scope.row.certExpire) }}
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ </el-table>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="certificate-pagination">
|
|
|
|
|
+ <Pagination
|
|
|
|
|
+ :total="certTotal"
|
|
|
|
|
+ v-model:page="certQueryParams.pageNo"
|
|
|
|
|
+ v-model:limit="certQueryParams.pageSize"
|
|
|
|
|
+ @pagination="getCertificateBoardList" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </section>
|
|
|
|
|
+ </div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
@@ -939,18 +1043,11 @@ onMounted(async () => {
|
|
|
padding: 18px 18px 24px;
|
|
padding: 18px 18px 24px;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-.summary-panel {
|
|
|
|
|
- padding-bottom: 22px;
|
|
|
|
|
- padding-left: 10px;
|
|
|
|
|
- padding-right: 10px;
|
|
|
|
|
- height: 210px;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
.summary-toolbar {
|
|
.summary-toolbar {
|
|
|
display: flex;
|
|
display: flex;
|
|
|
align-items: center;
|
|
align-items: center;
|
|
|
justify-content: space-between;
|
|
justify-content: space-between;
|
|
|
- padding: 8px 14px 4px;
|
|
|
|
|
|
|
+ padding: 10px 18px 6px;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.summary-toolbar__tabs {
|
|
.summary-toolbar__tabs {
|
|
@@ -960,12 +1057,11 @@ onMounted(async () => {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.summary-toolbar__tab {
|
|
.summary-toolbar__tab {
|
|
|
- min-width: 112px;
|
|
|
|
|
- height: 38px;
|
|
|
|
|
- padding: 0 20px;
|
|
|
|
|
|
|
+ min-width: 120px;
|
|
|
|
|
+ height: 40px;
|
|
|
|
|
+ padding: 0 22px;
|
|
|
font-family: YouSheBiaoTiHei, sans-serif;
|
|
font-family: YouSheBiaoTiHei, sans-serif;
|
|
|
font-size: 17px;
|
|
font-size: 17px;
|
|
|
- line-height: 1;
|
|
|
|
|
color: #2b76e9;
|
|
color: #2b76e9;
|
|
|
background: linear-gradient(180deg, rgb(255 255 255 / 92%) 0%, rgb(228 239 255 / 90%) 100%);
|
|
background: linear-gradient(180deg, rgb(255 255 255 / 92%) 0%, rgb(228 239 255 / 90%) 100%);
|
|
|
border: 1px solid rgb(126 174 244 / 44%);
|
|
border: 1px solid rgb(126 174 244 / 44%);
|
|
@@ -973,13 +1069,12 @@ onMounted(async () => {
|
|
|
box-shadow:
|
|
box-shadow:
|
|
|
inset 0 1px 0 rgb(255 255 255 / 96%),
|
|
inset 0 1px 0 rgb(255 255 255 / 96%),
|
|
|
0 8px 14px rgb(63 103 171 / 8%);
|
|
0 8px 14px rgb(63 103 171 / 8%);
|
|
|
|
|
+ cursor: pointer;
|
|
|
transition:
|
|
transition:
|
|
|
transform 0.2s ease,
|
|
transform 0.2s ease,
|
|
|
box-shadow 0.2s ease,
|
|
box-shadow 0.2s ease,
|
|
|
background 0.2s ease,
|
|
background 0.2s ease,
|
|
|
color 0.2s ease;
|
|
color 0.2s ease;
|
|
|
-
|
|
|
|
|
- cursor: pointer;
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.summary-toolbar__tab.is-active {
|
|
.summary-toolbar__tab.is-active {
|
|
@@ -1021,15 +1116,9 @@ onMounted(async () => {
|
|
|
0 8px 14px rgb(63 103 171 / 6%);
|
|
0 8px 14px rgb(63 103 171 / 6%);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-.summary-toolbar__picker :deep(.el-input__inner) {
|
|
|
|
|
- font-size: 16px;
|
|
|
|
|
- font-weight: 700;
|
|
|
|
|
- color: #3d5679;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.summary-toolbar__picker :deep(.el-input__prefix),
|
|
|
|
|
-.summary-toolbar__picker :deep(.el-input__suffix) {
|
|
|
|
|
- color: #6c86a8;
|
|
|
|
|
|
|
+.summary-panel {
|
|
|
|
|
+ padding: 0 10px 22px;
|
|
|
|
|
+ height: 210px;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.summary-grid {
|
|
.summary-grid {
|
|
@@ -1088,14 +1177,14 @@ onMounted(async () => {
|
|
|
gap: 24px;
|
|
gap: 24px;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-.center-column {
|
|
|
|
|
- display: block;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
.board-panel {
|
|
.board-panel {
|
|
|
min-height: 258px;
|
|
min-height: 258px;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+.board-panel.kb-stage-card:hover {
|
|
|
|
|
+ transform: none;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
.board-panel--center {
|
|
.board-panel--center {
|
|
|
min-height: 540px;
|
|
min-height: 540px;
|
|
|
}
|
|
}
|
|
@@ -1104,17 +1193,16 @@ onMounted(async () => {
|
|
|
margin-top: 18px;
|
|
margin-top: 18px;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-.chart-panel--bars {
|
|
|
|
|
- height: 176px;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
.chart-panel--echart {
|
|
.chart-panel--echart {
|
|
|
height: 188px;
|
|
height: 188px;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.safe-day-chart-panel {
|
|
.safe-day-chart-panel {
|
|
|
height: 218px;
|
|
height: 218px;
|
|
|
- // margin-top: 18px;
|
|
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.soc-chart-panel {
|
|
|
|
|
+ height: 220px;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.panel-title--center {
|
|
.panel-title--center {
|
|
@@ -1169,11 +1257,6 @@ onMounted(async () => {
|
|
|
line-height: 1.55;
|
|
line-height: 1.55;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-.soc-chart-panel {
|
|
|
|
|
- height: 220px;
|
|
|
|
|
- // margin-top: 10px;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
.qualification-panel {
|
|
.qualification-panel {
|
|
|
display: grid;
|
|
display: grid;
|
|
|
margin-top: 26px;
|
|
margin-top: 26px;
|
|
@@ -1227,7 +1310,7 @@ onMounted(async () => {
|
|
|
|
|
|
|
|
.bottom-card {
|
|
.bottom-card {
|
|
|
min-height: 180px;
|
|
min-height: 180px;
|
|
|
- padding: 15px 22px 0px;
|
|
|
|
|
|
|
+ padding: 15px 22px 0;
|
|
|
overflow: hidden;
|
|
overflow: hidden;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -1262,4 +1345,70 @@ onMounted(async () => {
|
|
|
color: #5d718e;
|
|
color: #5d718e;
|
|
|
line-height: 1.7;
|
|
line-height: 1.7;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+.certificate-board {
|
|
|
|
|
+ padding: 16px 18px 24px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.certificate-filter-panel {
|
|
|
|
|
+ padding: 18px 20px 12px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.certificate-filters {
|
|
|
|
|
+ display: grid;
|
|
|
|
|
+ grid-template-columns: repeat(4, minmax(0, 1fr)) auto;
|
|
|
|
|
+ gap: 18px 20px;
|
|
|
|
|
+ align-items: end;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.certificate-filter-item {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ gap: 14px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.certificate-filter-item__label {
|
|
|
|
|
+ flex-shrink: 0;
|
|
|
|
|
+ font-size: 16px;
|
|
|
|
|
+ font-weight: 700;
|
|
|
|
|
+ color: #4f6583;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.certificate-filter-item__control {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.certificate-filter-item__control :deep(.el-input__wrapper) {
|
|
|
|
|
+ height: 42px !important; //
|
|
|
|
|
+ border-radius: 12px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.certificate-filter-actions {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ gap: 10px;
|
|
|
|
|
+ justify-content: flex-end;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.certificate-table-panel {
|
|
|
|
|
+ margin-top: 18px;
|
|
|
|
|
+ padding: 18px 18px 12px;
|
|
|
|
|
+ height: 760px;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.certificate-table {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.certificate-table :deep(.el-table) {
|
|
|
|
|
+ --el-table-header-bg-color: rgba(248, 251, 255, 0.95);
|
|
|
|
|
+ --el-table-row-hover-bg-color: rgba(79, 141, 255, 0.06);
|
|
|
|
|
+ border-radius: 14px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.certificate-pagination {
|
|
|
|
|
+ padding-top: 14px;
|
|
|
|
|
+}
|
|
|
</style>
|
|
</style>
|