HotSpotList.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. <template>
  2. <div class="hot-spot-list" app-border dir-left>
  3. <div class="title">
  4. {{ $i18n.t("hotspot.add_hotspot") }}
  5. <i class="iconfont icon-help_i tool-tip-for-editor" v-tooltip="$i18n.t('hotspot.hotspot_tips')" />
  6. </div>
  7. <template v-if="currentScene.type !== '4dkk'">
  8. <ul class="hotspot-type-list">
  9. <li
  10. class="hotspot-type-item"
  11. v-for="(item, index) in hotspotTypeList"
  12. :key="index"
  13. @click="
  14. open({
  15. isAdd: true,
  16. hotspotType: item.id,
  17. idxInSystemIconList: item.idxInSystemIconList,
  18. })
  19. "
  20. >
  21. <img class="icon" :src="item.icon" alt="" draggable="false" />
  22. <div class="type-name">{{ item.name }}</div>
  23. <img v-if="item.isExperience" class="exp-tag" :src="experience_icon" alt="" draggable="false" />
  24. </li>
  25. </ul>
  26. <div class="total-count">
  27. {{ $i18n.t("hotspot.current_hotspots") }}
  28. <span class="number">({{ someData.hotspots.length }})</span>
  29. </div>
  30. <div class="hots">
  31. <ul v-if="someData.hotspots.length > 0">
  32. <li v-for="(item, key) in someData.hotspots" :key="key" @click="open(item)">
  33. <img class="hot-spot-thumb" :src="item.img" alt="" />
  34. <span class="hot-spot-title" v-title="item.hotspotTitle">{{ item.hotspotTitle }}</span>
  35. <i class="iconfont icon-editor_list_delete icon-delete" v-tooltip="$i18n.t('hotspot.delete')" @click.stop="deleIndex = key" />
  36. <div class="deletion-confirm-wrap">
  37. <div class="deletion-confirm" :class="deleIndex == key ? 'show' : 'hide'" v-clickoutside="clickoutside" @click.stop="deleteHot(item)">
  38. {{ $i18n.t("hotspot.delete") }}
  39. </div>
  40. </div>
  41. </li>
  42. </ul>
  43. <div v-else class="empty-tip">
  44. <img src="@/assets/images/default/empty_hotspot_list.png" alt="" />
  45. <div>{{ $i18n.t("hotspot.no_hotspot") }}</div>
  46. </div>
  47. </div>
  48. </template>
  49. <div class="goto-4dkk-tip" v-if="currentScene.type === '4dkk'">
  50. <div class="img-wrap">
  51. <img class="" src="@/assets/images/default/goto-4dage.png" alt="" draggable="false" />
  52. <div class="tip-text">
  53. {{ $i18n.t("screen.goto_4dkk_edit_tips") }}
  54. </div>
  55. </div>
  56. <button class="ui-button submit" @click="onClickGo4dkk">
  57. {{ $i18n.t("navigation.go_scene_editor") }}
  58. </button>
  59. </div>
  60. <EditPanel class="adding-hotspot-panel" v-if="showPanel" :editTitle="editTitle" :show="showPanel" @save="save" @close="close" />
  61. </div>
  62. </template>
  63. <script>
  64. import EditPanel from "./EditPanel";
  65. import { mapGetters } from "vuex";
  66. import browser from "@/utils/browser";
  67. import hotspotTypeList from "./hotspotTypeList.js";
  68. let mapFontSize = {
  69. 12: 0.5,
  70. 17: 1.5,
  71. 20: 2,
  72. };
  73. export default {
  74. name: "HotSpotList",
  75. components: {
  76. EditPanel,
  77. },
  78. data() {
  79. return {
  80. hotspotTypeList,
  81. showPanel: false,
  82. someData: { hotspots: [] },
  83. deleIndex: -1,
  84. editTitle: "",
  85. };
  86. },
  87. computed: {
  88. ...mapGetters({
  89. currentScene: "scene/currentScene",
  90. hotspot: "hotspot",
  91. info: "info",
  92. }),
  93. experience_icon() {
  94. const lang = browser.urlQueryValue("lang");
  95. if (lang == "en") {
  96. return require("@/assets/img/experience_en.png");
  97. } else {
  98. return require("@/assets/img/experience_zh.png");
  99. }
  100. },
  101. },
  102. watch: {
  103. "$route.name": function () {
  104. this.showPanel = false;
  105. },
  106. currentScene: {
  107. immediate: true,
  108. handler: function (newVal) {
  109. this.someData = newVal.someData || "";
  110. if (this.someData) {
  111. if (typeof this.someData == "string") {
  112. try {
  113. this.someData = JSON.parse(this.someData);
  114. } catch (e) {
  115. console.error(e);
  116. return false;
  117. }
  118. }
  119. if (!this.someData.hotspots) {
  120. this.someData.hotspots = [];
  121. }
  122. } else {
  123. this.someData = { hotspots: [] };
  124. }
  125. },
  126. },
  127. showPanel(newVal) {
  128. this.$store.commit("UpdateIsEditingState", newVal);
  129. this.$store.commit("tags/setIsConfirmingPosi", false);
  130. },
  131. },
  132. mounted() {
  133. this.$bus.on("updateHotSpotHV", (data) => {
  134. let hptarget = this.someData.hotspots.find((item) => item.name.toLowerCase() == data.hpname.toLowerCase());
  135. if (hptarget) {
  136. console.log("hptarget", hptarget);
  137. hptarget.ath = data.ath;
  138. hptarget.atv = data.atv;
  139. }
  140. });
  141. this.$bus.on("openHotspot", (data) => {
  142. let idx = this.someData.hotspots.findIndex((item) => item.name.toLowerCase() == data.toLowerCase());
  143. // console.log(data);
  144. if (data == this.hotspot.name) {
  145. // window.__krfn.utils.looktohotspot(this.$getKrpano(), this.hotspot.name);
  146. if (!this.showPanel) {
  147. this.open(this.someData.hotspots[idx]);
  148. }
  149. return;
  150. }
  151. if (this.editTitle == "新增" || this.editTitle == this.$i18n.t("hotspot.add")) {
  152. if (this.showPanel) {
  153. return this.$confirm({
  154. content: this.$i18n.t("hotspot.close_dialog"),
  155. ok: () => {
  156. this.deleteKRHotspot(this.hotspot);
  157. this.showPanel = false;
  158. },
  159. });
  160. }
  161. }
  162. this.open(this.someData.hotspots[idx]);
  163. });
  164. },
  165. methods: {
  166. deleteKRHotspot(data) {
  167. this.$getKrpano().call("removeJQHotspot(" + data.name + ");");
  168. // this.$getKrpano().call(
  169. // "removeplugin(" + ("tooltip_" + data.name) + ",true);"
  170. // );
  171. },
  172. close(data) {
  173. if (data) {
  174. if (data.type == "edit") {
  175. this.deleteKRHotspot(data.data);
  176. this.$bus.emit("addhotspot", data.data);
  177. let idx = this.someData.hotspots.findIndex((item) => item.name == data.data.name);
  178. this.someData.hotspots[idx] = data.data;
  179. } else {
  180. this.deleteKRHotspot(data.data);
  181. }
  182. }
  183. this.showPanel = false;
  184. },
  185. updateInfo() {
  186. let iidx = this.info.scenes.findIndex((item) => this.currentScene.sceneCode == item.sceneCode);
  187. if (iidx > -1) {
  188. this.info.scenes[iidx] = {
  189. ...this.currentScene,
  190. };
  191. }
  192. this.$store.commit("SetInfo", this.info);
  193. },
  194. save(data) {
  195. let HV = window.__krfn.utils.getHotspotHV(this.$getKrpano(), data.name);
  196. data.ath = HV.ath;
  197. data.atv = HV.atv;
  198. let idx = this.someData.hotspots.findIndex((item) => item.name === data.name);
  199. if (idx <= -1) {
  200. this.someData.hotspots.push(data);
  201. } else {
  202. this.someData.hotspots[idx] = data;
  203. }
  204. this.currentScene.someData = this.someData;
  205. this.$msg.success(this.editTitle + this.$i18n.t("hotspot.success"));
  206. // window.g_hotspotCurrentScale = mapFontSize[data.fontSize] || 1;
  207. window.g_hotspotCurrentScale = Math.ceil((data.fontSize * 10) / 12) / 10 || 1;
  208. console.log("g_hotspotCurrentScale", g_hotspotCurrentScale);
  209. let iidx = this.info.scenes.findIndex((item) => this.currentScene.sceneCode == item.sceneCode);
  210. if (iidx > -1) {
  211. this.info.scenes[iidx] = {
  212. ...this.currentScene,
  213. };
  214. }
  215. this.updateInfo();
  216. },
  217. deleteHot(data) {
  218. this.someData.hotspots.splice(
  219. this.someData.hotspots.findIndex((item) => item.name === data.name),
  220. 1
  221. );
  222. this.deleteKRHotspot(data);
  223. this.currentScene.someData = this.someData;
  224. this.updateInfo();
  225. this.$msg.success(this.$i18n.t("hotspot.delete") + this.$i18n.t("hotspot.success"));
  226. },
  227. open(data) {
  228. let hotspotData = null;
  229. if (data.isAdd) {
  230. console.error(this.currentScene);
  231. this.editTitle = this.$i18n.t("hotspot.add");
  232. hotspotData = {
  233. hotspotType: data.hotspotType, // 热点类型,切换场景、图片、视频、音频、链接、文本等等
  234. navigationId: this.currentScene.id,
  235. hotspotIconType: "system_icon", // 热点图标的类型,系统图标(system_icon)、自定义图片(custom_image)、序列帧(serial_frame)、个性标签(personalized_tag)
  236. img: this.$config.getStaticResource("/panoassets/images/hotspot/icon/") + `img_doticon_${String(data.idxInSystemIconList).padStart(2, "0")}.svg`, // 热点图标类型为系统图标时,图标在展时段使用的url
  237. icontype: "icon" + data.idxInSystemIconList, // 热点图标类型为系统图标时,图标的id
  238. customIconInfo: {
  239. // 热点图标类型为自定义图标时,图标的数据
  240. img: "",
  241. },
  242. serialFrameInfo: {
  243. // 热点图标类型为序列帧时,序列帧的数据
  244. img: "",
  245. frameNumber: 0, // 总帧数
  246. duration: 0, // 总播放时长(秒)
  247. },
  248. personalizedTagInfo: {
  249. // 热点图标类型为个性标签时,个性标签的数据
  250. isShowLine: true,
  251. lineDirection: "left-top",
  252. fillColor: "rgba(0, 0, 0, 0.5)",
  253. borderColor: "rgba(255, 255, 255, 0.8)",
  254. textColor: "rgba(255, 255, 255, 1)",
  255. textDirection: "left-right",
  256. isTextWrap: false,
  257. textNumPerLine: 10,
  258. },
  259. name: "_" + this.$randomWord(true, 8, 8),
  260. hotspotTitle: this.$i18n.t("hotspot.click_to_comfirm"),
  261. fontSize: 12,
  262. type: "",
  263. link: "",
  264. titleDisplayMode: "always", // 'always' | 'never' | 'hover' 标题显示方式
  265. titlePosition: "top", // 'top' | 'bottom' | 'left' | 'right' | 'custom' 标题相对图标位置
  266. ath: "",
  267. atv: "",
  268. size: 1,
  269. secne: null,
  270. hyperlink: "",
  271. textarea: "",
  272. image: [], // 热点类型为图片时,图片列表
  273. audio: "",
  274. video: "",
  275. imageTextInfo: {
  276. // 热点类型为图文时,图文内容
  277. imageList: [],
  278. text: "",
  279. isApplyToAll: true,
  280. audio: {},
  281. },
  282. phoneInfo: {
  283. // 热点类型为电话时,对应数据
  284. phone: "",
  285. },
  286. pdfInfo: {
  287. // 热点类型为pdf时,对应数据
  288. name: "",
  289. url: "",
  290. },
  291. articleInfo: {
  292. html: "",
  293. },
  294. };
  295. this.$bus.emit("addhotspot", hotspotData);
  296. this.$getKrpano().set("layer[tooltip_" + hotspotData.name + "].visible", true);
  297. // debugger;
  298. setTimeout(() => {
  299. this.$store.commit("tags/setIsConfirmingPosi", hotspotData.name);
  300. }, 0);
  301. console.log("hotspotData", hotspotData);
  302. } else {
  303. hotspotData = browser.CloneObject(data);
  304. /**
  305. * v1.3新增
  306. */
  307. if (!hotspotData.hotspotIconType) {
  308. hotspotData.hotspotIconType = "system_icon";
  309. }
  310. if (!hotspotData.customIconInfo) {
  311. hotspotData.customIconInfo = {
  312. img: "",
  313. };
  314. }
  315. if (!hotspotData.serialFrameInfo) {
  316. hotspotData.serialFrameInfo = {
  317. url: "",
  318. frameNumber: 0,
  319. duration: 0,
  320. };
  321. }
  322. if (!hotspotData.personalizedTagInfo) {
  323. hotspotData.personalizedTagInfo = {
  324. isShowLine: true,
  325. lineDirection: "left-top",
  326. fillColor: "rgba(0, 0, 0, 0.5)",
  327. borderColor: "rgba(255, 255, 255, 0.8)",
  328. textColor: "rgba(255, 255, 255, 1)",
  329. textDirection: "left-right",
  330. isTextWrap: false,
  331. textNumPerLine: 10,
  332. };
  333. }
  334. // v1.3把visible: Boolean换成了titleDisplayMode
  335. if (hotspotData.visible) {
  336. hotspotData.titleDisplayMode = "always";
  337. } else if (hotspotData.visible === false) {
  338. hotspotData.titleDisplayMode = "never";
  339. }
  340. if (!hotspotData.titlePosition) {
  341. hotspotData.titlePosition = "top";
  342. }
  343. if (!hotspotData.imageTextInfo) {
  344. hotspotData.imageTextInfo = {
  345. imageList: [],
  346. text: "",
  347. isApplyToAll: true,
  348. audio: {},
  349. };
  350. }
  351. if (!hotspotData.phoneInfo) {
  352. hotspotData.phoneInfo = {
  353. phone: "",
  354. };
  355. }
  356. if (!hotspotData.pdfInfo) {
  357. hotspotData.pdfInfo = {
  358. name: "",
  359. url: "",
  360. };
  361. }
  362. if (!hotspotData.articleInfo) {
  363. hotspotData.articleInfo = {
  364. html: "",
  365. };
  366. }
  367. /**
  368. * end of v1.3新增
  369. */
  370. }
  371. this.$store.commit("SetHotspot", hotspotData);
  372. this.showPanel = true;
  373. if (!data.isAdd) {
  374. this.editTitle = this.$i18n.t("hotspot.edit");
  375. window.__krfn.utils.looktohotspot(this.$getKrpano(), data.name);
  376. }
  377. },
  378. clickoutside() {
  379. if (this.deleIndex > -1) {
  380. this.deleIndex = -1;
  381. }
  382. },
  383. onClickGo4dkk() {
  384. window.open("/#/scene");
  385. },
  386. },
  387. };
  388. </script>
  389. <style lang="less" scoped>
  390. .hot-spot-list {
  391. padding: 20px;
  392. display: flex;
  393. flex-direction: column;
  394. background: #252526;
  395. position: relative;
  396. > .title {
  397. flex: 0 0 auto;
  398. font-size: 18px;
  399. color: #fff;
  400. flex: 0 0 auto;
  401. margin-bottom: 24px;
  402. > i {
  403. font-size: 12px;
  404. position: relative;
  405. top: -2px;
  406. }
  407. }
  408. > .hotspot-type-list {
  409. flex: 0 0 auto;
  410. margin-right: -10px;
  411. > .hotspot-type-item {
  412. position: relative;
  413. display: inline-flex;
  414. flex-direction: column;
  415. justify-content: center;
  416. align-items: center;
  417. width: 72px;
  418. height: 72px;
  419. background: #313131;
  420. border-radius: 2px;
  421. border: 1px solid #404040;
  422. margin-right: 9px;
  423. margin-bottom: 9px;
  424. cursor: pointer;
  425. > .icon {
  426. width: 28px;
  427. height: 28px;
  428. margin-bottom: 3px;
  429. }
  430. > .type-name {
  431. font-size: 12px;
  432. color: #ffffff;
  433. }
  434. > .exp-tag {
  435. position: absolute;
  436. top: 0;
  437. right: 0;
  438. width: 30px;
  439. height: 30px;
  440. }
  441. }
  442. }
  443. .total-count {
  444. flex: 0 0 auto;
  445. margin-top: 24px;
  446. font-size: 18px;
  447. color: #ffffff;
  448. .number {
  449. font-size: 14px;
  450. color: rgba(255, 255, 255, 0.6);
  451. position: relative;
  452. top: -1px;
  453. }
  454. }
  455. .hots {
  456. flex: 1 0 1px;
  457. margin-top: 16px;
  458. background: available;
  459. background: #1a1b1d;
  460. border-radius: 4px;
  461. border: 1px solid #404040;
  462. position: relative;
  463. overflow: auto;
  464. ul {
  465. padding: 10px;
  466. li {
  467. position: relative;
  468. height: 40px;
  469. border-radius: 2px;
  470. display: flex;
  471. align-items: center;
  472. padding: 0 5px 0 10px;
  473. &:hover {
  474. background: #252526;
  475. .icon-delete {
  476. display: block;
  477. }
  478. }
  479. > .hot-spot-thumb {
  480. width: 18px;
  481. }
  482. > .hot-spot-title {
  483. flex: 1 1 auto;
  484. margin-left: 10px;
  485. text-overflow: ellipsis;
  486. overflow: hidden;
  487. white-space: nowrap;
  488. }
  489. > .icon-delete {
  490. margin-left: 12px;
  491. display: none;
  492. cursor: pointer;
  493. padding: 5px;
  494. &:hover {
  495. color: #fa5555;
  496. }
  497. }
  498. > .deletion-confirm-wrap {
  499. position: absolute;
  500. top: 0;
  501. bottom: 0;
  502. right: 0;
  503. width: 44px;
  504. overflow: hidden;
  505. pointer-events: none;
  506. border-top-right-radius: 2px;
  507. border-bottom-right-radius: 2px;
  508. > .deletion-confirm {
  509. position: absolute;
  510. top: 0;
  511. bottom: 0;
  512. width: 100%;
  513. background: #fa5555;
  514. transition: right 0.3s;
  515. cursor: pointer;
  516. text-align: center;
  517. font-size: 12px;
  518. color: #fff;
  519. pointer-events: auto;
  520. &::after {
  521. content: "";
  522. height: 100%;
  523. vertical-align: middle;
  524. display: inline-block;
  525. }
  526. &.show {
  527. right: 0;
  528. }
  529. &.hide {
  530. right: -44px;
  531. }
  532. }
  533. }
  534. }
  535. }
  536. .empty-tip {
  537. text-align: center;
  538. position: absolute;
  539. text-align: center;
  540. width: 100%;
  541. top: 50%;
  542. transform: translateY(-50%);
  543. img {
  544. width: 125px;
  545. }
  546. div {
  547. margin-top: 20px;
  548. color: rgba(255, 255, 255, 0.6);
  549. font-size: 14px;
  550. }
  551. }
  552. }
  553. .ui-button {
  554. width: 100%;
  555. }
  556. .adding-hotspot-panel {
  557. position: absolute;
  558. top: 0;
  559. height: 100%;
  560. right: 0;
  561. width: 100%;
  562. }
  563. .goto-4dkk-tip {
  564. > .img-wrap {
  565. position: relative;
  566. width: 100%;
  567. > .img {
  568. width: 100%;
  569. }
  570. > .tip-text {
  571. position: absolute;
  572. left: 50%;
  573. bottom: 32px;
  574. transform: translateX(-50%);
  575. font-size: 14px;
  576. color: #fff;
  577. opacity: 0.6;
  578. white-space: pre;
  579. }
  580. }
  581. > button {
  582. margin-top: 16px;
  583. width: 100%;
  584. }
  585. }
  586. }
  587. </style>