sceneInGroupInEditor.vue 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. <template>
  2. <div class="scene-item" :class="isConfirmingDeletion ? '' : 'not-confirming-deletion'" @dragstart="onDragStart" @dragend="clearDragInfo" draggable="true">
  3. <div class="drag-image" ref="drag-image">
  4. <img :src="sceneInfo.icon + ossImagePreviewUrlSuffix()" alt="" class="scene-image" draggable="false" />
  5. </div>
  6. <img :src="sceneInfo.icon + ossImagePreviewUrlSuffix()" alt="" class="scene-image" draggable="false" />
  7. <div class="right">
  8. <span v-if="!isRenaming" class="scene-title" v-title="sceneInfo.name">{{ sceneInfo.name }}</span>
  9. <input
  10. v-if="isRenaming"
  11. class="scene-title-input"
  12. v-model.trim="newName"
  13. ref="input-for-rename"
  14. maxlength="50"
  15. :placeholder="$i18n.t('navigation.enter_name')"
  16. @blur="onInputNewNameComplete"
  17. @keydown.enter="onInputEnter"
  18. />
  19. <div class="right-bottom">
  20. <span class="scene-type">{{ translateSceneType(sceneInfo.type) }}</span>
  21. <div class="icons">
  22. <i class="iconfont icon-editor_list_edit icon-edit" v-tooltip="$i18n.t('navigation.rename')" @click="onRequestForRename"> </i>
  23. <i class="iconfont icon-editor_list_delete icon-delete" v-tooltip="$i18n.t('navigation.delete')" @click="onRequestForDelete"> </i>
  24. </div>
  25. </div>
  26. </div>
  27. <div class="deletion-confirm-wrap">
  28. <div class="deletion-confirm" :class="isConfirmingDeletion ? 'show' : 'hide'" v-clickoutside="onRequestForCancelDelete" @click="onConfirmDelete">
  29. {{ $i18n.t("navigation.delete") }}
  30. </div>
  31. </div>
  32. </div>
  33. </template>
  34. <script>
  35. import { ossImagePreviewUrlSuffix } from "@/utils/other.js";
  36. import { mapMutations } from "vuex";
  37. import { i18n } from "@/lang";
  38. export default {
  39. name: "SceneInGroupInEditor",
  40. components: {},
  41. props: {
  42. sceneInfo: {
  43. type: Object,
  44. require: true,
  45. },
  46. },
  47. data() {
  48. return {
  49. isRenaming: false,
  50. newName: "",
  51. isConfirmingDeletion: false,
  52. };
  53. },
  54. computed: {},
  55. methods: {
  56. ...mapMutations({
  57. recordDragType: "setEditorNavDragType",
  58. recordDragNode: "setEditorNavDragNode",
  59. clearDragInfo: "clearEditorNavDragInfo",
  60. }),
  61. onDragStart(e) {
  62. console.error(this.sceneInfo);
  63. this.recordDragType("scene");
  64. this.recordDragNode(this.sceneInfo);
  65. e.dataTransfer.setDragImage(this.$refs["drag-image"], -10, -18);
  66. },
  67. ossImagePreviewUrlSuffix,
  68. translateSceneType(type) {
  69. if (type === "pano") {
  70. return this.$i18n.t("navigation.pano");
  71. } else {
  72. return this.$i18n.t("navigation.scene");
  73. }
  74. },
  75. onRequestForRename() {
  76. this.isRenaming = true;
  77. this.newName = this.sceneInfo.name;
  78. this.$nextTick(() => {
  79. this.$refs["input-for-rename"].focus();
  80. });
  81. },
  82. onInputNewNameComplete() {
  83. this.isRenaming = false;
  84. if (String(this.newName).trim().length === 0 || String(this.newName).trim().length > 50) {
  85. this.$msg.warning(this.$i18n.t("hotspot.title_placeholder"));
  86. return;
  87. }
  88. this.$emit("rename", this.sceneInfo.id, this.newName);
  89. setTimeout(() => {
  90. this.newName = "";
  91. }, 100);
  92. },
  93. onInputEnter() {
  94. this.isRenaming = false; // 会导致input blur,进而触发onInputNewNameComplete
  95. },
  96. onRequestForDelete() {
  97. this.isConfirmingDeletion = true;
  98. },
  99. onRequestForCancelDelete() {
  100. this.isConfirmingDeletion = false;
  101. },
  102. onConfirmDelete() {
  103. this.$emit("delete", this.sceneInfo.id);
  104. this.isConfirmingDeletion = false;
  105. },
  106. },
  107. };
  108. </script>
  109. <style lang="less" scoped>
  110. .scene-item {
  111. position: relative;
  112. margin-left: -12px;
  113. margin-right: -10px;
  114. padding-right: 10px;
  115. padding-top: 10px;
  116. padding-bottom: 10px;
  117. display: flex;
  118. border-radius: 4px;
  119. &:hover {
  120. background: #313131;
  121. }
  122. &.not-confirming-deletion:hover {
  123. .icons {
  124. display: block !important;
  125. }
  126. }
  127. .drag-image {
  128. width: 40px;
  129. height: 40px;
  130. border-radius: 4px;
  131. padding: 4px;
  132. background: #313131;
  133. box-shadow: 0px 0px 4px 0px rgba(0, 0, 0, 0.5);
  134. position: absolute;
  135. z-index: -1;
  136. img {
  137. width: 100%;
  138. height: 100%;
  139. object-fit: cover;
  140. border-radius: 2px;
  141. }
  142. }
  143. .scene-image {
  144. flex: 0 0 auto;
  145. width: 64px;
  146. height: 64px;
  147. background: #b0b0b0;
  148. border-radius: 2px;
  149. object-fit: cover;
  150. }
  151. .right {
  152. margin-left: 10px;
  153. width: 0px;
  154. flex: 1 1 auto;
  155. display: flex;
  156. flex-direction: column;
  157. justify-content: space-between;
  158. .scene-title {
  159. word-break: break-all;
  160. display: -webkit-box;
  161. -webkit-box-orient: vertical;
  162. -webkit-line-clamp: 2;
  163. overflow: hidden;
  164. font-size: 14px;
  165. color: rgba(255, 255, 255, 0.6);
  166. }
  167. .scene-title-input {
  168. height: 30px;
  169. background: #1a1b1d;
  170. border-radius: 2px;
  171. border: 1px solid #404040;
  172. color: #fff;
  173. font-size: 14px;
  174. padding: 0 10px 0 16px;
  175. &:focus {
  176. border-color: #0076f6;
  177. }
  178. }
  179. .right-bottom {
  180. display: flex;
  181. justify-content: space-between;
  182. align-items: flex-end;
  183. .scene-type {
  184. color: #0076f6;
  185. line-height: 16px;
  186. }
  187. .icons {
  188. display: none;
  189. i {
  190. font-size: 16px;
  191. cursor: pointer;
  192. color: rgba(255, 255, 255, 0.6);
  193. }
  194. .icon-edit {
  195. &:hover {
  196. color: #0076f6;
  197. }
  198. }
  199. .icon-delete {
  200. margin-left: 11px;
  201. &:hover {
  202. color: #fa5555;
  203. }
  204. }
  205. }
  206. }
  207. }
  208. .deletion-confirm-wrap {
  209. position: absolute;
  210. top: 0;
  211. bottom: 0;
  212. right: 0;
  213. width: 44px;
  214. overflow: hidden;
  215. pointer-events: none;
  216. border-top-right-radius: 4px;
  217. border-bottom-right-radius: 4px;
  218. > .deletion-confirm {
  219. position: absolute;
  220. top: 0;
  221. bottom: 0;
  222. width: 100%;
  223. background: #fa5555;
  224. transition: right 0.3s;
  225. cursor: pointer;
  226. text-align: center;
  227. font-size: 12px;
  228. color: #fff;
  229. pointer-events: auto;
  230. &::after {
  231. content: "";
  232. height: 100%;
  233. vertical-align: middle;
  234. display: inline-block;
  235. }
  236. &.show {
  237. right: 0;
  238. }
  239. &.hide {
  240. right: -44px;
  241. }
  242. }
  243. }
  244. }
  245. </style>