Browse Source

feat: 制作展示页面

bill 6 months ago
parent
commit
0b5f77880a

+ 58 - 0
src/views/guide/guide/attach-animation-sam.vue

@@ -0,0 +1,58 @@
+<template>
+  <div
+    class="anima fun-ctrl"
+    :class="{ disabled: disableAttach, active: isPlayIng }"
+    @click="attachAnimation"
+  >
+    <ui-icon type="a-animation_s" />
+    <span>激活动画</span>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { currentTime } from "@/sdk/association/animation";
+import { computed, ref, watchEffect } from "vue";
+import { GuidePath } from "@/store";
+
+const props = defineProps<{ current: GuidePath; paths: GuidePath[] }>();
+
+const playNdx = computed(() => props.paths.findIndex((path) => path.playAnimation));
+const curNdx = computed(() => props.paths.indexOf(props.current));
+const isCurrentPlay = computed(
+  () => playNdx.value !== -1 && curNdx.value === playNdx.value
+);
+const disableAttach = computed(() => playNdx.value !== -1 && !isCurrentPlay.value);
+const isPlayIng = computed(() => playNdx.value !== -1 && curNdx.value >= playNdx.value);
+
+const getNdxTime = (curNdx: number) => {
+  if (playNdx.value === -1 || curNdx < playNdx.value) return 0;
+  let mis = 0;
+  for (let i = playNdx.value; i < curNdx; i++) {
+    mis += props.paths[i].time;
+  }
+  return mis;
+};
+
+watchEffect(() => {
+  currentTime.value = getNdxTime(curNdx.value);
+});
+
+const attachAnimation = () => {
+  props.current.playAnimation = !props.current.playAnimation;
+};
+</script>
+
+<style lang="scss" scoped>
+.anima {
+  display: flex;
+  align-items: center;
+  margin: 0 30px;
+  &.active {
+    color: var(--colors-primary-base) !important;
+  }
+
+  .icon {
+    font-size: 1.4em;
+  }
+}
+</style>

+ 16 - 9
src/views/guide/guide/edit-paths.vue

@@ -23,16 +23,19 @@
         <div class="length">
           <span>视频时长</span>{{ paths.reduce((t, c) => t + c.time, 0).toFixed(1) }}s
         </div>
-        <div
-          class="fun-ctrl clear"
-          @click="deleteAll"
-          :class="{ disabled: isScenePlayIng }"
-        >
-          <ui-icon type="del" />
-          <span>清空画面</span>
+        <div>
+          <attachAnimation :current="current" :paths="paths" />
+          <div
+            class="fun-ctrl clear"
+            @click="deleteAll"
+            :class="{ disabled: isScenePlayIng }"
+          >
+            <ui-icon type="del" />
+            <span>清空画面</span>
+          </div>
         </div>
       </div>
-      <attachAnimation :current="current" :paths="paths" />
+      <!-- <attachAnimation :current="current" :paths="paths" /> -->
 
       <div class="photo-list" ref="listVm">
         <template v-for="(path, i) in paths" :key="path.id">
@@ -84,7 +87,7 @@
 </template>
 
 <script setup lang="ts">
