| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- <template>
- <div
- v-if="posStyle"
- class="hot-item pc"
- :style="posStyle"
- @mouseenter="isHover = true"
- @mouseleave="isHover = false"
- :class="{ active: showContent }"
- >
- <ui-tip :tip="tagging.title" foreShow tipV="top" class="tag-tip">
- <img
- class="tag-img"
- :src="getResources(getFileUrl(taggingStyle.icon))"
- @click="iconClickHandler"
- v-if="taggingStyle"
- />
- </ui-tip>
- <div @click.stop>
- <UIBubble class="hot-bubble pc" :show="showContent" type="left" level="center">
- <h2>{{ tagging.title }}</h2>
- <ui-audio
- v-if="tagging.audio"
- class="audio"
- :src="getResources(getFileUrl(tagging.audio))"
- ref="audio"
- />
- <div class="content">
- <p><span>{{$t('tagging.tabs.typeId')}}:</span>{{ tagging.desc }}</p>
- <p><span>{{$t('tagging.tabs.part')}}:</span>{{ tagging.part }}</p>
- <p><span>{{$t('tagging.tabs.method')}}:</span>{{ tagging.method }}</p>
- <p><span>{{$t('tagging.tabs.principal')}}:</span>{{ tagging.principal }}</p>
- </div>
- <Images
- :tagging="tagging"
- :in-full="true"
- @pull="(index) => (pullIndex = index)"
- />
- <div
- class="edit-hot"
- v-if="router.currentRoute.value.name === RoutesName.tagging"
- >
- <span @click="$emit('delete')" class="fun-ctrl">
- <ui-icon type="del" />
- {{ $t('sys.del') }}
- </span>
- </div>
- </UIBubble>
- <Preview
- @close="pullIndex = -1"
- :current="pullIndex"
- :items="queryItems"
- v-if="!!~pullIndex"
- />
- </div>
- </div>
- </template>
- <script lang="ts" setup>
- import { computed, ref, watchEffect, watch, onUnmounted } from "vue";
- import { router, RoutesName } from "@/router";
- import UIBubble from "bill/components/bubble/index.vue";
- import Images from "@/views/tagging/images.vue";
- import Preview from "../static-preview/index.vue";
- import { getTaggingStyle, getFuseModel } from "@/store";
- import { getFileUrl, MetaType } from "@/utils";
- import { sdk } from "@/sdk";
- import { custom, getResource, getResources } from "@/env";
- import { useViewStack } from "@/hook";
- import type { Tagging, TaggingPosition } from "@/store";
- export type SignProps = { tagging: Tagging; scenePos: TaggingPosition; show?: boolean };
- defineEmits<{ (e: "delete"): void }>();
- const props = defineProps<SignProps>();
- const posStyle = ref<null | { left: string; top: string }>(null);
- const updatePosStyle = () => {
- const screenPos = sdk.getScreenByPosition(
- props.scenePos.localPos,
- props.scenePos.modelId
- );
- if (!screenPos?.trueSide) {
- posStyle.value = null;
- } else {
- posStyle.value = {
- left: screenPos.pos.x + "px",
- top: screenPos.pos.y + "px",
- };
- }
- };
- useViewStack(() => {
- sdk.sceneBus.on("cameraChange", updatePosStyle);
- return () => {
- sdk.sceneBus.off("cameraChange", updatePosStyle);
- };
- });
- watchEffect(updatePosStyle);
- const model = getFuseModel(props.scenePos.modelId);
- model && watch(model, updatePosStyle, { deep: true });
- const showContent = computed(() => {
- return (
- !~pullIndex.value &&
- (isHover.value || custom.showTaggingPositions.has(props.scenePos))
- );
- });
- const taggingStyle = computed(() => getTaggingStyle(props.tagging.styleId));
- const pullIndex = ref(-1);
- const isHover = ref(false);
- const queryItems = computed(() =>
- props.tagging.images.map((image) => ({
- type: MetaType.image,
- url: getResources(getFileUrl(image)),
- }))
- );
- const iconClickHandler = () => {
- if (custom.showTaggingPositions.has(props.scenePos)) {
- custom.showTaggingPositions.delete(props.scenePos);
- } else {
- custom.showTaggingPositions.add(props.scenePos);
- }
- };
- </script>
- <style lang="scss" scoped>
- .hot-item {
- pointer-events: all;
- position: absolute;
- transform: translate(-50%, -50%);
- cursor: pointer;
- .tag-img {
- width: 32px;
- height: 32px;
- }
- .hot-bubble {
- cursor: initial;
- &.pc {
- width: 400px;
- }
- &:not(.pc) {
- width: 80vw;
- --bottom-left: 40vw;
- }
- h2 {
- font-size: 20px;
- margin-bottom: 10px;
- color: #ffffff;
- position: relative;
- }
- .content {
- font-size: 14px;
- font-family: MicrosoftYaHei;
- color: #999999;
- line-height: 1.35em;
- margin-bottom: 20px;
- word-break: break-all;
- p {
- margin-bottom: 10px;
- }
- }
- }
- &.active,
- &:hover {
- z-index: 3;
- }
- }
- .edit-hot {
- margin-top: 20px;
- text-align: right;
- span {
- font-size: 14px;
- color: rgba(255, 255, 255, 0.6);
- cursor: pointer;
- }
- }
- </style>
- <style>
- .tag-tip {
- z-index: 8 !important;
- }
- .tag-tip p {
- padding: 6px 10px !important;
- margin: 5px 0 !important;
- }
- </style>
|