index.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. <template>
  2. <div class="panocon">
  3. <template v-if="showInfo">
  4. <v-ifr v-if="activeItem.type=='4dkk'" :url="`https://test.4dkankan.com/embed.html?from=mingyuan&m=${activeItem.sceneCode}`" />
  5. <div v-show="activeItem.type!='4dkk'" id="pano"></div>
  6. <div class="pano-logo" v-if="showInfo.isLogo&&activeItem.type!='4dkk'">
  7. <img :src="showInfo.logo||require('@/assets/images/default/img_logoshow@2x.png')" alt="" />
  8. </div>
  9. <ul class="aside" v-show="activeItem.type!='4dkk'">
  10. <li v-for="(item, i) in aside" :key="i">
  11. <span @click="handleItem(item)">
  12. <i class="iconfont" :class="item.icon"></i>
  13. </span>
  14. </li>
  15. </ul>
  16. <list
  17. v-if="canLoad"
  18. @select="handleSelect"
  19. :firstScene="firstScene"
  20. :select="activeItem"
  21. ></list>
  22. <div
  23. class="oper-tips"
  24. :class="{ hidetips: !showTips }"
  25. v-if="localRemind"
  26. >
  27. <img
  28. :src="
  29. showInfo.appIcon ||
  30. require('@/assets/images/default/show/img_tipsmb_default.png')
  31. "
  32. alt=""
  33. />
  34. </div>
  35. <password
  36. :bg="showInfo.icon"
  37. :show="showPassword"
  38. @submit="handlePassword"
  39. @close="showPassword = false"
  40. />
  41. <popup :title="'简介'" :show="showIntro" @close="showIntro = false">
  42. <div slot="content" class="introcon">
  43. {{ showInfo.description || "暂无简介" }}
  44. </div>
  45. </popup>
  46. <imgview
  47. @close="showImage = false"
  48. v-if="showImage"
  49. :image="currentHotspot.image"
  50. />
  51. <preview
  52. :item="currentHotspot"
  53. :show="showPreview"
  54. @close="showPreview = false"
  55. />
  56. <popup
  57. :title="currentHotspot.hotspotTitle"
  58. :show="showTextarea"
  59. @close="showTextarea = false"
  60. >
  61. <div slot="content" class="introcon">
  62. {{ currentHotspot.textarea }}
  63. </div>
  64. </popup>
  65. <div v-if="audioUrl" class="audio-btn" @click="bofang=!bofang">
  66. {{bofang?'继续':'停止'}}播放
  67. <v-audio :vkey="audioUrl.id" @audioEnded="handleEnded" :autoplay="true" :bofang="bofang" :v-show="false" :idleft="`_${$randomWord(true,8,8)}`" :idright="`_${$randomWord(true,8,8)}`" :myAudioUrl="audioUrl.audio.ossPath"></v-audio>
  68. </div>
  69. </template>
  70. <template v-else>
  71. <div class="hasDel" v-if="loadFinish">
  72. <div>
  73. <img :src="$noresult" alt="">
  74. <p>作品已被删除</p>
  75. </div>
  76. </div>
  77. </template>
  78. </div>
  79. </template>
  80. <script>
  81. import * as krfn from "@/core/index.js";
  82. import { getPanoInfo, checkPassword,checkWork } from "@/api";
  83. import password from "./popup/password";
  84. import preview from "./popup/preview";
  85. import imgview from "./popup/imgview";
  86. import vIfr from "./iframe";
  87. import popup from "./popup/";
  88. import { mapGetters } from "vuex";
  89. import vAudio from '@/components/audio'
  90. import list from "./list";
  91. let __krfn = krfn.default;
  92. export default {
  93. components: {
  94. list,
  95. password,
  96. popup,
  97. preview,
  98. imgview,
  99. vIfr,
  100. vAudio
  101. },
  102. computed: {
  103. ...mapGetters({
  104. showInfo: "showInfo",
  105. }),
  106. },
  107. data() {
  108. return {
  109. showPreview: false,
  110. audioUrl:'',
  111. bofang:false,
  112. showTips: true,
  113. showImage: false,
  114. showAudio:false,
  115. canLoad: false,
  116. showPassword: false,
  117. showIntro: false,
  118. showTextarea: false,
  119. password: "",
  120. activeItem: "",
  121. firstScene: "",
  122. someData: "",
  123. currentHotspot: "",
  124. list: [],
  125. loadFinish:false,
  126. aside: [
  127. {
  128. id: "about",
  129. icon: "icontool_about",
  130. },
  131. {
  132. id: "vr",
  133. icon: "icontool_vr",
  134. },
  135. ],
  136. };
  137. },
  138. methods: {
  139. handleEnded(){
  140. this.audioUrl = ''
  141. },
  142. handleItem(data) {
  143. if (data.id == "about") {
  144. this.showIntro = true;
  145. }
  146. if (data.id == "vr") {
  147. var krpano = document.getElementById("krpanoSWFObject");
  148. var webvr = krpano.get("webvr");
  149. webvr.entervr();
  150. // window.webvr.enterVR()
  151. }
  152. },
  153. handlePassword(data) {
  154. checkPassword(
  155. {
  156. password: data,
  157. },
  158. (res) => {
  159. if (res.code == 0) {
  160. this.showPassword = false;
  161. this.canLoad = true;
  162. }
  163. }
  164. );
  165. },
  166. startLoad() {
  167. this.canLoad = true;
  168. },
  169. handleSelect(data) {
  170. this.activeItem = data;
  171. },
  172. getSceneInfo() {
  173. checkWork("",data=>{
  174. if (data.data) {
  175. getPanoInfo(
  176. "",
  177. (data) => {
  178. this.loadFinish = true
  179. this.$store.commit("SetShowInfo", data);
  180. }
  181. );
  182. } else{
  183. this.loadFinish = true
  184. }
  185. })
  186. },
  187. },
  188. watch: {
  189. currentHotspot: {
  190. deep: true,
  191. handler: function (newVal) {
  192. if (newVal) {
  193. this.audioUrl = ''
  194. if (newVal.hotspotType == "link") {
  195. window.open(newVal.hyperlink, "_blank");
  196. return;
  197. }
  198. if (newVal.hotspotType == "scene") {
  199. this.activeItem = newVal.secne;
  200. return;
  201. }
  202. if (newVal.hotspotType == "image") {
  203. this.showImage = true;
  204. return;
  205. }
  206. if (newVal.hotspotType == "textarea") {
  207. this.showTextarea = true;
  208. return;
  209. }
  210. if (newVal.hotspotType == "audio") {
  211. this.audioUrl = newVal;
  212. return;
  213. }
  214. this.showPreview = true;
  215. }
  216. }
  217. },
  218. canLoad(newVal) {
  219. if (newVal) {
  220. setTimeout(() => {
  221. this.showTips = false;
  222. }, this.showInfo.remindTime * 1000);
  223. }
  224. },
  225. showInfo: {
  226. deep: true,
  227. immediate: true,
  228. handler: function (newVal) {
  229. if (newVal) {
  230. document.title = newVal.name || '未命名'
  231. let locoR = "localRemind"+newVal.id
  232. if (!newVal.description) {
  233. this.aside.shift()
  234. }
  235. if (newVal.isRemind==1) {
  236. this.localRemind = localStorage.getItem(locoR) == 1 ? false : true
  237. localStorage.setItem(locoR, 1);
  238. }
  239. else{
  240. this.localRemind = true;
  241. localStorage.setItem(locoR, 0);
  242. }
  243. newVal.password ? (this.showPassword = true) : this.startLoad();
  244. }
  245. },
  246. },
  247. activeItem: {
  248. handler(newVal) {
  249. this.$nextTick(()=>{
  250. removepano("#pano");
  251. $("#pano").empty();
  252. window.vrInitFn = () => {
  253. var krpano = document.getElementById("krpanoSWFObject");
  254. __krfn.utils.initHotspot(krpano, newVal && newVal.someData, false);
  255. };
  256. window.vrViewFn = () => {
  257. try {
  258. let tmp = newVal.initVisual||{};
  259. var krpano = document.getElementById("krpanoSWFObject");
  260. krpano.set("view.vlookat", tmp.vlookat||0);
  261. krpano.set("view.hlookat", tmp.hlookat||0);
  262. krpano.set("autorotate.enabled", Boolean(this.showInfo.isAuto));
  263. } catch (error) {
  264. error;
  265. }
  266. };
  267. var settings = {
  268. "events[skin_events].onxmlcomplete": "js(window.vrViewFn());",
  269. "events[skin_events].onloadcomplete": "js(window.vrInitFn());",
  270. };
  271. if (newVal) {
  272. removepano("#pano");
  273. embedpano({
  274. // xml: "%HTMLPATH%/static/template/tour.xml",
  275. xml: `${this.$cdn}/720yun_fd_manage/${newVal.sceneCode}/vtour/tour.xml`,
  276. swf: "%HTMLPATH%/static/template/tour.swf",
  277. target: "pano",
  278. html5: "auto",
  279. mobilescale: 0.7,
  280. vars: settings,
  281. passQueryParameters: true,
  282. });
  283. }
  284. })
  285. },
  286. },
  287. },
  288. mounted() {
  289. window.__krfn = __krfn;
  290. this.$bus.on("clickHotspot", (data) => {
  291. let someData = JSON.parse(this.activeItem.someData);
  292. let idx = someData.hotspots.findIndex((item) => item.name == data);
  293. this.currentHotspot = someData.hotspots[idx];
  294. });
  295. this.getSceneInfo();
  296. },
  297. };
  298. </script>
  299. <style lang="less" scoped>
  300. .panocon {
  301. width: 100%;
  302. height: 100%;
  303. #pano {
  304. width: 100%;
  305. height: 100%;
  306. }
  307. .hasDel{
  308. background: #fff;
  309. width: 100%;
  310. height: 100%;
  311. position: relative;
  312. >div{
  313. position: absolute;
  314. top: 50%;
  315. left: 50%;
  316. transform: translate(-50%,-50%);
  317. color: #909090;
  318. text-align: center;
  319. font-size: 18px;
  320. >p{
  321. margin-top: 20px;
  322. }
  323. }
  324. }
  325. >iframe{
  326. width: 100%;
  327. height: 100%;
  328. }
  329. .audio-btn{
  330. display: inline-block;
  331. margin: 0 auto;
  332. height: 36px;
  333. line-height: 36px;
  334. min-width: 78px;
  335. cursor: pointer;
  336. text-overflow: ellipsis;
  337. text-align: center;
  338. overflow: hidden;
  339. white-space: nowrap;
  340. position: fixed;
  341. left: 50%;
  342. transform: translateX(-50%);
  343. bottom: 12px;
  344. z-index: 9999;
  345. border-radius: 18px;
  346. background: rgba(0, 0, 0, 0.3);
  347. border-radius: 18px;
  348. border: 1px solid rgba(255, 255, 255, 0.2);
  349. margin-top: 10px;
  350. margin-left: 10px;
  351. padding: 0 10px;
  352. &.active{
  353. background: rgba(0, 0, 0, 0.3);
  354. border: 1px solid #1FE4DC;
  355. color: #1FE4DC;
  356. }
  357. }
  358. .pano-logo {
  359. position: absolute;
  360. top: 10px;
  361. left: 10px;
  362. > img {
  363. max-width: 80px;
  364. }
  365. }
  366. .oper-tips {
  367. position: absolute;
  368. top: 50%;
  369. left: 50%;
  370. transform: translate(-50%, -50%);
  371. transition: all 0.3s ease;
  372. > img {
  373. max-width: 90%;
  374. }
  375. }
  376. .hidetips {
  377. display: none;
  378. }
  379. .aside {
  380. position: fixed;
  381. z-index: 1001;
  382. right: 10px;
  383. bottom: 4px;
  384. display: flex;
  385. > li {
  386. margin: 0 0 5px 5px;
  387. > span {
  388. width: 36px;
  389. height: 36px;
  390. display: inline-block;
  391. background: rgba(0, 0, 0, 0.3);
  392. border: 1px solid rgba(255, 255, 255, 0.2);
  393. opacity: 1;
  394. border-radius: 18px;
  395. position: relative;
  396. cursor: pointer;
  397. > i {
  398. position: absolute;
  399. top: 50%;
  400. left: 50%;
  401. transform: translate(-50%, -50%);
  402. }
  403. }
  404. }
  405. }
  406. .introcon {
  407. line-height: 20px;
  408. color: #909090;
  409. margin: 0 auto;
  410. width: 90%;
  411. }
  412. }
  413. </style>