index.vue 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. <template>
  2. <RightFillPano>
  3. <ui-group :title="`${tagging?.title}放置位置`" class="position-group">
  4. <PositionSign
  5. v-for="(position, i) in positions"
  6. :key="position.id"
  7. :position="position"
  8. :title="`位置${i + 1}`"
  9. @delete="deletePosition(position)"
  10. @fixed="flyTaggingPosition(position)"
  11. />
  12. </ui-group>
  13. </RightFillPano>
  14. </template>
  15. <script lang="ts" setup>
  16. import PositionSign from "./sign.vue";
  17. import { router } from "@/router";
  18. import { Message } from "bill/index";
  19. import { RightFillPano } from "@/layout";
  20. import { asyncTimeout } from "@/utils";
  21. import { useViewStack } from "@/hook";
  22. import { computed, nextTick, ref, watchEffect } from "vue";
  23. import { sdk } from "@/sdk";
  24. import { showTaggingPositionsStack } from "@/env";
  25. import {
  26. autoSaveTaggings,
  27. getFuseModel,
  28. getFuseModelShowVariable,
  29. getTaggingPositions,
  30. taggingPositions,
  31. createTaggingPosition,
  32. getTagging,
  33. enterEdit,
  34. } from "@/store";
  35. import type { TaggingPosition } from "@/store";
  36. import { distance } from "@/utils/math";
  37. const tagging = computed(() => getTagging(router.currentRoute.value.params.id as string));
  38. const positions = computed(() => tagging.value && getTaggingPositions(tagging.value));
  39. const flyTaggingPosition = (position: TaggingPosition) => {
  40. const model = getFuseModel(position.modelId);
  41. if (!model || !getFuseModelShowVariable(model).value) {
  42. return;
  43. }
  44. const pop = showTaggingPositionsStack.push(ref(new WeakSet([position])));
  45. sdk.comeTo({
  46. position: position.localPos,
  47. modelId: position.modelId,
  48. dur: 300,
  49. distance: 3,
  50. });
  51. setTimeout(pop, 2000);
  52. };
  53. const deletePosition = (position: TaggingPosition) => {
  54. const index = taggingPositions.value.indexOf(position);
  55. if (~index) {
  56. taggingPositions.value.splice(index, 1);
  57. }
  58. };
  59. const cameraPos = ref<SceneLocalPos>();
  60. sdk.sceneBus.on("cameraChange", (pos) => (cameraPos.value = pos));
  61. watchEffect((onCleanup) => {
  62. if (tagging.value) {
  63. const clickHandler = async (ev: MouseEvent) => {
  64. await nextTick();
  65. await asyncTimeout();
  66. const position = sdk.getPositionByScreen({
  67. x: ev.clientX,
  68. y: ev.clientY,
  69. });
  70. if (!position) {
  71. Message.error("当前位置无法添加");
  72. } else {
  73. const storePosition = createTaggingPosition({
  74. ...position,
  75. taggingId: tagging.value!.id,
  76. });
  77. taggingPositions.value.push(storePosition);
  78. if (cameraPos.value && distance(cameraPos.value, position.worldPos) > 8) {
  79. flyTaggingPosition(storePosition);
  80. }
  81. }
  82. };
  83. sdk.layout.addEventListener("click", clickHandler, false);
  84. onCleanup(() => {
  85. sdk.layout.removeEventListener("click", clickHandler, false);
  86. });
  87. }
  88. });
  89. useViewStack(autoSaveTaggings);
  90. useViewStack(() => {
  91. const hide = Message.show({ msg: "请在模型上单击选择标签位置", type: "warning" });
  92. enterEdit(() => router.back());
  93. return hide;
  94. });
  95. </script>
  96. <style lang="scss" scoped src="./style.scss"></style>
  97. <style lang="scss">
  98. .position-group .group-title {
  99. margin-bottom: 0;
  100. }
  101. </style>