index.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. <template>
  2. <div class="panocon">
  3. <template v-if="showInfo">
  4. <iframe
  5. allowfullscreen="true"
  6. v-if="activeItem.type == '4dkk'"
  7. :src="`/spc.html?m=${activeItem.sceneCode}&lang=zh`"
  8. frameborder="0"
  9. ></iframe>
  10. <div v-show="activeItem.type != '4dkk'" id="pano"></div>
  11. <div
  12. class="pano-logo"
  13. v-if="showInfo.isLogo && activeItem.type != '4dkk'"
  14. >
  15. <img
  16. :src="
  17. showInfo.logo ||
  18. require('@/assets/images/default/img_logoshow@2x.png')
  19. "
  20. alt=""
  21. />
  22. </div>
  23. <div
  24. class="oper-tips"
  25. :class="{ hidetips: !showTips }"
  26. v-if="localRemind"
  27. >
  28. <img
  29. :src="
  30. showInfo.pcIcon ||
  31. require('@/assets/images/default/show/img_tipspc_default.png')
  32. "
  33. alt=""
  34. />
  35. </div>
  36. <list v-if="canLoad" @select="handleSelect" :select="activeItem"></list>
  37. <password
  38. :bg="showInfo.icon"
  39. :show="showPassword"
  40. @submit="handlePassword"
  41. @close="showPassword = false"
  42. />
  43. <popup :title="'简介'" :show="showIntro" @close="showIntro = false">
  44. <div slot="content" class="introcon">
  45. {{ showInfo.description || "暂无简介" }}
  46. </div>
  47. </popup>
  48. <preview
  49. :item="currentHotspot"
  50. :show="showPreview"
  51. @close="showPreview = false"
  52. />
  53. <ul class="aside" v-if="activeItem.type != '4dkk'">
  54. <li v-for="(item, i) in aside" :key="i">
  55. <span @click="handleItem(item)">
  56. <i class="iconfont" :class="item.icon"></i>
  57. </span>
  58. </li>
  59. </ul>
  60. </template>
  61. <template v-else>
  62. <div class="hasDel" v-if="loadFinish">
  63. <div>
  64. <img :src="$noresult" alt="" />
  65. <p>作品已被删除</p>
  66. </div>
  67. </div>
  68. </template>
  69. </div>
  70. </template>
  71. <script>
  72. import * as krfn from "@/core/index.js";
  73. import { getPanoInfo, checkPassword, checkWork } from "@/api";
  74. import password from "./popup/password";
  75. import preview from "./popup/preview";
  76. import { $smallWaiting } from "@/components/shared/loading";
  77. import popup from "./popup/";
  78. import { mapGetters } from "vuex";
  79. import list from "./list";
  80. let __krfn = krfn.default;
  81. export default {
  82. components: {
  83. list,
  84. password,
  85. popup,
  86. preview,
  87. },
  88. computed: {
  89. ...mapGetters({
  90. showInfo: "showInfo",
  91. }),
  92. },
  93. data() {
  94. return {
  95. showPreview: false,
  96. isFullscreen: false,
  97. showTips: false,
  98. canLoad: false,
  99. loadFinish: false,
  100. showPassword: false,
  101. showIntro: false,
  102. localRemind: false,
  103. password: "",
  104. activeItem: "",
  105. someData: "",
  106. currentHotspot: "",
  107. list: [],
  108. aside: [
  109. {
  110. id: "about",
  111. icon: "icontool_about",
  112. },
  113. {
  114. id: "vr",
  115. icon: "icontool_vr",
  116. },
  117. {
  118. id: "full",
  119. icon: "icontool_full",
  120. },
  121. ],
  122. };
  123. },
  124. methods: {
  125. onFullScreen() {
  126. let element = document.documentElement;
  127. if (this.isFullscreen) {
  128. if (document.exitFullscreen) {
  129. document.exitFullscreen();
  130. } else if (document.webkitCancelFullScreen) {
  131. document.webkitCancelFullScreen();
  132. } else if (document.mozCancelFullScreen) {
  133. document.mozCancelFullScreen();
  134. } else if (document.msExitFullscreen) {
  135. document.msExitFullscreen();
  136. }
  137. } else {
  138. if (element.requestFullscreen) {
  139. element.requestFullscreen();
  140. } else if (element.webkitRequestFullScreen) {
  141. element.webkitRequestFullScreen();
  142. } else if (element.mozRequestFullScreen) {
  143. element.mozRequestFullScreen();
  144. } else if (element.msRequestFullscreen) {
  145. element.msRequestFullscreen();
  146. }
  147. }
  148. // 改变当前全屏状态
  149. this.isFullscreen = !this.isFullscreen;
  150. },
  151. handleItem(data) {
  152. if (data.id == "about") {
  153. this.showIntro = true;
  154. }
  155. if (data.id == "full") {
  156. this.onFullScreen();
  157. }
  158. if (data.id == "vr") {
  159. var krpano = document.getElementById("krpanoSWFObject");
  160. var webvr = krpano.get("webvr");
  161. webvr.entervr();
  162. // window.webvr.enterVR()
  163. }
  164. },
  165. handlePassword(data) {
  166. checkPassword(
  167. {
  168. password: data,
  169. },
  170. (res) => {
  171. if (res.code == 0) {
  172. this.showPassword = false;
  173. this.canLoad = true;
  174. }
  175. }
  176. );
  177. },
  178. startLoad() {
  179. this.canLoad = true;
  180. },
  181. handleSelect(data) {
  182. this.activeItem = data;
  183. },
  184. fixData() {
  185. let tmp = [];
  186. this.showInfo.scenes.forEach((item) => {
  187. this.showInfo.catalogs.forEach((sub) => {
  188. if (item.category == sub.id) {
  189. if (tmp.indexOf(sub) < 0) {
  190. tmp.push(sub);
  191. }
  192. }
  193. });
  194. });
  195. tmp = this.$unique(tmp);
  196. this.showInfo.catalogs = tmp;
  197. let rootmp = [];
  198. tmp.forEach((item) => {
  199. this.showInfo.catalogRoot.forEach((sub) => {
  200. sub.children = this.$unique(sub.children);
  201. if (sub.children.indexOf(item.id) > -1) {
  202. rootmp.push(sub);
  203. }
  204. });
  205. });
  206. rootmp = this.$unique(rootmp);
  207. let sortArr = this.showInfo.catalogRoot.map((item) => item.name);
  208. rootmp.sort((a, b) => {
  209. return sortArr.indexOf(a.name) - sortArr.indexOf(b.name);
  210. });
  211. this.showInfo.catalogRoot = rootmp.map((item) => {
  212. let temp = [];
  213. item.children = this.$unique(item.children);
  214. item.children.forEach((sub) => {
  215. tmp.forEach((jj) => {
  216. if (jj.id == sub) {
  217. temp.push(sub);
  218. }
  219. });
  220. });
  221. return {
  222. ...item,
  223. children: temp,
  224. };
  225. });
  226. this.showInfo.catalogs = tmp;
  227. let cid = "c_" + this.$randomWord(true, 8, 8);
  228. if (this.showInfo.catalogRoot.length <= 0) {
  229. this.showInfo.catalogRoot.push({
  230. id: "r_" + this.$randomWord(true, 8, 8),
  231. name: "全部场景",
  232. children: [cid],
  233. });
  234. }
  235. if (this.showInfo.catalogs.length <= 0) {
  236. this.showInfo.catalogs.push({
  237. id: cid,
  238. name: "默认二级分组",
  239. });
  240. }
  241. if (this.showInfo.firstScene) {
  242. this.showInfo.firstScene = this.showInfo.scenes.find(
  243. (item) => item.sceneCode == this.showInfo.firstScene.sceneCode
  244. );
  245. }
  246. this.$store.commit("SetShowInfo", this.showInfo);
  247. },
  248. getSceneInfo() {
  249. checkWork("", (data) => {
  250. if (data.data) {
  251. getPanoInfo("", (res) => {
  252. this.$store.commit("SetShowInfo", res);
  253. this.fixData();
  254. this.loadFinish = true;
  255. });
  256. } else {
  257. this.loadFinish = true;
  258. }
  259. });
  260. },
  261. },
  262. watch: {
  263. currentHotspot: {
  264. deep: true,
  265. handler: function (newVal) {
  266. if (newVal) {
  267. if (newVal.hotspotType == "link") {
  268. window.open(newVal.hyperlink, "_blank");
  269. return;
  270. }
  271. if (newVal.hotspotType == "scene") {
  272. this.activeItem = newVal.secne;
  273. return;
  274. }
  275. this.showPreview = true;
  276. }
  277. },
  278. },
  279. canLoad(newVal) {
  280. if (newVal) {
  281. setTimeout(() => {
  282. this.showTips = this.localRemind;
  283. setTimeout(() => {
  284. this.showTips = false;
  285. }, this.showInfo.remindTime * 1000);
  286. }, 2000);
  287. }
  288. },
  289. showInfo: {
  290. deep: true,
  291. immediate: true,
  292. handler: function (newVal) {
  293. if (newVal) {
  294. document.title = newVal.name || "无标题";
  295. let locoR = "localRemind" + newVal.id;
  296. if (!newVal.description) {
  297. this.aside.shift();
  298. }
  299. if (newVal.isRemind == 1) {
  300. this.localRemind = localStorage.getItem(locoR) == 1 ? false : true;
  301. localStorage.setItem(locoR, 1);
  302. } else {
  303. this.localRemind = true;
  304. localStorage.setItem(locoR, 0);
  305. }
  306. if (this.showInfo.firstScene) {
  307. if (this.showInfo.firstScene.type == "4dkk") {
  308. this.localRemind = false;
  309. }
  310. }
  311. newVal.password ? (this.showPassword = true) : this.startLoad();
  312. }
  313. },
  314. },
  315. activeItem: {
  316. handler(newVal) {
  317. this.currentHotspot = "";
  318. $("#pano").empty();
  319. window.vrInitFn = () => {
  320. $smallWaiting.hide();
  321. var krpano = document.getElementById("krpanoSWFObject");
  322. __krfn.utils.initHotspot(krpano, newVal && newVal.someData, false);
  323. };
  324. window.vrViewFn = () => {
  325. try {
  326. let tmp = newVal.initVisual || {};
  327. var krpano = document.getElementById("krpanoSWFObject");
  328. krpano.set("view.vlookat", tmp.vlookat || 0);
  329. krpano.set("view.hlookat", tmp.hlookat || 0);
  330. krpano.set("autorotate.enabled", Boolean(this.showInfo.isAuto));
  331. } catch (error) {
  332. error;
  333. }
  334. };
  335. var settings = {
  336. "events[skin_events].onxmlcomplete": "js(window.vrViewFn());",
  337. "events[skin_events].onloadcomplete": "js(window.vrInitFn());",
  338. };
  339. if (newVal) {
  340. if (newVal.type == "4dkk") {
  341. removepano("#pano");
  342. $("#pano").empty();
  343. return;
  344. }
  345. removepano("#pano");
  346. $smallWaiting.show();
  347. embedpano({
  348. // xml: "%HTMLPATH%/static/template/tour.xml",
  349. xml: `${this.$cdn}/720yun_fd_manage/${newVal.sceneCode}/vtour/tour.xml`,
  350. swf: "%HTMLPATH%/static/template/tour.swf",
  351. target: "pano",
  352. html5: "auto",
  353. mobilescale: 1,
  354. vars: settings,
  355. passQueryParameters: true,
  356. });
  357. }
  358. },
  359. },
  360. },
  361. mounted() {
  362. window.__krfn = __krfn;
  363. this.$bus.on("clickHotspot", (data) => {
  364. let someData = this.activeItem.someData;
  365. if (typeof someData == "string") {
  366. someData = JSON.parse(this.activeItem.someData);
  367. }
  368. let idx = someData.hotspots.findIndex((item) => item.name == data);
  369. this.currentHotspot = someData.hotspots[idx];
  370. });
  371. this.getSceneInfo();
  372. },
  373. };
  374. </script>
  375. <style lang="less" scoped>
  376. .panocon {
  377. width: 100%;
  378. height: 100%;
  379. .hasDel {
  380. background: #fff;
  381. width: 100%;
  382. height: 100%;
  383. position: relative;
  384. > div {
  385. position: absolute;
  386. top: 50%;
  387. left: 50%;
  388. transform: translate(-50%, -50%);
  389. color: #909090;
  390. text-align: center;
  391. font-size: 18px;
  392. > p {
  393. margin-top: 20px;
  394. }
  395. }
  396. }
  397. #pano {
  398. width: 100%;
  399. height: 100%;
  400. }
  401. > iframe {
  402. width: 100%;
  403. height: 100%;
  404. }
  405. .pano-logo {
  406. position: absolute;
  407. top: 20px;
  408. left: 20px;
  409. > img {
  410. max-width: 120px;
  411. max-height: 100px;
  412. pointer-events: none;
  413. }
  414. }
  415. .oper-tips {
  416. position: absolute;
  417. top: 50%;
  418. left: 50%;
  419. transform: translate(-50%, -50%);
  420. transition: display 0.3s ease;
  421. > img {
  422. max-width: 300px;
  423. }
  424. }
  425. .hidetips {
  426. display: none;
  427. }
  428. .aside {
  429. position: fixed;
  430. z-index: 999;
  431. right: 10px;
  432. top: 50%;
  433. transform: translateY(-50%);
  434. > li {
  435. margin: 5px 0;
  436. > span {
  437. width: 36px;
  438. height: 36px;
  439. display: inline-block;
  440. background: rgba(0, 0, 0, 0.3);
  441. border: 1px solid rgba(255, 255, 255, 0.2);
  442. opacity: 1;
  443. border-radius: 18px;
  444. position: relative;
  445. cursor: pointer;
  446. > i {
  447. position: absolute;
  448. top: 50%;
  449. left: 50%;
  450. transform: translate(-50%, -50%);
  451. }
  452. }
  453. }
  454. }
  455. .introcon {
  456. line-height: 20px;
  457. word-break: break-all;
  458. text-align: justify;
  459. }
  460. }
  461. </style>