pane.vue 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. <template>
  2. <ActionMenus
  3. v-if="!store.child.value"
  4. class="menus"
  5. :class="{ level: level === 2 }"
  6. :menus="store.menus as any"
  7. :active-key="store.activeMenuKey.value"
  8. dire="column"
  9. />
  10. <scene-menus
  11. :parentKey="store.activeMenuKey.value"
  12. v-if="store.child.value"
  13. @back="store.child.value = null"
  14. :menus="store.child.value as MenuRaw[]"
  15. :level="level + 1"
  16. />
  17. </template>
  18. <script lang="ts" setup>
  19. import ActionMenus from "@/components/group-button/index.vue";
  20. import { generateMixMenus, MenuRaw, menus, findMenuByKey } from "./menus";
  21. import { joinActions } from "./actions";
  22. import { computed, onMounted, onUnmounted, ref, watchEffect } from "vue";
  23. import { disabledMap, laserModeStack } from "@/hook";
  24. import { Mode } from "@/sdk";
  25. const props = withDefaults(
  26. defineProps<{ menus?: MenuRaw[]; level?: number; parentKey?: string }>(),
  27. { level: 1 }
  28. );
  29. const emit = defineEmits<{
  30. (e: "back"): void;
  31. (e: "enterChild"): void;
  32. (e: "leaveChild"): void;
  33. }>();
  34. const backMenu = {
  35. icon: "return",
  36. text: "",
  37. key: "back",
  38. onClick: () => emit("back"),
  39. };
  40. const menusMix = computed(() => (props.level === 1 ? menus : [backMenu, ...props.menus]));
  41. const store = generateMixMenus("children", (m) => m, menusMix.value);
  42. watchEffect(() => {
  43. const menu = findMenuByKey(store.itemActiveKey.value as any);
  44. if (menu?.disabled && menu?.disabled()) {
  45. store.itemActiveKey.value = null;
  46. }
  47. });
  48. watchEffect((onCleanup) => {
  49. const menu = store.activeMenuKey.value && findMenuByKey(store.activeMenuKey.value);
  50. if (store.child && menu?.onClick) {
  51. const leaveHook = menu.onClick();
  52. leaveHook && onCleanup(leaveHook);
  53. } else {
  54. onCleanup(() => {});
  55. }
  56. });
  57. if (props.level === 1) {
  58. watchEffect(() => {
  59. disabledMap.photo = !store.child.value?.length;
  60. });
  61. watchEffect(() => {
  62. if (store.child.value) {
  63. emit("enterChild");
  64. } else {
  65. emit("leaveChild");
  66. }
  67. });
  68. }
  69. const stopWatch = joinActions(store.itemActiveKey);
  70. onUnmounted(() => {
  71. stopWatch();
  72. if (props.parentKey === "measure") {
  73. laserModeStack.pop();
  74. }
  75. });
  76. onMounted(() => {
  77. if (props.level > 1) {
  78. const defaultMenu = props.menus.find((menu) => {
  79. if (typeof menu.defaultSelect === "function") {
  80. return menu.defaultSelect();
  81. } else {
  82. return menu.defaultSelect;
  83. }
  84. });
  85. store.itemActiveKey.value = defaultMenu?.key;
  86. // store.activeMenuKey.value =
  87. if (props.parentKey === "measure") {
  88. laserModeStack.push(ref(Mode.cloud));
  89. }
  90. }
  91. });
  92. </script>
  93. <script lang="ts">
  94. export default { name: "scene-menus" };
  95. </script>
  96. <style lang="scss" scoped>
  97. .menus {
  98. position: absolute;
  99. left: var(--boundMargin);
  100. top: 50%;
  101. transform: translateY(-50%);
  102. z-index: 2;
  103. }
  104. </style>
  105. <style lang="scss">
  106. .level div:first-child {
  107. background-color: rgba(255, 255, 255, 0.3);
  108. height: 50px;
  109. width: 50px;
  110. min-width: 50px;
  111. border-radius: 50%;
  112. margin-bottom: 30px !important;
  113. position: relative;
  114. i {
  115. font-size: 16px !important;
  116. }
  117. &:after {
  118. position: absolute;
  119. content: "";
  120. height: 1px;
  121. left: 10px;
  122. right: 10px;
  123. bottom: -15px;
  124. background-color: rgba(255, 255, 255, 0.2);
  125. }
  126. }
  127. </style>