Преглед изворни кода

[Feat 0000] 可配置首页原版模块支持Transition动画

houzekong пре 1 недеља
родитељ
комит
75819cac5e

+ 46 - 45
src/views/vent/home/configurable/components/ModuleOriginal.vue

@@ -16,56 +16,57 @@
   </component>
 </template>
 <script lang="ts" setup>
-import Header from './header.vue';
-import Content from './content.vue';
-import ModuleLeft from './original/moduleLeft.vue';
-import ModuleBottom from './original/moduleBottom.vue';
-import { computed, ref } from 'vue';
-import { openWindow } from '/@/utils';
-import { getFormattedText } from '../hooks/helper';
-// import { ModuleProps } from '../types';
+  import Header from './header.vue';
+  import Content from './content.vue';
+  import ModuleLeft from './original/moduleLeft.vue';
+  import ModuleRight from './original/moduleRight.vue';
+  import ModuleBottom from './original/moduleBottom.vue';
+  import { computed, ref } from 'vue';
+  import { openWindow } from '/@/utils';
+  import { getFormattedText } from '../hooks/helper';
+  // import { ModuleProps } from '../types';
 
-const props = defineProps<{
-  /** 配置的详细模块信息 */
-  moduleData: any;
-  /** 配置的详细样式信息 */
-  showStyle: any;
-  /** 该模块配置中的设备标识符 */
-  deviceType: string;
-  /** api返回的数据 */
-  data: any;
-  moduleName: string;
-  visible: boolean;
-}>();
-defineEmits(['close', 'click']);
+  const props = defineProps<{
+    /** 配置的详细模块信息 */
+    moduleData: any;
+    /** 配置的详细样式信息 */
+    showStyle: any;
+    /** 该模块配置中的设备标识符 */
+    deviceType: string;
+    /** api返回的数据 */
+    data: any;
+    moduleName: string;
+    visible: boolean;
+  }>();
+  defineEmits(['close', 'click']);
 
-const { header } = props.moduleData;
-const selectedData = ref();
+  const { header } = props.moduleData;
+  const selectedData = ref();
 
-const style = computed(() => {
-  const size = props.showStyle.size;
-  const position = props.showStyle.position;
-  return size + position;
-});
+  const style = computed(() => {
+    const size = props.showStyle.size;
+    const position = props.showStyle.position;
+    return size + position;
+  });
 