-import attachAnimation from "./attach-animation.vue";
+import attachAnimation from "./attach-animation-sam.vue";
 import ViewSetting from "@/components/view-setting/index.vue";
 import { loadPack, togetherCallback, getFileUrl, asyncTimeout } from "@/utils";
 import {
@@ -314,6 +317,10 @@ onUnmounted(() => {
     .length span {
       margin-right: 10px;
     }
+    > div {
+      display: flex;
+      align-items: center;
+    }
 
     .clear {
       display: flex;

+ 15 - 1
src/views/guide/guide/show.vue

@@ -1,8 +1,22 @@
 <template>
-  <GuideSign v-for="guide in guides" :key="guide.id" :guide="guide" :edit="false" />
+  <ui-group title="导览列表" class="show-taggings">
+    <GuideSign
+      v-for="guide in filterGuides"
+      :key="guide.id"
+      :guide="guide"
+      :edit="false"
+    />
+  </ui-group>
 </template>
 
 <script setup lang="ts">
+import { computed } from "vue";
 import GuideSign from "./sign.vue";
 import { guides } from "@/store";
+
+const props = withDefaults(defineProps<{ keyword?: string }>(), { keyword: "" });
+
+const filterGuides = computed(() =>
+  guides.value.filter((guide) => guide.title.includes(props.keyword))
+);
 </script>

+ 0 - 3
src/views/guide/guide/sign.vue

@@ -141,9 +141,6 @@ const paths = computed(() => getGuidePaths(props.guide));
   align-items: center;
   padding: 20px 0;
   border-bottom: 1px solid var(--colors-border-color);
-  &:first-child {
-    border-top: 1px solid var(--colors-border-color);
-  }
 
   &.search {
     padding: 0;

+ 30 - 1
src/views/guide/path/show.vue

@@ -1,8 +1,37 @@
 <template>
-  <PathSign v-for="path in paths" :key="path.id" :path="path" :edit="false" />
+  <ui-group title="路径列表" class="show-taggings">
+    <template #icon>
+      <ui-icon
+        ctrl
+        :type="custom.showPaths ? 'eye-s' : 'eye-n'"
+        @click="custom.showPaths = !custom.showPaths"
+      />
+    </template>
+    <PathSign
+      v-for="path in filterPath"
+      :key="path.id"
+      :path="path"
+      :edit="false"
+      class="show-path"
+    />
+  </ui-group>
 </template>
 
 <script setup lang="ts">
+import { custom } from "@/env";
 import PathSign from "./sign.vue";
 import { paths } from "@/store";
+import { computed } from "vue";
+
+const props = withDefaults(defineProps<{ keyword?: string }>(), { keyword: "" });
+
+const filterPath = computed(() =>
+  paths.value.filter((path) => path.name.includes(props.keyword))
+);
 </script>
+
+<style lang="scss" scoped>
+.show-path {
+  border-bottom: 1px solid var(--colors-border-color);
+}
+</style>

+ 18 - 12
src/views/measure/show.vue

@@ -1,31 +1,37 @@
 <template>
   <ui-group title="测量列表" class="show-measures">
     <template #icon>
-      <ui-icon 
+      <ui-icon
         ctrl
-        :type="custom.showMeasures ? 'eye-s' : 'eye-n'" 
-        @click="custom.showMeasures = !custom.showMeasures" 
+        :type="custom.showMeasures ? 'eye-s' : 'eye-n'"
+        @click="custom.showMeasures = !custom.showMeasures"
       />
     </template>
-    <MeasureSign 
-      v-for="measure in measures" 
-      :key="measure.id" 
-      :measure="measure" 
+    <MeasureSign
+      v-for="measure in filterMeasures"
+      :key="measure.id"
+      :measure="measure"
       :edit="false"
     />
   </ui-group>
 </template>
 
 <script setup lang="ts">
-import MeasureSign from '@/views/measure/sign.vue'
-import { measures } from '@/store'
-import { custom } from '@/env'
+import MeasureSign from "@/views/measure/sign.vue";
+import { measures } from "@/store";
+import { custom } from "@/env";
+import { computed } from "vue";
 
-</script>
+const props = withDefaults(defineProps<{ keyword?: string }>(), { keyword: "" });
 
+const filterMeasures = computed(() => {
+  console.log(props.keyword);
+  return measures.value.filter((measure) => measure.title.includes(props.keyword));
+});
+</script>
 
 <style lang="scss">
 .show-measures.ui-group > h3.group-title {
   margin-bottom: 0;
 }
-</style>
+</style>

+ 33 - 18
src/views/summary/index.vue

@@ -5,46 +5,51 @@
 
   <RightFillPano>
     <template #header>
-      <div class="tabs">
-        <span
-          v-for="tab in tabs"
-          :key="tab.key"
-          :class="{ active: tab.key === current }"
-          @click="current = tab.key"
-        >
-          {{ tab.text }}
-        </span>
-      </div>
+      <InputGroup compact style="margin-bottom: 20px" class="head-sam-group">
+        <Select v-model:value="current" style="width: 30%">
+          <SelectOption :value="tab.key" v-for="tab in tabs" :key="tab.key">{{
+            tab.text
+          }}</SelectOption>
+        </Select>
+        <Input v-model:value="keyword" style="width: 70%" />
+      </InputGroup>
     </template>
-    <Taggings v-if="current === TabKey.tagging" />
-    <Guides v-if="current === TabKey.guide" />
-    <Measures v-if="current === TabKey.measure" />
+    <component :is="comp" v-if="comp" :keyword="keyword" />
   </RightFillPano>
 </template>
 
 <script setup lang="ts">
-import { ref, watchEffect } from "vue";
+import { computed, ref, watchEffect } from "vue";
 import { useViewStack } from "@/hook";
 import { showRightCtrlPanoStack, showRightPanoStack } from "@/env";
 import { currentModel, fuseModel, loadModel } from "@/model";
 import { LeftPano, RightFillPano } from "@/layout";
+import { InputGroup, Select, SelectOption, Input } from "ant-design-vue";
 import SceneList from "@/layout/scene-list/index.vue";
 import Taggings from "@/views/tagging/hot/show.vue";
 import Measures from "@/views/measure/show.vue";
-import Guides from "@/views/guide/show.vue";
+import Guides from "@/views/guide/guide/show.vue";
+import Paths from "@/views/guide/path/show.vue";
+import Monitor from "@/views/tagging/monitor/show.vue";
 
 enum TabKey {
   tagging,
+  monitor,
+  path,
   measure,
   guide,
 }
 const tabs = [
-  { key: TabKey.tagging, text: "标签" },
-  { key: TabKey.measure, text: "测量" },
-  { key: TabKey.guide, text: "路径" },
+  { comp: Taggings, key: TabKey.tagging, text: "标签" },
+  { comp: Monitor, key: TabKey.monitor, text: "监控" },
+  { comp: Paths, key: TabKey.path, text: "路径" },
+  { comp: Measures, key: TabKey.measure, text: "测量" },
+  { comp: Guides, key: TabKey.guide, text: "导览" },
 ];
 const current = ref(tabs[0].key);
+const comp = computed(() => tabs.find((item) => item.key === current.value)?.comp);
 const showRightCtrl = ref(true);
+const keyword = ref("");
 
 watchEffect((onclean) => {
   const isFuse = currentModel.value === fuseModel;
@@ -96,3 +101,13 @@ useViewStack(() => showRightCtrlPanoStack.push(showRightCtrl));
   }
 }
 </style>
+
+<style lang="scss">
+.head-sam-group {
+  .ant-select-selector,
+  .ant-input {
+    background-color: rgba(255, 255, 255, 0.1) !important;
+    border-color: rgba(255, 255, 255, 0.2) !important;
+  }
+}
+</style>

+ 3 - 0
src/views/tagging/hot/show.vue

@@ -31,10 +31,13 @@ import StyleTypeSelect from "./style-type-select.vue";
 
 import type { Tagging, TaggingStyle } from "@/store";
 
+const props = withDefaults(defineProps<{ keyword?: string }>(), { keyword: "" });
+
 const selectTagging = ref<Tagging | null>(null);
 const type = ref<TaggingStyle["typeId"]>(-1);
 const filterTaggings = computed(() =>
   taggings.value.filter((tagging) => {
+    if (!tagging.title.includes(props.keyword)) return false;
     if (type.value === -1) return true;
     const style = getTaggingStyle(tagging.styleId);
     return style?.typeId === type.value;

+ 45 - 0
src/views/tagging/monitor/show.vue

@@ -0,0 +1,45 @@
+<template>
+  <ui-group title="监控列表" class="show-taggings">
+    <template #icon>
+      <ui-icon
+        ctrl
+        :type="custom.showMonitors ? 'eye-s' : 'eye-n'"
+        @click="custom.showMonitors = !custom.showMonitors"
+      />
+    </template>
+    <MonitorSign
+      v-for="monitor in filterMonitors"
+      :key="monitor.id"
+      :monitor="monitor"
+      :selected="selectMonitor === monitor"
+      :edit="false"
+      @select="(selected) => (selectMonitor = selected ? monitor : null)"
+      class="show-tagging"
+    />
+  </ui-group>
+</template>
+
+<script setup lang="ts">
+import { computed, ref } from "vue";
+import { custom } from "@/env";
+import MonitorSign from "./sign.vue";
+import { monitors } from "@/store";
+
+import type { Monitor } from "@/store";
+
+const props = withDefaults(defineProps<{ keyword?: string }>(), { keyword: "" });
+
+const selectMonitor = ref<Monitor | null>(null);
+const filterMonitors = computed(() =>
+  monitors.value.filter((monitor) => monitor.title.includes(props.keyword))
+);
+</script>
+
+<style lang="scss">
+.show-taggings.ui-group > h3.group-title {
+  margin-bottom: 0;
+}
+.show-tagging.sign-tagging.active::after {
+  display: none;
+}
+</style>