Showing
10 changed files
with
698 additions
and
73 deletions
| @@ -35,8 +35,7 @@ | @@ -35,8 +35,7 @@ | ||
| 35 | "sortablejs": "^1.15.0", | 35 | "sortablejs": "^1.15.0", |
| 36 | "video.js": "^7.20.3", | 36 | "video.js": "^7.20.3", |
| 37 | "videojs-flvjs-es6": "^1.0.1", | 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 | "devDependencies": { | 40 | "devDependencies": { |
| 42 | "@iconify/vue": "^4.1.1", | 41 | "@iconify/vue": "^4.1.1", |
| @@ -68,9 +68,6 @@ dependencies: | @@ -68,9 +68,6 @@ dependencies: | ||
| 68 | vue: | 68 | vue: |
| 69 | specifier: ^3.3.4 | 69 | specifier: ^3.3.4 |
| 70 | version: 3.3.4 | 70 | version: 3.3.4 |
| 71 | - vue3-seamless-scroll: | ||
| 72 | - specifier: ^2.0.1 | ||
| 73 | - version: 2.0.1 | ||
| 74 | 71 | ||
| 75 | devDependencies: | 72 | devDependencies: |
| 76 | '@iconify/vue': | 73 | '@iconify/vue': |
| @@ -6412,12 +6409,6 @@ packages: | @@ -6412,12 +6409,6 @@ packages: | ||
| 6412 | vue: 3.3.4 | 6409 | vue: 3.3.4 |
| 6413 | dev: false | 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 | /vue@3.3.4: | 6412 | /vue@3.3.4: |
| 6422 | resolution: {integrity: sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw==} | 6413 | resolution: {integrity: sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw==} |
| 6423 | dependencies: | 6414 | dependencies: |
| 1 | +import type { AlarmStatusEnum } from '@/enums/datasource' | ||
| 2 | + | ||
| 1 | /** | 3 | /** |
| 2 | * 告警列表 | 4 | * 告警列表 |
| 3 | */ | 5 | */ |
| @@ -28,7 +30,7 @@ export interface AlarmListItemType { | @@ -28,7 +30,7 @@ export interface AlarmListItemType { | ||
| 28 | deviceName: string | 30 | deviceName: string |
| 29 | type: string | 31 | type: string |
| 30 | severity: string | 32 | severity: string |
| 31 | - status: string | 33 | + status: AlarmStatusEnum |
| 32 | startTs: string | 34 | startTs: string |
| 33 | endTs: string | 35 | endTs: string |
| 34 | ackTs: string | 36 | ackTs: string |
src/core/Library/hook/useComponentStyle.ts
0 → 100644
| 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,7 +8,7 @@ import { ComponentEnum } from '@/components/Form/src/enum' | ||
| 8 | import { useContentDataStoreWithOut } from '@/store/modules/contentData' | 8 | import { useContentDataStoreWithOut } from '@/store/modules/contentData' |
| 9 | import { DateFormatEnum } from '@/enums/timeEnum' | 9 | import { DateFormatEnum } from '@/enums/timeEnum' |
| 10 | import type { BasicColumn } from '@/components/Table' | 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 | const contentDataStore = useContentDataStoreWithOut() | 13 | const contentDataStore = useContentDataStoreWithOut() |
| 14 | 14 | ||
| @@ -31,37 +31,12 @@ export interface TableRecordItemType { | @@ -31,37 +31,12 @@ export interface TableRecordItemType { | ||
| 31 | [ContentDataFieldsEnum.CODE_TYPE]?: Nullable<CodeTypeEnum> | 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 | <script setup lang="ts"> | 1 | <script setup lang="ts"> |
| 2 | import { computed, nextTick, onMounted, reactive, unref } from 'vue' | 2 | import { computed, nextTick, onMounted, reactive, unref } from 'vue' |
| 3 | import { Divider, Tag } from 'ant-design-vue' | 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 | import { fetchAlarmList } from '@/api/alarm' | 5 | import { fetchAlarmList } from '@/api/alarm' |
| 6 | +import type { AlarmListItemType } from '@/api/alarm/model' | ||
| 8 | import type { CreateComponentType } from '@/core/Library/types' | 7 | import type { CreateComponentType } from '@/core/Library/types' |
| 9 | import { useContentDataStore } from '@/store/modules/contentData' | 8 | import { useContentDataStore } from '@/store/modules/contentData' |
| 10 | import { isLightboxMode } from '@/utils/env' | 9 | import { isLightboxMode } from '@/utils/env' |
| 10 | +import { AlarmStatusColorEnum, AlarmStatusEnum, AlarmStatusNameEnum } from '@/enums/datasource' | ||
| 11 | import { formatToDateTime } from '@/utils/dateUtil' | 11 | import { formatToDateTime } from '@/utils/dateUtil' |
| 12 | 12 | ||
| 13 | const props = defineProps<{ | 13 | const props = defineProps<{ |
| @@ -20,10 +20,8 @@ const getCellBounds = computed( | @@ -20,10 +20,8 @@ const getCellBounds = computed( | ||
| 20 | 20 | ||
| 21 | const contentDataStore = useContentDataStore() | 21 | const contentDataStore = useContentDataStore() |
| 22 | 22 | ||
| 23 | -const { byStatusFindLabel } = useAlarmList() | ||
| 24 | - | ||
| 25 | const initOptions = reactive<{ | 23 | const initOptions = reactive<{ |
| 26 | - alarmList: alarmListInterface[] | 24 | + alarmList: AlarmListItemType[] |
| 27 | scroll: boolean | 25 | scroll: boolean |
| 28 | interval: number | 26 | interval: number |
| 29 | polling: number | 27 | polling: number |
| @@ -72,6 +70,7 @@ onMounted(async () => { | @@ -72,6 +70,7 @@ onMounted(async () => { | ||
| 72 | setInterval(initFetchAlarmList, initOptions.polling * 1000) | 70 | setInterval(initFetchAlarmList, initOptions.polling * 1000) |
| 73 | } | 71 | } |
| 74 | else { | 72 | else { |
| 73 | + const statusList = Object.values(AlarmStatusEnum) | ||
| 75 | Object.assign(initOptions, { | 74 | Object.assign(initOptions, { |
| 76 | scroll: false, | 75 | scroll: false, |
| 77 | interval: 0, | 76 | interval: 0, |
| @@ -80,9 +79,7 @@ onMounted(async () => { | @@ -80,9 +79,7 @@ onMounted(async () => { | ||
| 80 | deviceName: `示例设备${index + 1}`, | 79 | deviceName: `示例设备${index + 1}`, |
| 81 | deviceAlias: `示例设备${index + 1}`, | 80 | deviceAlias: `示例设备${index + 1}`, |
| 82 | startTs: formatToDateTime(), | 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,26 +88,28 @@ onMounted(async () => { | ||
| 91 | 88 | ||
| 92 | <template> | 89 | <template> |
| 93 | <div class="seamless-scroll w-full h-full flex justify-center items-center overflow-y-scroll"> | 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 | width: `${getCellBounds.width}px`, | 94 | width: `${getCellBounds.width}px`, |
| 98 | height: `${getCellBounds.height}px`, | 95 | height: `${getCellBounds.height}px`, |
| 99 | }" | 96 | }" |
| 100 | > | 97 | > |
| 101 | <div v-for="(item, index) in initOptions.alarmList" :key="index" class="flex flex-col items-start h-15 px-2"> | 98 | <div v-for="(item, index) in initOptions.alarmList" :key="index" class="flex flex-col items-start h-15 px-2"> |
| 102 | <p class="text-xs"> | 99 | <p class="text-xs"> |
| 103 | - 设备:{{ item.deviceAlias || item.deviceName }} | 100 | + <span>设备:</span> |
| 101 | + <span class="ml-1">{{ item.deviceAlias || item.deviceName }}</span> | ||
| 104 | </p> | 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 | </Tag> | 108 | </Tag> |
| 110 | </div> | 109 | </div> |
| 111 | <Divider class="mt-2 divider" /> | 110 | <Divider class="mt-2 divider" /> |
| 112 | </div> | 111 | </div> |
| 113 | - </Vue3SeamlessScroll> | 112 | + </ScrollList> |
| 114 | </div> | 113 | </div> |
| 115 | </template> | 114 | </template> |
| 116 | 115 |
src/core/Library/packages/Basic/AlarmList/useAlarmList.hook.ts
deleted
100644 → 0
| 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,3 +335,25 @@ export enum SocketSubscriberEnum { | ||
| 335 | TS_SUB_CMDS = 'tsSubCmds', | 335 | TS_SUB_CMDS = 'tsSubCmds', |
| 336 | HISTORY_CMDS = 'historyCmds', | 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,6 +18,39 @@ export type MxState = mxgraph.mxCellState | ||
| 18 | 18 | ||
| 19 | export type MxEditor = mxgraph.mxEditor | 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 | interface Entries { | 54 | interface Entries { |
| 22 | title: string | 55 | title: string |
| 23 | key?: string | 56 | key?: string |