Commit 93a40494b8a59da3eef5b2dcc6909a0e915a687b

Authored by ww
1 parent 609fffbb

perf: 移除vue3-seamless-scroll插件

... ... @@ -35,8 +35,7 @@
35 35 "sortablejs": "^1.15.0",
36 36 "video.js": "^7.20.3",
37 37 "videojs-flvjs-es6": "^1.0.1",
38   - "vue": "^3.3.4",
39   - "vue3-seamless-scroll": "^2.0.1"
  38 + "vue": "^3.3.4"
40 39 },
41 40 "devDependencies": {
42 41 "@iconify/vue": "^4.1.1",
... ...
... ... @@ -68,9 +68,6 @@ dependencies:
68 68 vue:
69 69 specifier: ^3.3.4
70 70 version: 3.3.4
71   - vue3-seamless-scroll:
72   - specifier: ^2.0.1
73   - version: 2.0.1
74 71
75 72 devDependencies:
76 73 '@iconify/vue':
... ... @@ -6412,12 +6409,6 @@ packages:
6412 6409 vue: 3.3.4
6413 6410 dev: false
6414 6411
6415   - /vue3-seamless-scroll@2.0.1:
6416   - resolution: {integrity: sha512-mI3BaDU3pjcPUhVSw3/xNKdfPBDABTi/OdZaZqKysx4cSdNfGRbVvGNDzzptBbJ5S7imv5T55l6x/SqgnxKreg==}
6417   - dependencies:
6418   - throttle-debounce: 5.0.0
6419   - dev: false
6420   -
6421 6412 /vue@3.3.4:
6422 6413 resolution: {integrity: sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw==}
6423 6414 dependencies:
... ...
  1 +import type { AlarmStatusEnum } from '@/enums/datasource'
  2 +
1 3 /**
2 4 * 告警列表
3 5 */
... ... @@ -28,7 +30,7 @@ export interface AlarmListItemType {
28 30 deviceName: string
29 31 type: string
30 32 severity: string
31   - status: string
  33 + status: AlarmStatusEnum
32 34 startTs: string
33 35 endTs: string
34 36 ackTs: string
... ...
  1 +import type { CSSProperties } from 'vue'
  2 +import type { RenderComponentProps } from '../types'
  3 +import { NodeUtils } from '@/hooks/business/useNodeUtils'
  4 +import { EnableEnum, GradientDirectionEnum, type MxShapeStyleType } from '@/fitCore/types'
  5 +
  6 +const gradientDirectionMap = {
  7 + [GradientDirectionEnum.NORTH]: 'to top',
  8 + [GradientDirectionEnum.EAST]: 'to right',
  9 + [GradientDirectionEnum.SOUTH]: 'to bottom',
  10 + [GradientDirectionEnum.WEST]: 'to left',
  11 +}
  12 +
  13 +export interface UseComponentStyleReturnType {
  14 + style: CSSProperties
  15 + textAalign?: string
  16 + borderColor?: string
  17 + borderWidth?: number
  18 + borderStyle?: string
  19 + backgroundColor?: string
  20 + fontFamily?: string
  21 + color?: string
  22 + fontSize?: number
  23 + gradientBackgroundColor?: string
  24 + gradientDirection?: GradientDirectionEnum
  25 + opacity?: number
  26 +}
  27 +
  28 +export function useComponentStyle(props: RenderComponentProps): UseComponentStyleReturnType {
  29 + const result: UseComponentStyleReturnType = { style: {} }
  30 +
  31 + const nodeUtils = new NodeUtils()
  32 + const { cellInfo } = props.config
  33 + const { id } = cellInfo || {}
  34 + if (!id) return result
  35 + const cell = nodeUtils.getCellById(id)
  36 +
  37 + if (!cell) return result
  38 +
  39 + const cellState = nodeUtils.getCellState(cell)
  40 +
  41 + const {
  42 + align,
  43 + dashed,
  44 + fillColor,
  45 + fontColor,
  46 + fontFamily,
  47 + fontSize,
  48 + gradientColor,
  49 + gradientDirection,
  50 + opacity,
  51 + // shadow,
  52 + strokeColor,
  53 + // sketch,
  54 + strokeWidth = 1,
  55 + } = cellState.style as MxShapeStyleType
  56 +
  57 + const getBackgroundColor = () => {
  58 + return {
  59 + background: gradientColor !== 'none'
  60 + ? gradientDirection === GradientDirectionEnum.RADIAL
  61 + ? `radial-gradient(${fillColor}, ${gradientColor})`
  62 + : `linear-gradient(${gradientDirectionMap[gradientDirection]}, ${fillColor}, ${gradientColor})`
  63 + : fillColor,
  64 + } as CSSProperties
  65 + }
  66 +
  67 + const getBorderStyle = () => {
  68 + return {
  69 + borderColor: strokeColor,
  70 + borderWidth: strokeWidth,
  71 + borderStyle: strokeColor
  72 + ? dashed === EnableEnum.ENABLE
  73 + ? 'dashed'
  74 + : 'solid'
  75 + : 'none',
  76 + } as CSSProperties
  77 + }
  78 +
  79 + return {
  80 + style: {
  81 + textAlign: align,
  82 + opacity,
  83 + fontSize,
  84 + fontFamily,
  85 + color: fontColor,
  86 + ...getBorderStyle(),
  87 + ...getBackgroundColor(),
  88 + },
  89 + textAalign: align,
  90 + borderColor: strokeColor,
  91 + borderWidth: strokeWidth,
  92 + borderStyle: dashed === EnableEnum.ENABLE ? 'dashed' : 'solid',
  93 + backgroundColor: fillColor,
  94 + fontFamily,
  95 + color: fontColor,
  96 + fontSize,
  97 + gradientBackgroundColor: gradientColor,
  98 + gradientDirection,
  99 + opacity,
  100 + }
  101 +}
... ...
  1 +import type { CSSProperties } from 'vue'
  2 +import {
  3 + computed,
  4 + defineComponent,
  5 + getCurrentInstance,
  6 + nextTick,
  7 + onBeforeMount,
  8 + onMounted,
  9 + ref,
  10 + watch,
  11 +} from 'vue'
  12 +import { useThrottleFn } from '@vueuse/core'
  13 +
  14 +interface PropsType {
  15 + modelValue: boolean
  16 + list: Array<unknown>
  17 + step: number
  18 + limitScrollNum: number
  19 + hover: boolean
  20 + direction: String
  21 + singleHeight: number
  22 + singleWidth: number
  23 + singleWaitTime: number
  24 + isRemUnit: boolean
  25 + isWatch: boolean
  26 + delay: number
  27 + ease: any
  28 + count: number
  29 + copyNum: number
  30 + wheel: boolean
  31 + singleLine: boolean
  32 +}
  33 +
  34 +function useExpose(apis: Record<string, any>) {
  35 + const instance = getCurrentInstance()
  36 + if (instance)
  37 + Object.assign(instance.proxy as Object, apis)
  38 +}
  39 +
  40 +const Props = {
  41 + // 是否开启自动滚动
  42 + modelValue: {
  43 + type: Boolean,
  44 + default: true,
  45 + },
  46 + // 原始数据列表
  47 + list: {
  48 + type: Array,
  49 + required: true,
  50 + default: [],
  51 + },
  52 + // 步进速度,step 需是单步大小的约数
  53 + step: {
  54 + type: Number,
  55 + default: 1,
  56 + },
  57 + // 开启滚动的数据量
  58 + limitScrollNum: {
  59 + type: Number,
  60 + default: 3,
  61 + },
  62 + // 是否开启鼠标悬停
  63 + hover: {
  64 + type: Boolean,
  65 + default: false,
  66 + },
  67 + // 控制滚动方向
  68 + direction: {
  69 + type: String,
  70 + default: 'up',
  71 + },
  72 + // 单步运动停止的高度
  73 + singleHeight: {
  74 + type: Number,
  75 + default: 0,
  76 + },
  77 + // 单步运动停止的宽度
  78 + singleWidth: {
  79 + type: Number,
  80 + default: 0,
  81 + },
  82 + // 单步停止等待时间 (默认值 1000ms)
  83 + singleWaitTime: {
  84 + type: Number,
  85 + default: 1000,
  86 + },
  87 + // 是否开启 rem 度量
  88 + isRemUnit: {
  89 + type: Boolean,
  90 + default: false,
  91 + },
  92 + // 开启数据更新监听
  93 + isWatch: {
  94 + type: Boolean,
  95 + default: true,
  96 + },
  97 + // 动画时间
  98 + delay: {
  99 + type: Number,
  100 + default: 0,
  101 + },
  102 + // 动画方式
  103 + ease: {
  104 + type: [String, Object],
  105 + default: 'ease-in',
  106 + },
  107 + // 动画循环次数,-1 表示一直动画
  108 + count: {
  109 + type: Number,
  110 + default: -1,
  111 + },
  112 + // 拷贝几份滚动列表
  113 + copyNum: {
  114 + type: Number,
  115 + default: 1,
  116 + },
  117 + // 开启鼠标悬停时支持滚轮滚动
  118 + wheel: {
  119 + type: Boolean,
  120 + default: false,
  121 + },
  122 + // 启用单行滚动
  123 + singleLine: {
  124 + type: Boolean,
  125 + default: false,
  126 + },
  127 +}
  128 +
  129 +globalThis.window.cancelAnimationFrame = (function () {
  130 + return (
  131 + globalThis.window.cancelAnimationFrame
  132 + || function (id) {
  133 + return globalThis.window.clearTimeout(id)
  134 + }
  135 + )
  136 +})()
  137 +globalThis.window.requestAnimationFrame = (function () {
  138 + return (
  139 + globalThis.window.requestAnimationFrame
  140 + || function (callback) {
  141 + return globalThis.window.setTimeout(callback, 1000 / 60)
  142 + }
  143 + )
  144 +})()
  145 +
  146 +function dataWarm(list: any[]) {
  147 + if (list && typeof list !== 'boolean' && list.length > 100) {
  148 + console.warn(
  149 + `数据达到了${list.length}条有点多哦~,可能会造成部分老旧浏览器卡顿。`,
  150 + )
  151 + }
  152 +}
  153 +
  154 +const ScrollList = defineComponent({
  155 + name: 'ScrollList',
  156 + inheritAttrs: false,
  157 + props: Props,
  158 + emits: ['stop', 'count', 'move'],
  159 + setup(_props, { slots, emit, attrs }) {
  160 + const props = _props as unknown as PropsType
  161 + const scrollRef = ref(null)
  162 + const slotListRef = ref<HTMLDivElement | null>(null)
  163 + const realBoxRef = ref<HTMLDivElement | null>(null)
  164 + const reqFrame = ref<number | null>(null)
  165 + const singleWaitTimeout = ref<NodeJS.Timeout | null>(null)
  166 + const realBoxWidth = ref(0)
  167 + const realBoxHeight = ref(0)
  168 + const xPos = ref(0)
  169 + const yPos = ref(0)
  170 + const isHover = ref(false)
  171 + const _count = ref(0)
  172 +
  173 + const isScroll = computed(() => props.list ? (props.list.length >= props.limitScrollNum) : false)
  174 +
  175 + const realBoxStyle = computed(() => {
  176 + return {
  177 + width: realBoxWidth.value ? `${realBoxWidth.value}px` : 'auto',
  178 + transform: `translate(${xPos.value}px,${yPos.value}px)`,
  179 +
  180 + transition: `all ${typeof props.ease === 'string'
  181 + ? props.ease
  182 + : `cubic-bezier(${
  183 + props.ease.x1
  184 + },${
  185 + props.ease.y1
  186 + },${
  187 + props.ease.x2
  188 + },${
  189 + props.ease.y2
  190 + })`
  191 + } ${props.delay}ms`,
  192 + overflow: 'hidden',
  193 + display: props.singleLine ? 'flex' : 'block',
  194 + }
  195 + })
  196 +
  197 + const isHorizontal = computed(
  198 + () => props.direction === 'left' || props.direction === 'right',
  199 + )
  200 +
  201 + const floatStyle = computed<CSSProperties>(() => {
  202 + return isHorizontal.value
  203 + ? {
  204 + float: 'left',
  205 + overflow: 'hidden',
  206 + display: props.singleLine ? 'flex' : 'block',
  207 + flexShrink: props.singleLine ? 0 : 1,
  208 + }
  209 + : { overflow: 'hidden' }
  210 + })
  211 +
  212 + const baseFontSize = computed(() => {
  213 + return props.isRemUnit
  214 + ? parseInt(
  215 + globalThis.window.getComputedStyle(
  216 + globalThis.document.documentElement,
  217 + null,
  218 + ).fontSize,
  219 + )
  220 + : 1
  221 + })
  222 +
  223 + const realSingleStopWidth = computed(
  224 + () => props.singleWidth * baseFontSize.value,
  225 + )
  226 +
  227 + const realSingleStopHeight = computed(
  228 + () => props.singleHeight * baseFontSize.value,
  229 + )
  230 +
  231 + const step = computed(() => {
  232 + let singleStep: number
  233 + const _step = props.step
  234 + if (isHorizontal.value)
  235 + singleStep = realSingleStopWidth.value
  236 +
  237 + else
  238 + singleStep = realSingleStopHeight.value
  239 +
  240 + if (singleStep > 0 && singleStep % _step > 0) {
  241 + console.error(
  242 + '如果设置了单步滚动, step 需是单步大小的约数,否则无法保证单步滚动结束的位置是否准确。~~~~~',
  243 + )
  244 + }
  245 + return _step
  246 + })
  247 +
  248 + const cancel = () => {
  249 + cancelAnimationFrame(reqFrame.value as number)
  250 + reqFrame.value = null
  251 + }
  252 +
  253 + const animation = (
  254 + _direction: 'up' | 'down' | 'left' | 'right',
  255 + _step: number,
  256 + isWheel?: boolean,
  257 + ) => {
  258 + reqFrame.value = requestAnimationFrame(() => {
  259 + const h = realBoxHeight.value / 2
  260 + const w = realBoxWidth.value / 2
  261 + if (_direction === 'up') {
  262 + if (Math.abs(yPos.value) >= h) {
  263 + yPos.value = 0
  264 + _count.value += 1
  265 + emit('count', _count.value)
  266 + }
  267 + yPos.value -= _step
  268 + }
  269 + else if (_direction === 'down') {
  270 + if (yPos.value >= 0) {
  271 + yPos.value = h * -1
  272 + _count.value += 1
  273 + emit('count', _count.value)
  274 + }
  275 + yPos.value += _step
  276 + }
  277 + else if (_direction === 'left') {
  278 + if (Math.abs(xPos.value) >= w) {
  279 + xPos.value = 0
  280 + _count.value += 1
  281 + emit('count', _count.value)
  282 + }
  283 + xPos.value -= _step
  284 + }
  285 + else if (_direction === 'right') {
  286 + if (xPos.value >= 0) {
  287 + xPos.value = w * -1
  288 + _count.value += 1
  289 + emit('count', _count.value)
  290 + }
  291 + xPos.value += _step
  292 + }
  293 + if (isWheel)
  294 + return
  295 +
  296 + const { singleWaitTime } = props
  297 + if (singleWaitTimeout.value)
  298 + clearTimeout(singleWaitTimeout.value)
  299 +
  300 + if (realSingleStopHeight.value) {
  301 + if (Math.abs(yPos.value) % realSingleStopHeight.value < _step) {
  302 + singleWaitTimeout.value = setTimeout(() => {
  303 + move()
  304 + }, singleWaitTime)
  305 + }
  306 + else {
  307 + move()
  308 + }
  309 + }
  310 + else if (realSingleStopWidth.value) {
  311 + if (Math.abs(xPos.value) % realSingleStopWidth.value < _step) {
  312 + singleWaitTimeout.value = setTimeout(() => {
  313 + move()
  314 + }, singleWaitTime)
  315 + }
  316 + else {
  317 + move()
  318 + }
  319 + }
  320 + else {
  321 + move()
  322 + }
  323 + })
  324 + }
  325 +
  326 + function move() {
  327 + cancel()
  328 + if (isHover.value || !isScroll.value || _count.value === props.count) {
  329 + emit('stop', _count.value)
  330 + _count.value = 0
  331 + return
  332 + }
  333 + animation(
  334 + props.direction as 'up' | 'down' | 'left' | 'right',
  335 + step.value,
  336 + false,
  337 + )
  338 + }
  339 +
  340 + const initMove = () => {
  341 + dataWarm(props.list)
  342 + if (isHorizontal.value) {
  343 + let slotListWidth = (slotListRef.value as HTMLDivElement).offsetWidth
  344 + slotListWidth = slotListWidth * 2 + 1
  345 + realBoxWidth.value = slotListWidth
  346 + }
  347 +
  348 + if (isScroll.value) {
  349 + realBoxHeight.value = (realBoxRef.value as HTMLDivElement).offsetHeight
  350 + if (props.modelValue)
  351 + move()
  352 + }
  353 + else {
  354 + cancel()
  355 + yPos.value = xPos.value = 0
  356 + }
  357 + }
  358 +
  359 + const startMove = () => {
  360 + isHover.value = false
  361 + move()
  362 + }
  363 +
  364 + const stopMove = () => {
  365 + isHover.value = true
  366 + if (singleWaitTimeout.value)
  367 + clearTimeout(singleWaitTimeout.value)
  368 +
  369 + cancel()
  370 + }
  371 +
  372 + const hoverStop = computed(
  373 + () => props.hover && props.modelValue && isScroll.value,
  374 + )
  375 +
  376 + const throttleFunc = useThrottleFn((e: WheelEvent) => {
  377 + cancel()
  378 + const singleHeight = realSingleStopHeight.value
  379 + ? realSingleStopHeight.value
  380 + : 15
  381 + if (e.deltaY < 0)
  382 + animation('down', singleHeight, true)
  383 +
  384 + if (e.deltaY > 0)
  385 + animation('up', singleHeight, true)
  386 + }, 30)
  387 +
  388 + const onWheel = (e: WheelEvent) => {
  389 + throttleFunc(e)
  390 + }
  391 +
  392 + const reset = () => {
  393 + cancel()
  394 + isHover.value = false
  395 + initMove()
  396 + }
  397 +
  398 + const Reset = () => {
  399 + reset()
  400 + }
  401 +
  402 + useExpose({ Reset })
  403 +
  404 + watch(
  405 + () => props.list,
  406 + () => {
  407 + if (props.isWatch) {
  408 + nextTick(() => {
  409 + reset()
  410 + })
  411 + }
  412 + },
  413 + {
  414 + deep: true,
  415 + },
  416 + )
  417 +
  418 + watch(
  419 + () => props.modelValue,
  420 + (newValue) => {
  421 + if (newValue)
  422 + startMove()
  423 +
  424 + else
  425 + stopMove()
  426 + },
  427 + )
  428 +
  429 + watch(
  430 + () => props.count,
  431 + (newValue) => {
  432 + if (newValue !== 0)
  433 + startMove()
  434 + },
  435 + )
  436 +
  437 + onBeforeMount(() => {
  438 + cancel()
  439 + clearTimeout(singleWaitTimeout.value as unknown as number)
  440 + })
  441 +
  442 + onMounted(() => {
  443 + if (isScroll.value)
  444 + initMove()
  445 + })
  446 +
  447 + const { default: $default, html } = slots
  448 + const copyNum = new Array(props.copyNum).fill(null)
  449 +
  450 + const getHtml = () => {
  451 + return (
  452 + <>
  453 + <div ref={slotListRef} style={floatStyle.value}>
  454 + {$default && $default()}
  455 + </div>
  456 + {isScroll.value
  457 + ? copyNum.map(() => {
  458 + if (html && typeof html === 'function')
  459 + return <div style={floatStyle.value}>{html()}</div>
  460 +
  461 + else
  462 + return <div style={floatStyle.value}>{$default && $default()}</div>
  463 + })
  464 + : null}
  465 + </>
  466 + )
  467 + }
  468 +
  469 + return () => (
  470 + <div ref={scrollRef} class={attrs.class}>
  471 + {props.wheel && props.hover
  472 + ? (
  473 + <div
  474 + ref={realBoxRef}
  475 + style={realBoxStyle.value}
  476 + onMouseenter={() => {
  477 + if (hoverStop.value)
  478 + stopMove()
  479 + }}
  480 + onMouseleave={() => {
  481 + if (hoverStop.value)
  482 + startMove()
  483 + }}
  484 + onWheel={(e) => {
  485 + if (hoverStop.value)
  486 + onWheel(e)
  487 + }}
  488 + >
  489 + {getHtml()}
  490 + </div>
  491 + )
  492 + : (
  493 + <div
  494 + ref={realBoxRef}
  495 + style={realBoxStyle.value}
  496 + onMouseenter={() => {
  497 + if (hoverStop.value)
  498 + stopMove()
  499 + }}
  500 + onMouseleave={() => {
  501 + if (hoverStop.value)
  502 + startMove()
  503 + }}
  504 + >
  505 + {getHtml()}
  506 + </div>
  507 + )}
  508 + </div>
  509 + )
  510 + },
  511 +})
  512 +
  513 +export default ScrollList
  514 +
  515 +export { ScrollList }
... ...
... ... @@ -8,7 +8,7 @@ import { ComponentEnum } from '@/components/Form/src/enum'
8 8 import { useContentDataStoreWithOut } from '@/store/modules/contentData'
9 9 import { DateFormatEnum } from '@/enums/timeEnum'
10 10 import type { BasicColumn } from '@/components/Table'
11   -import type { CodeTypeEnum, ContentDataFieldsEnum } from '@/enums/datasource'
  11 +import { AlarmStatusEnum, type CodeTypeEnum, type ContentDataFieldsEnum } from '@/enums/datasource'
12 12
13 13 const contentDataStore = useContentDataStoreWithOut()
14 14
... ... @@ -31,37 +31,12 @@ export interface TableRecordItemType {
31 31 [ContentDataFieldsEnum.CODE_TYPE]?: Nullable<CodeTypeEnum>
32 32 }
33 33
34   -// 告警状态
35   -export const alarmStatus = [
36   - {
37   - label: '清除未确认',
38   - value: 'CLEARED_UNACK',
39   - color: 'red',
40   - },
41   - {
42   - label: '激活未确认',
43   - value: 'ACTIVE_UNACK',
44   - color: 'orange',
45   - },
46   - {
47   - label: '清除已确认',
48   - value: 'CLEARED_ACK',
49   - color: 'cyan',
50   - },
51   - {
52   - label: '激活已确认',
53   - value: 'ACTIVE_ACK',
54   - color: 'green',
55   - },
56   -]
57   -
58   -export interface alarmListInterface {
59   - deviceName: string
60   - deviceAlias: string
61   - status: string
62   - startTs: string
  34 +export const AlarmColorMap = {
  35 + [AlarmStatusEnum.CLEARED_UN_ACK]: 'red',
  36 + [AlarmStatusEnum.ACTIVE_UN_ACK]: 'orange',
  37 + [AlarmStatusEnum.CLEARED_ACK]: 'cyan',
  38 + [AlarmStatusEnum.ACTIVE_ACK]: 'green',
63 39 }
64   -
65 40 /**
66 41 * 告警列表相关枚举
67 42 */
... ...
1 1 <script setup lang="ts">
2 2 import { computed, nextTick, onMounted, reactive, unref } from 'vue'
3 3 import { Divider, Tag } from 'ant-design-vue'
4   -import Vue3SeamlessScroll from 'vue3-seamless-scroll/package/Vue3SeamlessScroll'
5   -import { useAlarmList } from './useAlarmList.hook'
6   -import { type alarmListInterface, alarmStatus } from './form.config'
  4 +import { ScrollList } from './ScrollList'
7 5 import { fetchAlarmList } from '@/api/alarm'
  6 +import type { AlarmListItemType } from '@/api/alarm/model'
8 7 import type { CreateComponentType } from '@/core/Library/types'
9 8 import { useContentDataStore } from '@/store/modules/contentData'
10 9 import { isLightboxMode } from '@/utils/env'
  10 +import { AlarmStatusColorEnum, AlarmStatusEnum, AlarmStatusNameEnum } from '@/enums/datasource'
11 11 import { formatToDateTime } from '@/utils/dateUtil'
12 12
13 13 const props = defineProps<{
... ... @@ -20,10 +20,8 @@ const getCellBounds = computed(
20 20
21 21 const contentDataStore = useContentDataStore()
22 22
23   -const { byStatusFindLabel } = useAlarmList()
24   -
25 23 const initOptions = reactive<{
26   - alarmList: alarmListInterface[]
  24 + alarmList: AlarmListItemType[]
27 25 scroll: boolean
28 26 interval: number
29 27 polling: number
... ... @@ -72,6 +70,7 @@ onMounted(async () => {
72 70 setInterval(initFetchAlarmList, initOptions.polling * 1000)
73 71 }
74 72 else {
  73 + const statusList = Object.values(AlarmStatusEnum)
75 74 Object.assign(initOptions, {
76 75 scroll: false,
77 76 interval: 0,
... ... @@ -80,9 +79,7 @@ onMounted(async () => {
80 79 deviceName: `示例设备${index + 1}`,
81 80 deviceAlias: `示例设备${index + 1}`,
82 81 startTs: formatToDateTime(),
83   - status: alarmStatus.map(item => item.value)[
84   - Math.floor(Math.random() * alarmStatus.length)
85   - ],
  82 + status: statusList[index % 4],
86 83 })),
87 84 })
88 85 }
... ... @@ -91,26 +88,28 @@ onMounted(async () => {
91 88
92 89 <template>
93 90 <div class="seamless-scroll w-full h-full flex justify-center items-center overflow-y-scroll">
94   - <Vue3SeamlessScroll
95   - v-model="initOptions.scroll" :single-wait-time="initOptions.interval"
96   - :list="initOptions.alarmList" :limit-scroll-num="10" :is-rem-unit="true" :delay="10" :wheel="true" hover :style="{
  91 + <ScrollList
  92 + v-model="initOptions.scroll" :single-wait-time="initOptions.interval" :list="initOptions.alarmList"
  93 + :limit-scroll-num="10" :is-rem-unit="true" :delay="10" :wheel="true" hover :style="{
97 94 width: `${getCellBounds.width}px`,
98 95 height: `${getCellBounds.height}px`,
99 96 }"
100 97 >
101 98 <div v-for="(item, index) in initOptions.alarmList" :key="index" class="flex flex-col items-start h-15 px-2">
102 99 <p class="text-xs">
103   - 设备:{{ item.deviceAlias || item.deviceName }}
  100 + <span>设备:</span>
  101 + <span class="ml-1">{{ item.deviceAlias || item.deviceName }}</span>
104 102 </p>
105   - <div class="flex items-center justify-between -mt-2">
106   - <span class="text-xs">时间:{{ item.startTs }}</span>
107   - <Tag class="ml-2 text-xs" :color="byStatusFindLabel(item.status, 'color')">
108   - {{ byStatusFindLabel(item.status, "") }}
  103 + <div class="flex items-center justify-between -mt-2 text-xs">
  104 + <span>时间:</span>
  105 + <span class="ml-1">{{ item.startTs }}</span>
  106 + <Tag class="ml-2" :color="AlarmStatusColorEnum[item.status]">
  107 + {{ AlarmStatusNameEnum[item.status] }}
109 108 </Tag>
110 109 </div>
111 110 <Divider class="mt-2 divider" />
112 111 </div>
113   - </Vue3SeamlessScroll>
  112 + </ScrollList>
114 113 </div>
115 114 </template>
116 115
... ...
1   -import { alarmStatus } from './form.config'
2   -
3   -export const useAlarmList = () => {
4   - // 映射label
5   - const byStatusFindLabel = (status: string, color: string) => {
6   - if (!color) return alarmStatus.find(item => item.value === status)?.label
7   - return alarmStatus.find(item => item.value === status)?.color
8   - }
9   - return {
10   - byStatusFindLabel,
11   - }
12   -}
... ... @@ -335,3 +335,25 @@ export enum SocketSubscriberEnum {
335 335 TS_SUB_CMDS = 'tsSubCmds',
336 336 HISTORY_CMDS = 'historyCmds',
337 337 }
  338 +
  339 +export enum AlarmStatusEnum {
  340 + CLEARED_UN_ACK = 'CLEARED_UNACK',
  341 + ACTIVE_UN_ACK = 'ACTIVE_UNACK',
  342 + CLEARED_ACK = 'CLEARED_ACK',
  343 + ACTIVE_ACK = 'ACTIVE_ACK',
  344 +}
  345 +
  346 +export enum AlarmStatusColorEnum {
  347 + CLEARED_UNACK = 'red',
  348 + ACTIVE_UNACK = 'orange',
  349 + CLEARED_ACK = 'cyan',
  350 + ACTIVE_ACK = 'green',
  351 +}
  352 +
  353 +export enum AlarmStatusNameEnum {
  354 + CLEARED_UNACK = '清除未确认',
  355 + ACTIVE_UNACK = '激活未确认',
  356 + CLEARED_ACK = '清除已确认',
  357 + ACTIVE_ACK = '激活已确认',
  358 +}
  359 +
... ...
... ... @@ -18,6 +18,39 @@ export type MxState = mxgraph.mxCellState
18 18
19 19 export type MxEditor = mxgraph.mxEditor
20 20
  21 +export enum EnableEnum {
  22 + ENABLE = 1,
  23 + CLOSE = 0,
  24 +}
  25 +
  26 +export enum GradientDirectionEnum {
  27 + WEST = 'west',
  28 + NORTH = 'north',
  29 + EAST = 'east',
  30 + SOUTH = 'south',
  31 + RADIAL = 'radial',
  32 +}
  33 +
  34 +export interface MxShapeStyleType {
  35 + align: 'center'
  36 + dashed: EnableEnum
  37 + fillColor: string
  38 + fontColor: string
  39 + fontFamily: string
  40 + fontSize: number
  41 + gradientColor: string
  42 + gradientDirection: GradientDirectionEnum
  43 + opacity: number
  44 + shadow: EnableEnum
  45 + strokeColor: string
  46 + // fillStyle:
  47 + /**
  48 + * @description 草图模式
  49 + */
  50 + sketch: EnableEnum
  51 + strokeWidth: number
  52 +}
  53 +
21 54 interface Entries {
22 55 title: string
23 56 key?: string
... ...