select-back.vue 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. <template>
  2. <div class="back-layout">
  3. <template v-for="back in backs" :key="back.value">
  4. <div v-if="back.children" class="child-layout-parent">
  5. <Dropdown placement="bottom">
  6. <div class="child-layout" :class="{ active: activeParent === back.value }">
  7. <ui-icon type="menu" />
  8. <BackItem
  9. :type="back.type"
  10. :label="back.label"
  11. :url="back.image"
  12. :active="activeParent === back.value"
  13. />
  14. </div>
  15. <template #overlay>
  16. <Menu
  17. :selectedKeys="[value]"
  18. :default-active="value[1]?.toString()"
  19. active-text-color="#ffd04b"
  20. >
  21. <MenuItem
  22. v-for="item in back.children"
  23. @click="
  24. value[1] !== item.value && $emit('update:value', [null, item.value])
  25. "
  26. :index="item.value.toString()"
  27. >
  28. <span
  29. :style="{
  30. color:
  31. value[1] === item.value ? 'var(--colors-primary-base) ' : '#fff',
  32. }"
  33. >{{ item.label }}</span
  34. >
  35. </MenuItem>
  36. </Menu>
  37. </template>
  38. </Dropdown>
  39. </div>
  40. <BackItem
  41. v-else
  42. :type="back.type"
  43. :label="back.label"
  44. :url="back.image"
  45. :active="value[0] === back.value"
  46. @click="value[0] !== back.value && $emit('update:value', [back.value, null])"
  47. />
  48. </template>
  49. </div>
  50. </template>
  51. <script lang="ts" setup>
  52. import { Dropdown, MenuItem, Menu } from "ant-design-vue";
  53. import { computed, ref } from "vue";
  54. import BackItem from "./back-item.vue";
  55. import { fetchMapTiles } from "@/api/map-tile";
  56. import { sysTiles } from "@/store";
  57. const props = defineProps<{
  58. value: [string | null | undefined, number | null | undefined];
  59. }>();
  60. defineEmits<{
  61. (e: "update:value", value: [string | null, number | null]): void;
  62. }>();
  63. const backs = computed(() => [
  64. { label: "无", type: "icon", image: "icon-without", value: "none" },
  65. {
  66. label: "地图",
  67. type: "map",
  68. image: "https://4dkk.4dage.com/fusion/default/images/map.png",
  69. value: "dt",
  70. children: sysTiles.value.map((t) => ({ label: t.name, value: t.id })),
  71. },
  72. {
  73. label: "蓝天白云",
  74. type: "img",
  75. image: "https://4dkk.4dage.com/fusion/default/images/pic_ltby@2x.png",
  76. value: "https://4dkk.4dage.com/fusion/default/images/蓝天白云.jpg",
  77. },
  78. {
  79. label: "乌云密布",
  80. type: "img",
  81. image: "https://4dkk.4dage.com/fusion/default/images/pic_wymb@2x.png",
  82. value: "https://4dkk.4dage.com/fusion/default/images/乌云密布.jpg",
  83. },
  84. {
  85. label: "夜空",
  86. type: "img",
  87. image: "https://4dkk.4dage.com/fusion/default/images/pic_yk@2x.png",
  88. value: "https://4dkk.4dage.com/fusion/default/images/夜空.jpg",
  89. },
  90. {
  91. label: "傍晚",
  92. type: "img",
  93. image: "https://4dkk.4dage.com/fusion/default/images/pic_bw@2x.png",
  94. value: "https://4dkk.4dage.com/fusion/default/images/傍晚.jpg",
  95. },
  96. ]);
  97. const activeParent = computed(() => {
  98. for (const back of backs.value) {
  99. if (back.value === props.value[0]) {
  100. return back.value;
  101. } else if (back.children) {
  102. for (const c of back.children) {
  103. if (c.value === props.value[1]) {
  104. return back.value;
  105. }
  106. }
  107. }
  108. }
  109. });
  110. </script>
  111. <style lang="scss" scoped>
  112. .back-layout {
  113. display: grid;
  114. grid-template-columns: repeat(3, 1fr);
  115. gap: 20px;
  116. }
  117. .child-layout-parent {
  118. position: relative;
  119. }
  120. .child-layout {
  121. position: absolute;
  122. top: 0;
  123. left: 0;
  124. height: 88px;
  125. > .icon {
  126. position: absolute;
  127. font-size: 22px;
  128. left: 50%;
  129. top: 50%;
  130. transform: translate(-50%, -50%);
  131. z-index: 2;
  132. }
  133. &::after {
  134. content: "";
  135. position: absolute;
  136. z-index: 1;
  137. background: rgba(0, 0, 0, 0.5);
  138. inset: 0;
  139. border-radius: 4px;
  140. cursor: pointer;
  141. }
  142. &.active::after {
  143. inset: 0px;
  144. }
  145. }
  146. </style>