-// 根据配置里的定位判断应该使用哪个module组件
-function getModuleComponent({ size, position }) {
-  const [_, width] = size.match(/width:([0-9]+)px/) || [];
-  if (position.includes('bottom') || parseInt(width) > 800) {
+  // 根据配置里的定位判断应该使用哪个module组件
+  function getModuleComponent({ size, position }) {
+    const [_, width] = size.match(/width:([0-9]+)px/) || [];
+    if (position.includes('bottom') || parseInt(width) > 800) {
+      return ModuleBottom;
+    }
+    if (position.includes('left')) {
+      return ModuleLeft;
+    }
+    if (position.includes('right')) {
+      return ModuleRight;
+    }
     return ModuleBottom;
   }
-  if (position.includes('left')) {
-    return ModuleLeft;
-  }
-  if (position.includes('right')) {
-    return ModuleLeft;
-  }
-  return ModuleBottom;
-}
 
-function redirectTo() {
-  const { to } = props.moduleData;
-  if (!to) return;
-  openWindow(getFormattedText(selectedData.value, to));
-}
+  function redirectTo() {
+    const { to } = props.moduleData;
+    if (!to) return;
+    openWindow(getFormattedText(selectedData.value, to));
+  }
 </script>

+ 10 - 8
src/views/vent/home/configurable/components/original/moduleBottom.vue

@@ -1,13 +1,15 @@
 <template>
-  <div v-if="visible" class="module-content">
-    <div v-if="title" class="module-content__title__expand">
-      <span class="action-btn close-btn" @click="closeModel"></span>
-      <span @click="clickHandler">{{ title }}</span>
+  <Transition>
+    <div v-if="visible" class="module-content">
+      <div v-if="title" class="module-content__title__expand">
+        <span class="action-btn close-btn" @click="closeModel"></span>
+        <span @click="clickHandler">{{ title }}</span>
+      </div>
+      <div class="module-slot">
+        <slot></slot>
+      </div>
     </div>
-    <div class="module-slot">
-      <slot></slot>
-    </div>
-  </div>
+  </Transition>
 </template>
 <script lang="ts" setup>
   defineProps<{ title: string; visible: boolean }>();

+ 10 - 8
src/views/vent/home/configurable/components/original/moduleLeft.vue

@@ -1,13 +1,15 @@
 <template>
-  <div v-if="visible" class="module-content">
-    <div v-if="title" class="module-content__title__expand">
-      <span class="action-btn close-btn" @click="closeModel"></span>
-      <span @click="clickHandler">{{ title }}</span>
+  <Transition>
+    <div v-if="visible" class="module-content">
+      <div v-if="title" class="module-content__title__expand">
+        <span class="action-btn close-btn" @click="closeModel"></span>
+        <span @click="clickHandler">{{ title }}</span>
+      </div>
+      <div class="module-slot">
+        <slot></slot>
+      </div>
     </div>
-    <div class="module-slot">
-      <slot></slot>
-    </div>
-  </div>
+  </Transition>
 </template>
 <script lang="ts" setup>
   defineProps<{ title: string; visible: boolean }>();

+ 100 - 0
src/views/vent/home/configurable/components/original/moduleRight.vue

@@ -0,0 +1,100 @@
+<template>
+  <Transition>
+    <div v-if="visible" class="module-content">
+      <div v-if="title" class="module-content__title__expand">
+        <span class="action-btn close-btn" @click="closeModel"></span>
+        <span @click="clickHandler">{{ title }}</span>
+      </div>
+      <div class="module-slot">
+        <slot></slot>
+      </div>
+    </div>
+  </Transition>
+</template>
+<script lang="ts" setup>
+  // 和 ./moduleLeft 一样,针对动画做了一些修改
+  defineProps<{ title: string; visible: boolean }>();
+  const emit = defineEmits(['close', 'click']);
+
+  function closeModel() {
+    emit('close');
+  }
+  function clickHandler() {
+    emit('click');
+  }
+</script>
+<style lang="less" scoped>
+  @import '/@/design/theme.less';
+
+  @{theme-deepblue} {
+    .module-content {
+      --image-model_original_title_bg: url('@/assets/images/themify/deepblue/home-container/configurable/model_original_title_bg.png');
+    }
+  }
+
+  .module-content {
+    --image-model_original_title_bg: url('@/assets/images/home-container/configurable/model_original_title_bg.png');
+    --bg-height: 33px;
+    color: #fff;
+    box-sizing: border-box;
+    position: absolute;
+    width: 100%;
+    height: 100%;
+  }
+
+  .module-content__title__expand {
+    width: 100%;
+    height: var(--bg-height);
+    background: var(--image-model_original_title_bg) no-repeat;
+    background-size: 100% 100%;
+    position: relative;
+    text-align: center;
+    line-height: var(--bg-height);
+  }
+
+  // .module-content__title {
+  //   width: 50%;
+  //   height: var(--bg-height);
+  //   background: url('@/assets/images/home-container/configurable/model_left_title_bg.png') no-repeat;
+  //   background-size: 100% 100%;
+  //   position: relative;
+  //   text-align: right;
+  //   padding: 4px 10% 0 0;
+  // }
+
+  // 固定在父容器右上角的按钮图标
+  // .action-btn {
+  //   width: 18px;
+  //   height: 18px;
+  //   background: url('@/assets/images/home-container/configurable/expand.svg') no-repeat center;
+  //   position: absolute;
+  //   right: 0;
+  //   top: 0;
+  // }
+  // .close-btn {
+  //   transform: rotate(-90deg);
+  // }
+
+  .module-slot {
+    height: calc(100% - 33px);
+    width: calc(100% - 20px);
+    backdrop-filter: blur(5px);
+    // #182d47
+    background-color: var(--vent-configurable-original-module-bg);
+    margin-left: 10px;
+  }
+
+  // Transition动画相关
+  .v-enter-active,
+  .v-leave-active {
+    transition: all 0.3s ease;
+  }
+
+  .v-enter-from,
+  .v-leave-to {
+    // opacity: 1;
+    transform: translateX(100%);
+    // transform: scaleY(0);
+    // transform-origin: center top;
+  }
+</style>