refactor(Charts): 重构报警列表组件配置和数据获取

- 更新配置文件,使用深拷贝初始化配置选项
- 添加默认属性设置,包括位置和尺寸
- 优化模板结构,移除冗余空行
- 修改数据获取 API,添加场景码参数
This commit is contained in:
Free-sss 2025-09-08 15:04:00 +08:00
parent bdeac87abd
commit 417d458775
21 changed files with 134 additions and 1172 deletions

View File

@ -2,6 +2,8 @@ import { PublicConfigClass } from '@/packages/public'
import { CreateComponentType } from '@/packages/index.d' import { CreateComponentType } from '@/packages/index.d'
import { AlarmListHazCConfig } from './index' import { AlarmListHazCConfig } from './index'
import dataJson from './data.json' import dataJson from './data.json'
import { chartInitConfig } from '@/settings/designSetting'
import { cloneDeep } from 'lodash'
export enum FontWeightEnum { export enum FontWeightEnum {
NORMAL = '常规', NORMAL = '常规',
BOLD = '加粗', BOLD = '加粗',
@ -38,20 +40,12 @@ export const option = {
itemHeight: 28, itemHeight: 28,
fontSize: 12, fontSize: 12,
titleText: '近60分钟报警信息', titleText: '近60分钟报警信息',
titleSize: 16,
titleColor: '#eee',
fontWeight: 'normal',
fontStyle: 'italic',
paddingX: 45,
paddingY: -25,
letterSpacing: 0.5,
isShowButton: false
} }
export default class Config extends PublicConfigClass implements CreateComponentType { export default class Config extends PublicConfigClass implements CreateComponentType {
public key = AlarmListHazCConfig.key public key = AlarmListHazCConfig.key
public chartConfig = AlarmListHazCConfig public chartConfig = AlarmListHazCConfig
public option = option public option = cloneDeep(option)
public attr = { ...chartInitConfig, x: 0, y: 0, w: 450, h: 300, zIndex: 1 }
} }

View File

@ -33,18 +33,13 @@
</div> </div>
</PublicSmallBorder> </PublicSmallBorder>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { PropType, computed, ref, onMounted, onUnmounted } from 'vue' import { PropType, computed, ref, onMounted, onUnmounted } from 'vue'
import { option as configOption } from './config' import { option as configOption } from './config'
import SmallBorder from '../SmallBorder/index.vue'
import axiosInstance from '@/api/axios' import axiosInstance from '@/api/axios'
import PublicSmallBorder from '../../Public_SmallBorder/index.vue' import PublicSmallBorder from '../../PublicSmallBorder/index.vue'
const props = defineProps({ const props = defineProps({
chartConfig: { chartConfig: {
type: Object as PropType<{ option: typeof configOption }>, type: Object as PropType<{ option: typeof configOption }>,
@ -73,7 +68,7 @@ const convertTimestampToDateTime = (timestamp: number | string) => {
const fetchRecentAlarms = async () => { const fetchRecentAlarms = async () => {
try { try {
const res: any = await axiosInstance.get( const res: any = await axiosInstance.get(
`/awjt/space/getRecentAlarms`, `/awjt/space/getRecentAlarms/${option.value.sceneCode}`,
{ {
responseType: 'json', responseType: 'json',
baseURL: '' baseURL: ''

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 174 KiB

View File

@ -3,13 +3,12 @@ import { LineDropdownConfig } from './index'
import { CreateComponentType } from '@/packages/index.d' import { CreateComponentType } from '@/packages/index.d'
import cloneDeep from 'lodash/cloneDeep' import cloneDeep from 'lodash/cloneDeep'
import dataJson from './data.json' import dataJson from './data.json'
import { chartInitConfig } from '@/settings/designSetting'
export const includes = ['xAxis', 'yAxis', 'grid'] export const includes = ['xAxis', 'yAxis', 'grid']
// 其它配置 // 其它配置
const otherConfig = { const otherConfig = {
dateTime: { dateTime: {
show: true,
selectValue: 'day', selectValue: 'day',
dataset: [ dataset: [
{ {
@ -144,4 +143,5 @@ export default class Config extends PublicConfigClass implements CreateComponent
public key: string = LineDropdownConfig.key public key: string = LineDropdownConfig.key
public chartConfig = cloneDeep(LineDropdownConfig) public chartConfig = cloneDeep(LineDropdownConfig)
public option = echartOptionProfixHandle(option, includes) public option = echartOptionProfixHandle(option, includes)
public attr = { ...chartInitConfig, x: 0, y: 0, w: 450, h: 300, zIndex: 1 }
} }

View File

@ -35,7 +35,7 @@ import config, { includes } from './config'
import { DatasetComponent, GridComponent, TooltipComponent } from 'echarts/components' import { DatasetComponent, GridComponent, TooltipComponent } from 'echarts/components'
import CustomSelect from './select.vue' import CustomSelect from './select.vue'
import axiosInstance from '@/api/axios' import axiosInstance from '@/api/axios'
import PublicSmallBorder from '../../Public_SmallBorder/index.vue' import PublicSmallBorder from '../../PublicSmallBorder/index.vue'
const props = defineProps({ const props = defineProps({
themeSetting: { themeSetting: {

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 174 KiB

View File

@ -4,6 +4,7 @@ import { CreateComponentType } from '@/packages/index.d'
import cloneDeep from 'lodash/cloneDeep' import cloneDeep from 'lodash/cloneDeep'
import { chartInitConfig } from '@/settings/designSetting' import { chartInitConfig } from '@/settings/designSetting'
import dataJson from './data.json' import dataJson from './data.json'
export interface DataSourceItem { export interface DataSourceItem {
dataname: string; dataname: string;
values: number[]; values: number[];
@ -17,7 +18,9 @@ export interface DatasType {
dataSource: DataSourceItem[]; dataSource: DataSourceItem[];
} }
const otherOption = {
titleText: '报警处置情况'
}
export const includes = ['legend', 'xAxis', 'yAxis', 'grid'] export const includes = ['legend', 'xAxis', 'yAxis', 'grid']
export const seriesItem = { export const seriesItem = {
type: 'line', type: 'line',
@ -57,31 +60,32 @@ export const seriesItem = {
} }
} }
export const option = { export const option = {
...otherOption,
sceneCode: 'T04', sceneCode: 'T04',
dateTime: { dateTime: {
selectValue: 'day', selectValue: 'day',
dataset: [ dataset: [
{ {
label: '当天', label: '当天',
value: 'day' value: 'day'
}, },
{ {
label: '本周', label: '本周',
value: 'week' value: 'week'
}, },
{ {
label: '当月', label: '当月',
value: 'month' value: 'month'
}, },
{ {
label: '本季度', label: '本季度',
value: 'quarter' value: 'quarter'
}, },
{ {
label: '当年', label: '当年',
value: 'year' value: 'year'
} }
] ]
}, },
dataset: { dataset: {

View File

@ -1,38 +1,38 @@
<template> <template>
<div class="go-border-box"> <div class="go-border-box">
<img src="./assets/title.svg" class="svg" />
<div class="buttonContent">
<span class="title">报警处置情况</span>
</div>
<!-- 使用新的下拉选择器组件 --> <!-- 使用新的下拉选择器组件 -->
<CustomSelect :options="option.dateTime.dataset" :selectedValue="option.dateTime.selectValue" <!-- <CustomSelect :options="option.dateTime.dataset" :selectedValue="option.dateTime.selectValue"
@change="handleSelectChange" /> @change="handleSelectChange" /> -->
<PublicSmallBorder :title-text="option.titleText" :select-option="option.dateTime" @change="handleSelectChange">
<div class="content">
<div class="textContent">
<div class="textInContent">
<span class="smallText">报警总数 </span>
<span class="bigText">{{ currentData.alertTotal?.toLocaleString('en-US') || '0' }}</span>
</div>
<div class="textInContent">
<span class="smallText">未处置报警数</span>
<span class="bigText">{{ currentData.unprocessedAlert?.toLocaleString('en-US') || '0' }}</span>
</div>
<div class="textInContent">
<span class="smallText">平均处置时长</span>
<span class="bigText">{{ currentData.averageResolutionTime?.toLocaleString('en-US') || '0' }}</span>
</div>
</div>
<div class="chartsContent">
<span class="smallText Tips">
<img class="icon" src="./icon01.png" alt="">
数据统计图表</span>
<v-chart ref="vChartRef" :init-options="initOptions" :theme="themeColor" :option="chartOption"
:update-options="{
replaceMerge: replaceMergeArr
}" autoresize>
</v-chart>
</div>
</div>
</PublicSmallBorder>
<div class="textContent">
<div class="textInContent">
<span class="smallText">报警总数 </span>
<span class="bigText">{{ currentData.alertTotal?.toLocaleString('en-US') || '0' }}</span>
</div>
<div class="textInContent">
<span class="smallText">未处置报警数</span>
<span class="bigText">{{ currentData.unprocessedAlert?.toLocaleString('en-US') || '0' }}</span>
</div>
<div class="textInContent">
<span class="smallText">平均处置时长</span>
<span class="bigText">{{ currentData.averageResolutionTime?.toLocaleString('en-US') || '0' }}</span>
</div>
</div>
<div class="chartsContent">
<span class="smallText Tips">
<img class="icon" src="./icon01.png" alt="">
数据统计图表</span>
<v-chart ref="vChartRef" :init-options="initOptions" :theme="themeColor" :option="chartOption" :update-options="{
replaceMerge: replaceMergeArr
}" autoresize>
</v-chart>
</div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@ -50,7 +50,7 @@ import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } fr
import isObject from 'lodash/isObject' import isObject from 'lodash/isObject'
import CustomSelect from './select.vue' import CustomSelect from './select.vue'
import axiosInstance from '@/api/axios' import axiosInstance from '@/api/axios'
import PublicSmallBorder from '../../PublicSmallBorder/index.vue'
const props = defineProps({ const props = defineProps({
themeSetting: { themeSetting: {
type: Object, type: Object,
@ -82,7 +82,7 @@ const selectedTimeRange = ref('day')
// API // API
const fetchChartData = async (option: string) => { const fetchChartData = async (option: string) => {
try { try {
const response:any = await axiosInstance.get(`/awjt/screen/handleByOption/${option}/${props.chartConfig.option.sceneCode}`,{baseURL:''}) const response: any = await axiosInstance.get(`/awjt/screen/handleByOption/${option}/${props.chartConfig.option.sceneCode}`, { baseURL: '' })
if (response.state === true) { if (response.state === true) {
return response.value || [] return response.value || []
} else { } else {
@ -251,41 +251,13 @@ onMounted(() => {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@include go(border-box) { @include go(border-box) {
position: relative;
border-radius: 5px;
overflow: hidden;
display: flex;
flex-direction: column;
align-items: center;
width: 100%; width: 100%;
height: 100%; height: 100%;
padding: 0;
//
// background-color: #0E121B;
//
background: linear-gradient(to top,
rgba(14, 18, 27, 1) 0%,
rgba(14, 18, 27, 0.6) 100%);
&::before { .content {
content: ''; width: 100%;
position: absolute; height: 100%;
top: 0; position: relative;
left: 0;
right: 0;
bottom: 0;
border-radius: 10px;
padding: 2px;
/* 边框宽度 */
background: linear-gradient(to top,
rgba(128, 128, 128, 0.3),
rgba(128, 128, 128, 0));
-webkit-mask:
linear-gradient(#fff, #fff) content-box,
linear-gradient(#fff, #fff);
-webkit-mask-composite: xor;
mask-composite: exclude;
pointer-events: none;
} }
} }

View File

@ -1,159 +0,0 @@
<template>
<div class="custom-select" @click="toggleDropdown">
<div class="select-display">
<span class="select-text">{{ getSelectedLabel() }}</span>
<span class="select-arrow" :class="{ 'arrow-up': isDropdownOpen }"></span>
</div>
<div class="select-dropdown" v-show="isDropdownOpen">
<div
v-for="item in options"
:key="item.value"
class="select-option"
:class="{ 'selected': item.value === selectedValue }"
@click.stop="selectOption(item)"
>
{{ item.label }}
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
// props
const props = defineProps<{
options: Array<{ label: string; value: any }>
selectedValue: any
}>()
// emits
const emit = defineEmits<{
change: [value: any]
}>()
//
const isDropdownOpen = ref(false)
//
const toggleDropdown = (event: Event) => {
event.stopPropagation()
isDropdownOpen.value = !isDropdownOpen.value
}
//
const selectOption = (item: any) => {
emit('change', item.value)
isDropdownOpen.value = false
}
//
const getSelectedLabel = () => {
const selectedItem = props.options.find(
(item: any) => item.value === props.selectedValue
)
return selectedItem ? selectedItem.label : '请选择'
}
//
const handleClickOutside = (event: Event) => {
const target = event.target as HTMLElement
if (!target.closest('.custom-select')) {
isDropdownOpen.value = false
}
}
//
onMounted(() => {
document.addEventListener('click', handleClickOutside)
})
//
onUnmounted(() => {
document.removeEventListener('click', handleClickOutside)
})
</script>
<style lang="scss" scoped>
.custom-select {
position: absolute;
top: 12px;
right: 14px;
font-size: 12px;
z-index: 1000;
}
.select-display {
display: flex;
align-items: center;
justify-content: space-between;
height: 22px;
padding: 0 10px;
background-color: #086C67;
color: #fff;
border-radius: 10px;
cursor: pointer;
transition: all 0.3s ease;
}
.select-text {
flex: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.select-arrow {
margin-left: 8px;
font-size: 10px;
transition: transform 0.3s ease;
&.arrow-up {
transform: rotate(180deg);
}
}
.select-dropdown {
position: absolute;
top: 100%;
left: 0;
right: 0;
background-color: #086C67;
border-radius: 6px;
margin-top: 2px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
overflow: hidden;
animation: slideDown 0.2s ease;
}
.select-option {
padding: 10px 12px;
color: #fff;
cursor: pointer;
transition: background-color 0.2s ease;
&:hover {
background-color: rgba(255, 255, 255, 0.1);
}
&.selected {
background-color: rgba(255, 255, 255, 0.2);
font-weight: bold;
}
&:not(:last-child) {
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
}
@keyframes slideDown {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
</style>

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 174 KiB

View File

@ -3,12 +3,13 @@ import { PieCenterConfig } from './index'
import { CreateComponentType } from '@/packages/index.d' import { CreateComponentType } from '@/packages/index.d'
import cloneDeep from 'lodash/cloneDeep' import cloneDeep from 'lodash/cloneDeep'
import dataJson from './data.json' import dataJson from './data.json'
import { chartInitConfig } from '@/settings/designSetting'
export const includes = ['legend'] export const includes = ['legend']
// 其它配置 // 其它配置
const otherConfig = { const otherConfig = {
sceneCode:'T04', titleText: "报警统计",
sceneCode: 'T04',
dateTime: { dateTime: {
selectValue: 'day', selectValue: 'day',
dataset: [ dataset: [
@ -236,4 +237,5 @@ export default class Config extends PublicConfigClass implements CreateComponent
public key: string = PieCenterConfig.key public key: string = PieCenterConfig.key
public chartConfig = cloneDeep(PieCenterConfig) public chartConfig = cloneDeep(PieCenterConfig)
public option = echartOptionProfixHandle(option, includes) public option = echartOptionProfixHandle(option, includes)
public attr = { ...chartInitConfig, x: 0, y: 0, w: 450, h: 300, zIndex: 1 }
} }

View File

@ -1,11 +1,11 @@
<template> <template>
<div class="go-border-box"> <div class="go-border-box">
<img src="./assets/title.svg" class="svg" /> <PublicSmallBorder :title-text="option.titleText" :select-option="option.dateTime" @change="handleSelectChange">
<div class="header-title">报警统计</div>
<v-chart ref="vChartRef" autoresize :init-options="initOptions" :theme="themeColor" :option="option"></v-chart> <!-- <div class="content"> -->
<!-- 使用新的下拉选择器组件 --> <v-chart ref="vChartRef" autoresize :init-options="initOptions" :theme="themeColor"
<CustomSelect :options="option.dateTime.dataset" :selectedValue="option.dateTime.selectValue" :option="option"></v-chart>
@change="handleSelectChange" /> </PublicSmallBorder>
</div> </div>
</template> </template>
@ -25,6 +25,7 @@ import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent, Gra
import CustomSelect from './select.vue' import CustomSelect from './select.vue'
import dataJson from './data.json' import dataJson from './data.json'
import axiosInstance from '@/api/axios' import axiosInstance from '@/api/axios'
import PublicSmallBorder from '../../PublicSmallBorder/index.vue'
const props = defineProps({ const props = defineProps({
themeSetting: { themeSetting: {
@ -285,64 +286,4 @@ const handleSelectChange = async (value: string) => {
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped></style>
@include go(border-box) {
position: relative;
border-radius: 5px;
overflow: hidden;
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
height: 100%;
padding: 0;
//
// background-color: #0E121B;
//
background: linear-gradient(to top,
rgba(14, 18, 27, 1) 0%,
rgba(14, 18, 27, 0.6) 100%);
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: 5px;
padding: 2px;
/* 边框宽度 */
background: linear-gradient(to top,
rgba(128, 128, 128, 0.3),
rgba(128, 128, 128, 0));
-webkit-mask:
linear-gradient(#fff, #fff) content-box,
linear-gradient(#fff, #fff);
-webkit-mask-composite: xor;
mask-composite: exclude;
pointer-events: none;
}
}
.header-title {
position: absolute;
top: 0;
height: 45px;
line-height: 45px;
left: 80px;
white-space: nowrap;
font-family: 'CustomFont';
font-style: italic;
letter-spacing: 0.5px;
color: #eee;
text-shadow: 1px 3px 10px #000000;
font-size: 16px;
}
.svg {
width: 100%;
height: 45px;
}
</style>

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 174 KiB

View File

@ -1,17 +0,0 @@
import { PublicConfigClass } from '@/packages/public'
import { CreateComponentType } from '@/packages/index.d'
import { SmallBorderConfig } from './index'
import cloneDeep from 'lodash/cloneDeep'
export const option = {
colors: ['#1089ff', '#0000ff'],
backgroundColor: '#00000000'
}
export default class Config extends PublicConfigClass implements CreateComponentType {
public key = SmallBorderConfig.key
public chartConfig = cloneDeep(SmallBorderConfig)
public option = cloneDeep(option)
}

View File

@ -1,54 +0,0 @@
<template>
<CollapseItem name="边框" :expanded="true">
<SettingItemBox
:name="`颜色-${index + 1}`"
v-for="(item, index) in optionData.colors"
:key="index"
>
<SettingItem name="颜色">
<n-color-picker
size="small"
:modes="['hex']"
v-model:value="optionData.colors[index]"
></n-color-picker>
</SettingItem>
<SettingItem>
<n-button
size="small"
@click="optionData.colors[index] = option.colors[index]"
>
恢复默认
</n-button>
</SettingItem>
</SettingItemBox>
</CollapseItem>
<CollapseItem name="背景" :expanded="true">
<SettingItemBox name="颜色">
<SettingItem>
<n-color-picker
size="small"
:modes="['hex']"
v-model:value="optionData.backgroundColor"
></n-color-picker>
</SettingItem>
</SettingItemBox>
</CollapseItem>
</template>
<script setup lang="ts">
import { PropType } from 'vue'
import {
CollapseItem,
SettingItemBox,
SettingItem
} from '@/components/Pages/ChartItemSetting'
import { option } from './config'
const props = defineProps({
optionData: {
type: Object as PropType<typeof option>,
required: true
}
})
</script>

View File

@ -1,17 +0,0 @@
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
// import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
// 曲线图
export const SmallBorderConfig: ConfigType = {
key: 'SmallBorder',
chartKey: 'VSmallBorder',
conKey: 'VCSmallBorder',
title: '带标题小边框',
category: 'MyComponents',
categoryName: '自定义组件',
package: 'Charts',
chartFrame: ChartFrameEnum.COMMON,
image: "SmallBorder.png",
}
// 默认导出配置对象
export default SmallBorderConfig

View File

@ -1,83 +0,0 @@
<template>
<div class="go-small-border">
<div class="border-content">
<div class="svg-content">
<img src="./assets/title.svg" class="svg" />
</div>
<div class="content">
<slot></slot>
</div>
</div>
</div>
</template>
<script lang="ts">export default { name: "SmallBorder" }</script>
<style lang="scss" scoped>
$border-radius: 10px;
$border-width: 2px;
$bg-color-start: rgba(14, 18, 27, 1);
$bg-color-end: rgba(14, 18, 27, 0.6);
$border-gradient-start: rgba(128, 128, 128, 0.3);
$border-gradient-end: rgba(128, 128, 128, 0);
@include go(small-border) {
position: relative;
width: 100%;
height: 100%;
padding: 0;
display: flex;
flex-direction: column;
align-items: center;
& .border-content {
width: 100%;
height: 100%;
padding: 0;
border-radius: $border-radius;
overflow: hidden;
display: flex;
flex-direction: column;
align-items: center;
background: linear-gradient(to top, $bg-color-start, $bg-color-end);
&::before {
content: '';
position: absolute;
inset: 0;
border-radius: $border-radius;
padding: $border-width;
background: linear-gradient(to top, $border-gradient-start, $border-gradient-end);
//
-webkit-mask:
linear-gradient(#fff, #fff) content-box,
linear-gradient(#fff, #fff);
-webkit-mask-composite: xor;
mask:
linear-gradient(#fff, #fff) content-box,
linear-gradient(#fff, #fff);
mask-composite: exclude;
pointer-events: none; // 穿
}
}
& .svg-content {
// z-index: 2;
width: 100%;
height: 12%;
.svg {
width: 100%;
}
// background-color: antiquewhite;
& .svg {
width: 100%;
}
}
}
</style>

View File

@ -3,8 +3,9 @@ import { CreateComponentType } from '@/packages/index.d'
import { TopAlarmsConfig } from './index' import { TopAlarmsConfig } from './index'
import dataJson from './data.json' import dataJson from './data.json'
import { cloneDeep } from 'lodash' import { cloneDeep } from 'lodash'
import { chartInitConfig } from '@/settings/designSetting'
export const option = { export const option = {
sceneCode: 'T04', sceneCode: 'T05',
componentIndexKey: "a", componentIndexKey: "a",
dateTime: { dateTime: {
selectValue: 'day', selectValue: 'day',
@ -34,24 +35,16 @@ export const option = {
dataset: dataJson.source, dataset: dataJson.source,
titleText: '未处置报警数TOP5', titleText: '未处置报警数TOP5',
titleColor: '#eee',
titleSize: 16,
rankColor: '#5AA1AD', rankColor: '#5AA1AD',
nameColor: '#eeeeee', nameColor: '#eeeeee',
valueColor: '#eeeeee', valueColor: '#eeeeee',
barColorStart: '#2f72b5', barColorStart: '#2f72b5',
barColorEnd: '#99C6E6', barColorEnd: '#99C6E6',
dropdownOptions: ['当日', '当月', '当年'],
dropdownDefault: '当日',
iconColor: '#00E5FF',
letterSpacing: 0.5,
paddingX: 45,
paddingY: -5,
isShowButton: false isShowButton: false
} }
export default class Config extends PublicConfigClass implements CreateComponentType { export default class Config extends PublicConfigClass implements CreateComponentType {
public key = TopAlarmsConfig.key public key = TopAlarmsConfig.key
public chartConfig = TopAlarmsConfig public chartConfig = TopAlarmsConfig
public option = cloneDeep(option) public option = cloneDeep(option)
public attr = { ...chartInitConfig, x: 0, y: 0, w: 450, h: 300, zIndex: 1 }
} }

View File

@ -1,40 +1,8 @@
<template> <template>
<SmallBorder class="SmallBorder"> <div class="go-top-alarms">
<div class="go-top-alarms"> <!-- <CustomSelect :options="option.dateTime.dataset" :selectedValue="option.dateTime.selectValue"
<CustomSelect :options="option.dateTime.dataset" :selectedValue="option.dateTime.selectValue" @change="handleSelectChange" class="top-select" /> -->
@change="handleSelectChange" class="top-select" /> <PublicSmallBorder :title-text="option.titleText" :select-option="option.dateTime" @change="handleSelectChange">
<div class="header">
<div class="title">
<div class="title-text">
<span :style="{
color: option.titleColor,
fontSize: option.titleSize + 'px',
marginTop: option.paddingY + 'px',
marginLeft: option.paddingX + 'px',
letterSpacing: option.letterSpacing + 'px'
}">{{ option.titleText }}</span>
</div>
</div>
<n-dropdown v-if='option.isShowButton' trigger="hover" :options="dropdownOptions" @select="handleSelect">
<div class="dropdown-button">
{{ selectedOption }}
<div class="arrow-down-icon">
<svg viewBox="0 0 1024 1024" width="14" height="14">
<path
d="M512 768c-6.3 0-12.6-2.4-17.4-7.3L285.3 551.4c-9.8-9.8-9.8-25.6 0-35.4s25.6-9.8 35.4 0L512 707.3l191.3-191.3c9.8-9.8 25.6-9.8 35.4 0s9.8 25.6 0 35.4L529.4 760.7c-4.8 4.9-11.1 7.3-17.4 7.3z"
fill="currentColor"></path>
</svg>
</div>
</div>
</n-dropdown>
<!-- <n-dropdown v-if='option.isShowButton' trigger="hover" :options="dropdownOptions" @select="handleSelect">
<div class="dropdown-button">
{{ selectedOption }}
<svg-icon icon-class="arrow-down" class="arrow-down-icon" />
</div>
</n-dropdown> -->
</div>
<div class="content"> <div class="content">
<ul> <ul>
<li v-for="(item, index) in displayData" :key="index" class="alarm-item"> <li v-for="(item, index) in displayData" :key="index" class="alarm-item">
@ -59,8 +27,8 @@
</li> </li>
</ul> </ul>
</div> </div>
</div> </PublicSmallBorder>
</SmallBorder> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@ -71,6 +39,7 @@ import CustomSelect from './select.vue'
import axiosInstance from '@/api/axios' import axiosInstance from '@/api/axios'
import { TopAlarmsConfig } from './index' import { TopAlarmsConfig } from './index'
import axios from 'axios' import axios from 'axios'
import PublicSmallBorder from '../../PublicSmallBorder/index.vue'
const props = defineProps({ const props = defineProps({
chartConfig: { chartConfig: {
type: Object as PropType<{ option: typeof configOption }>, type: Object as PropType<{ option: typeof configOption }>,
@ -79,18 +48,10 @@ const props = defineProps({
}) })
const option = computed(() => props.chartConfig.option) const option = computed(() => props.chartConfig.option)
const selectedOption = ref(props.chartConfig.option.dropdownDefault)
// API // API
const displayData: any = ref([]) const displayData: any = ref([])
const dropdownOptions = computed(() => {
return props.chartConfig.option.dropdownOptions.map(opt => ({
label: opt,
key: opt
}))
})
// API // API
const calculateWidth = (value: number) => { const calculateWidth = (value: number) => {
if (displayData.value.length === 0 || displayData.value[0].value === 0) { if (displayData.value.length === 0 || displayData.value[0].value === 0) {
@ -157,9 +118,6 @@ const fetchCorpsData = async (option: string) => {
} }
} }
const handleSelect = (key: string) => {
selectedOption.value = key
}
// API // API
const handleSelectChange = async (value: any) => { const handleSelectChange = async (value: any) => {
@ -191,26 +149,19 @@ onMounted(async () => {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.SmallBorder {
position: relative;
}
.go-top-alarms { .go-top-alarms {
position: absolute;
top: 0;
right: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
margin-top: -10px;
// background-color: #0a162b;
padding: 15px;
box-sizing: border-box;
display: flex;
flex-direction: column;
color: #fff;
.top-select { .content {
top: 20px; width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
z-index: 10;
// background-color: #00e5ff;
} }
.header { .header {
@ -260,16 +211,12 @@ onMounted(async () => {
} }
.content { .content {
flex: 1;
margin-top: -15px;
padding-right: 10px;
font-size: 12.5px;
ul { ul {
list-style: none; list-style: none;
padding: 0; padding: 0;
margin: 0; margin: 0;
height: 100%; height: 90%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: space-around; justify-content: space-around;

View File

@ -2,8 +2,9 @@ import { PublicConfigClass } from '@/packages/public'
import { CreateComponentType } from '@/packages/index.d' import { CreateComponentType } from '@/packages/index.d'
import { yushiVideoConfig } from './index' import { yushiVideoConfig } from './index'
import cloneDeep from 'lodash/cloneDeep' import cloneDeep from 'lodash/cloneDeep'
import { chartInitConfig } from '@/settings/designSetting'
export const option = { export const option = {
titleText: '实时视频',
sceneCode: 'T04', sceneCode: 'T04',
// 摄像头id // 摄像头id
dataset: { dataset: {
@ -33,4 +34,5 @@ export default class Config extends PublicConfigClass implements CreateComponent
public key = yushiVideoConfig.key public key = yushiVideoConfig.key
public chartConfig = cloneDeep(yushiVideoConfig) public chartConfig = cloneDeep(yushiVideoConfig)
public option = cloneDeep(option) public option = cloneDeep(option)
public attr = { ...chartInitConfig, x: 0, y: 0, w: 450, h: 300, zIndex: 1 }
} }

View File

@ -1,30 +1,32 @@
<!-- eslint-disable vue/multi-word-component-names --> <!-- eslint-disable vue/multi-word-component-names -->
<template> <template>
<div class="go-border-box"> <div class="go-border-box">
<img src="./assets/title.svg" class="svg" /> <PublicSmallBorder :title-text="option.titleText">
<div class="header-title">实时视频</div> <div :class="option.isOldStyle ? 'video_title' : 'video_title video_title_new'" v-if="option.showBtn">
<div :class="option.isOldStyle ? 'video_title' : 'video_title video_title_new'" v-if="option.showBtn"> <div class="title_text" v-if="option.showTree && option.showBtn">{{ option.videoTitle }}</div>
<div class="title_text" v-if="option.showTree && option.showBtn">{{ option.videoTitle }}</div> <n-select v-if="!option.showTree" class="video_select" placement="top-end"
<n-select v-if="!option.showTree" class="video_select" placement="top-end" v-model:value="option.selectedDataSource" :options="option.dataSource" :style="`width:${w / 2}px;`"
v-model:value="option.selectedDataSource" :options="option.dataSource" :style="`width:${w / 2}px;`" @update:value="handleSelectDataSource" />
@update:value="handleSelectDataSource" /> <n-button tertiary v-else-if="option.showTree && option.showBtn && option.isOldStyle"
<n-button tertiary v-else-if="option.showTree && option.showBtn && option.isOldStyle" :class="option.isOldStyle ? 'videoChangBtn' : 'videoChangBtn videoChangBtn_new'"
:class="option.isOldStyle ? 'videoChangBtn' : 'videoChangBtn videoChangBtn_new'" @click="handleClick">切换</n-button>
@click="handleClick">切换</n-button> <n-button tertiary v-else-if="option.showTree && option.showBtn && !option.isOldStyle"
<n-button tertiary v-else-if="option.showTree && option.showBtn && !option.isOldStyle" :class="option.isOldStyle ? 'videoChangBtn' : 'videoChangBtn videoChangBtn_new'"
:class="option.isOldStyle ? 'videoChangBtn' : 'videoChangBtn videoChangBtn_new'" @click="handleClick"></n-button>
@click="handleClick"></n-button>
<n-modal v-model:show="showDialog" :mask-closable="false" preset="card" title="选择摄像头"
:class="['custom-tab-modal']" :draggable="{ bounds: 'none' }" :style="{ width: '644px', height: '420px' }">
<n-tree-select ref="cameraTree" class="cameraTree" :menu-props="{
class: 'custom-dropdown'
}" v-model:value="option.selectedDataSource" :options="option.dataset.list" clearable
:default-expanded-keys="option.expandedKeys" style="width: 615px; margin-top: 16px" :show="isDropdownOpen"
@update:show="handleShowChange" @update:value="handleSelectDataSource" />
</n-modal>
</div>
<div ref="vYushiVideoRef" class="go-video" :id="uuid"></div>
</PublicSmallBorder>
<n-modal v-model:show="showDialog" :mask-closable="false" preset="card" title="选择摄像头"
:class="['custom-tab-modal']" :draggable="{ bounds: 'none' }" :style="{ width: '644px', height: '420px' }">
<n-tree-select ref="cameraTree" class="cameraTree" :menu-props="{
class: 'custom-dropdown'
}" v-model:value="option.selectedDataSource" :options="option.dataset.list" clearable
:default-expanded-keys="option.expandedKeys" style="width: 615px; margin-top: 16px" :show="isDropdownOpen"
@update:show="handleShowChange" @update:value="handleSelectDataSource" />
</n-modal>
</div>
<div ref="vYushiVideoRef" class="go-video" :id="uuid"></div>
</div> </div>
</template> </template>
@ -41,7 +43,7 @@ import { PageEnum } from '@/enums/pageEnum'
import axios from 'axios' import axios from 'axios'
import { getUUID, isPreview } from '@/utils' import { getUUID, isPreview } from '@/utils'
import { useYushiVideoStore } from '@/store/modules/yushiVideoStore/yushiVideoStore' import { useYushiVideoStore } from '@/store/modules/yushiVideoStore/yushiVideoStore'
import PublicSmallBorder from '../../PublicSmallBorder/index.vue'
const yushiStore = useYushiVideoStore() const yushiStore = useYushiVideoStore()
let selectedList = [] let selectedList = []
@ -704,63 +706,3 @@ const { vChartRef } = useChartDataFetch(props.chartConfig, useChartEditStore, (n
transform: translateX(7px) translateY(104px) !important; transform: translateX(7px) translateY(104px) !important;
} }
</style> </style>
<style lang="scss" scoped>
@include go(border-box) {
position: relative;
border-radius: 5px;
overflow: hidden;
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
height: 100%;
padding: 0;
//
// background-color: #0E121B;
//
background: linear-gradient(to top,
rgba(14, 18, 27, 1) 0%,
rgba(14, 18, 27, 0.6) 100%);
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: 5px;
padding: 2px;
/* 边框宽度 */
background: linear-gradient(to top,
rgba(128, 128, 128, 0.3),
rgba(128, 128, 128, 0));
-webkit-mask:
linear-gradient(#fff, #fff) content-box,
linear-gradient(#fff, #fff);
-webkit-mask-composite: xor;
mask-composite: exclude;
pointer-events: none;
}
}
.header-title {
position: absolute;
top: 3px;
height: 45px;
line-height: 45px;
left: 80px;
white-space: nowrap;
font-family: 'CustomFont';
font-style: italic;
letter-spacing: 0.5px;
color: #eee;
text-shadow: 1px 3px 10px #000000;
font-size: 16px;
}
.svg {
width: 100%;
height: 45px;
}
</style>