| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- <!-- eslint-disable vue/multi-word-component-names -->
- <template>
- <!-- 基准的画廊模块,通过不同的 type 展示不同的样式 -->
- <div ref="container" class="syswind__container w-full h-full">
- <!-- 画廊项的具体内容填充剩余宽度 -->
- <div
- v-for="item in data"
- :key="item.deviceID"
- class="syswind__card"
- @mouseenter="getTrigger(item.deviceID).onEnter($event)"
- @mousemove="getTrigger(item.deviceID).onMove($event)"
- @mouseleave="getTrigger(item.deviceID).onLeave()"
- >
- <!-- 数据解读悬浮按钮(公共组件) -->
- <DataInterpretationBtn
- v-if="getTrigger(item.deviceID).state.visible"
- :x="getTrigger(item.deviceID).state.x"
- :y="getTrigger(item.deviceID).state.y"
- @click="handleInterpret(item)"
- @btn-enter="getTrigger(item.deviceID).onBtnEnter()"
- @btn-leave="getTrigger(item.deviceID).onBtnLeave()"
- />
- <!-- 卡片内容 -->
- <div class="syswind__card__title font-bold" :title="getFormattedText(item, config.title)">{{ getFormattedText(item, config.title) }}</div>
- <div class="flex items-center justify-between syswind__card__vol_wrapper">
- <div class="syswind__card__vol_image" :class="{ overlimit: isVolumnOverLimit(item) }"></div>
- <div>
- <div
- v-for="(ctx, idx) in config.volumns"
- :key="`v${idx}`"
- class="flex justify-between pl-20px pr-10px syswind__card__vol_space"
- :class="{ overlimit_space: isVolumnOverLimit(item) }"
- >
- <span>{{ getFormattedText(item, ctx.label) }}</span>
- <span class="font-bold">{{ getFormattedText(item, ctx.value) }}</span>
- </div>
- </div>
- </div>
- <div class="flex items-center justify-between syswind__card__spd_wrapper">
- <div class="syswind__card__spd_image" :class="{ overlimit: isSpeedOverLimit(item) }"></div>
- <div>
- <div
- v-for="(ctx, idx) in config.speeds"
- :key="`s${idx}`"
- class="flex justify-between pl-20px pr-10px syswind__card__spd_space"
- :class="{
- overlimit_space: isSpeedOverLimit(item),
- }"
- >
- <span>{{ getFormattedText(item, ctx.label) }}</span>
- <span class="font-bold">{{ getFormattedText(item, ctx.value) }}</span>
- </div>
- </div>
- </div>
- </div>
- <!-- 数据解读弹框(公共组件) -->
- <DataInterpretationModal
- :visible="modalVisible"
- :loading="loading"
- :streaming-text="streamingText"
- :error="error"
- :thinking="thinking"
- :todos="todos"
- :executing-tools="executingTools"
- :tool-calls="toolCalls"
- @close="handleClose"
- />
- </div>
- </template>
- <script lang="ts" setup>
- import { defaultTo, inRange, first } from 'lodash-es';
- import { getFormattedText } from '../../hooks/helper';
- // import { onMounted, ref } from 'vue';
- // import { useEventListener, useScroll } from '@vueuse/core';
- // import { get } from 'lodash-es';
- // import { computed } from 'vue';
- import { useDataInterpretationList, DataInterpretationBtn, DataInterpretationModal } from '/@/views/ventAI/dataPicker';
- const props = defineProps<{
- config: {
- title: string;
- volumns: { value: string; label: string; lowerLimit: string }[];
- speeds: { value: string; label: string; lowerLimit: string; upperLimit: string }[];
- prop: string;
- };
- data: any[];
- }>();
- // defineEmits(['click']);
- // 判断val是否在low、high指定的范围内
- const { modalVisible, loading, streamingText, error, thinking, todos, executingTools, toolCalls, getTrigger, handleInterpret, handleClose } =
- useDataInterpretationList((item) => ({
- device_id: item.deviceID,
- device_name: item.strinstallpos,
- device_type: 'windrect',
- }));
- function isOverLimit(val: string, low: string = '', high: string = '') {
- const l = parseFloat(low);
- const h = parseFloat(high);
- const v = parseFloat(val);
- return !inRange(defaultTo(v, 0), defaultTo(l, -Infinity), defaultTo(h, Infinity));
- }
- function isVolumnOverLimit(item) {
- const ctx = first(props.config.volumns);
- if (!ctx) return false;
- return isOverLimit(getFormattedText(item, ctx.value), getFormattedText(item, ctx.lowerLimit));
- }
- function isSpeedOverLimit(item) {
- const ctx = first(props.config.speeds);
- if (!ctx) return false;
- return isOverLimit(getFormattedText(item, ctx.value), getFormattedText(item, ctx.lowerLimit), getFormattedText(item, ctx.upperLimit));
- }
- // const container = ref<HTMLElement>();
- // const { y, directions } = useScroll(container); // 当前滚动位置(响应式)
- // const STEP = 234;
- // useEventListener(
- // container,
- // 'scrollend',
- // (event) => {
- // console.log('debug rr', event);
- // event.preventDefault();
- // event.stopPropagation(); // 防止冒泡到外层
- // const direction = directions.top ? -1 : 1;
- // const targetY = y.value + direction * STEP;
- // container.value?.scrollTo({
- // top: targetY,
- // behavior: 'smooth',
- // });
- // },
- // { passive: false }
- // );
- </script>
- <style lang="less" scoped>
- @import '@/design/theme.less';
- @import '@/design/theme.less';
- @{theme-green} {
- .gallery {
- --image-gallery_I_2: url(/@/assets/images/themify/deepblue/home-container/configurable/dusthome/gallery_I_2.png);
- --image-gallery_I_1: url(/@/assets/images/themify/green/home-container/configurable/dusthome/gallery_I_1.png);
- }
- }
- .syswind__container {
- padding: 10px 30px;
- display: flex;
- flex-wrap: wrap;
- justify-content: space-between;
- overflow: auto;
- scroll-padding-top: 10px;
- scroll-snap-type: y mandatory;
- }
- .syswind__card {
- --image-syswind-space-red: url(/@/assets/images/home-container/configurable/preset/syswind-space-red.png);
- --image-syswind-space-blue: url(/@/assets/images/home-container/configurable/preset/syswind-space-blue.png);
- --image-syswind-space-green: url(/@/assets/images/home-container/configurable/preset/syswind-space-green.png);
- --image-syswind-border-blue: url(/@/assets/images/home-container/configurable/preset/syswind-border-blue.png);
- --image-syswind-border-green: url(/@/assets/images/home-container/configurable/preset/syswind-border-green.png);
- --image-syswind-module-title: url(/@/assets/images/home-container/configurable/preset/syswind-module-title.png);
- --image-syswind-module: url(/@/assets/images/home-container/configurable/preset/syswind-module.png);
- --image-syswind-icon-blue: url(/@/assets/images/home-container/configurable/preset/syswind-icon-blue.png);
- --image-syswind-icon-green: url(/@/assets/images/home-container/configurable/preset/syswind-icon-green.png);
- --image-syswind-icon-red: url(/@/assets/images/home-container/configurable/preset/syswind-icon-red.png);
- --image-syswind-icon-vol: url(/@/assets/images/home-container/configurable/preset/syswind-icon-vol.svg);
- --image-syswind-icon-vol-red: url(/@/assets/images/home-container/configurable/preset/syswind-icon-vol-red.svg);
- --image-syswind-icon-spd: url(/@/assets/images/home-container/configurable/preset/syswind-icon-spd.svg);
- --image-syswind-icon-spd-red: url(/@/assets/images/home-container/configurable/preset/syswind-icon-spd-red.svg);
- position: relative;
- background-image: var(--image-syswind-module);
- background-repeat: no-repeat;
- width: 320px;
- // width: 320px;
- height: 234px;
- margin: 0 0 10px 0;
- scroll-padding-top: 10px;
- scroll-snap-align: start;
- .syswind__card__title {
- background-image: var(--image-syswind-module-title);
- width: 250px;
- height: 24px;
- padding-left: 10px;
- padding-right: 20px;
- font-size: 16px;
- background-size: 100% 100%;
- overflow: hidden; /* 隐藏溢出内容 */
- white-space: nowrap; /* 强制文本不换行 */
- text-overflow: ellipsis; /* 显示省略号 */
- }
- .syswind__card__vol_image {
- background-image: var(--image-syswind-icon-green), var(--image-syswind-icon-vol);
- background-position: center, center;
- background-repeat: no-repeat;
- width: 76px;
- height: 70px;
- }
- .syswind__card__spd_image {
- background-image: var(--image-syswind-icon-blue), var(--image-syswind-icon-spd);
- background-position: center, center;
- background-repeat: no-repeat;
- width: 76px;
- height: 70px;
- }
- .syswind__card__vol_space {
- background-image: var(--image-syswind-space-green);
- background-repeat: no-repeat;
- background-position: bottom left;
- width: 208px;
- height: 28px;
- line-height: 28px;
- }
- .syswind__card__spd_space {
- background-image: var(--image-syswind-space-blue);
- background-repeat: no-repeat;
- background-position: bottom left;
- width: 208px;
- height: 28px;
- line-height: 28px;
- }
- .syswind__card__vol_wrapper {
- background-image: var(--image-syswind-border-green);
- height: 72px;
- background-position: right center;
- background-repeat: no-repeat;
- margin: 10px;
- padding-right: 10px;
- .overlimit {
- background-image: var(--image-syswind-icon-red), var(--image-syswind-icon-vol-red);
- }
- }
- .syswind__card__spd_wrapper {
- background-image: var(--image-syswind-border-blue);
- height: 100px;
- background-position: right center;
- background-repeat: no-repeat;
- margin: 10px;
- padding-right: 10px;
- .overlimit {
- background-image: var(--image-syswind-icon-red), var(--image-syswind-icon-spd-red);
- }
- }
- .overlimit_space {
- background-image: var(--image-syswind-space-red);
- }
- }
- </style>
|