showMobile.vue 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. <template>
  2. <LoadingLogo v-if="workEnable" />
  3. <template v-if="workEnable">
  4. <Opening
  5. :coverData="coverInfo"
  6. v-if="coverInfo.isShowCover && !hasPasswordLock"
  7. />
  8. <Password @pass="handlePass" />
  9. <Share />
  10. <div class="ui-view-layout" :class="{ show: show }">
  11. <Pano />
  12. <Tags />
  13. <UiGather />
  14. <TitieSlide />
  15. </div>
  16. </template>
  17. <Error v-else />
  18. </template>
  19. <script setup>
  20. import Pano from "@/components/Pano";
  21. import Tags from "@/components/assembly/MobileTags";
  22. import Password from "@/components/assembly/Password";
  23. import Share from "@/components/assembly/Share";
  24. import Error from "@/components/assembly/Error";
  25. import UiGather from "@/components/UIGather/mobile";
  26. import TitieSlide from "@/components/assembly/titieSlide";
  27. import Opening from "@/components/assembly/OpeningMobile";
  28. import LoadingLogo from "@/components/assembly/Loading";
  29. import { createApp } from "@/app";
  30. import {
  31. ref,
  32. onMounted,
  33. computed,
  34. unref,
  35. onBeforeMount,
  36. watch,
  37. nextTick,
  38. } from "vue";
  39. import { getPanoInfo, checkWork, exchangeId } from "@/apis";
  40. import { useStore } from "vuex";
  41. import config from "@/utils/config";
  42. import browser from "@/utils/browser";
  43. import { useApp } from "@/app";
  44. import { useWxShared } from "@/hooks/useWxshared";
  45. import { useAudio } from "@/hooks/useAudio";
  46. import { useI18n, getLocale } from "@/i18n";
  47. import { Dialog } from "@/global_components";
  48. const { t } = useI18n({ useScope: "global" });
  49. const { initWxShare } = useWxShared();
  50. const coverInfo = ref({});
  51. const store = useStore();
  52. const show = ref(false);
  53. const workEnable = ref(true);
  54. const lang = getLocale();
  55. const hasPasswordLock = ref(false);
  56. const currentScene = computed(() => store.getters["scene/currentScene"]);
  57. const currentCatalogRoot = computed(
  58. () => store.getters["scene/currentCatalogRoot"]
  59. );
  60. const isAutoRotate = computed(() => store.getters["functions/isAutoRotate"]);
  61. const earthMask = computed(() => store.getters["scene/earthMask"]);
  62. const skyMask = computed(() => store.getters["scene/skyMask"]);
  63. const isShowOpeningAnimation = ref(0);
  64. onBeforeMount(() => {
  65. const vlog = browser.getURLParam("vlog");
  66. if (vlog) {
  67. var vConsole = new window.VConsole();
  68. }
  69. });
  70. onMounted(async () => {
  71. if (!browser.isMobile()) {
  72. window.location.href = window.location.href.replace(
  73. "showMobile.html",
  74. "show.html"
  75. );
  76. return;
  77. }
  78. const idRes = await exchangeId({
  79. id: config.projectNum
  80. })
  81. const { id, num, calcStatus } = idRes.data
  82. config.projectNum = id
  83. if (calcStatus === 0) {
  84. Dialog.alert({
  85. title: t("common.tips"),
  86. content: t('common.calcing'),
  87. okText: t("common.confirm"),
  88. });
  89. return
  90. }
  91. let res = await checkWork();
  92. if (!res.data) {
  93. workEnable.value = res.data;
  94. return;
  95. }
  96. getPanoInfo().then(async (data) => {
  97. isShowOpeningAnimation.value = data.isShowOpeningAnimation
  98. ? Number(data.isShowOpeningAnimation)
  99. : 0;
  100. //TODO 兼容1.2.0或以下数据
  101. if (
  102. !("isShowOpeningAnimation" in data) &&
  103. "openingAnimationType" in data &&
  104. data.openingAnimationType.length > 0
  105. ) {
  106. console.log("小行星没有开关,但有openingAnimationType强制开启");
  107. isShowOpeningAnimation.value = 1;
  108. }
  109. store.commit("scene/setScenes", data.scenes);
  110. store.commit(
  111. "scene/setPassword",
  112. data.password === "" ? false : data.password
  113. );
  114. if (data.password.length > 0) {
  115. hasPasswordLock.value = true;
  116. }
  117. store.commit("scene/setMetaData", data);
  118. // document.title = data.name || t("common.no_title");
  119. let firstScene = "";
  120. if (config.sceneNum) {
  121. console.log(config.sceneNum);
  122. firstScene = data.scenes.find(
  123. (item) => item.sceneCode == config.sceneNum
  124. );
  125. } else if (data.firstScene) {
  126. firstScene = data.scenes.find(
  127. (item) => item.sceneCode == data.firstScene.sceneCode
  128. );
  129. }
  130. // 所有audio入口
  131. const currentSceneData = firstScene || data.scenes[0];
  132. // debugger;
  133. store.dispatch(
  134. "audio/initNormalBGM",
  135. data.backgroundMusic ? data.backgroundMusic.ossPath : ""
  136. );
  137. store.commit("scene/setCurrentScene", currentSceneData);
  138. // 过滤空分组
  139. let ttt = data.catalogRoot.filter((item) => {
  140. let flag = "";
  141. if (item.children) {
  142. item.children.some((sub) => {
  143. flag = data.scenes.some((son) => {
  144. // console.log(String(son.category).toLowerCase(), String(sub).toLowerCase());
  145. return (
  146. String(son.category).toLowerCase() == String(sub).toLowerCase()
  147. );
  148. });
  149. return flag;
  150. });
  151. }
  152. return flag;
  153. });
  154. data.catalogRoot = ttt;
  155. let catalog = data.catalogs.find(
  156. (item) => item.id == currentScene.value.category
  157. );
  158. // 查询初始场景的所在1级分组
  159. data.catalogRoot.forEach((item) => {
  160. let temp =
  161. item.children && item.children.find((sub) => sub == catalog.id);
  162. if (temp) {
  163. store.commit("scene/setCurrentCatalogRoot", item);
  164. return;
  165. }
  166. });
  167. // 查询初始场景的所在2级分组
  168. store.commit("scene/setCurrentSecondary", catalog);
  169. store.commit("functions/setAutoRotate", !!data.isAuto);
  170. show.value = true;
  171. let isHavePano = data.scenes.some((item) => item.type == "pano");
  172. document.body.setAttribute("is-mobile", true);
  173. const app = createApp({
  174. // xml: "%HTMLPATH%/static/template/tour.xml",
  175. xml: `${process.env.VUE_APP_CDN}/720yun_fd_manage/${
  176. config.projectNum
  177. }/tour.xml?rnd=${Math.random()}`,
  178. swf: "%HTMLPATH%/showviewer/lib/krpano/tour.swf",
  179. target: "pano",
  180. html5: "auto",
  181. mobilescale: 1,
  182. isHavePano,
  183. vars: {
  184. startscene: "scene_" + currentScene.value.sceneCode,
  185. "view.org_vlookat": currentScene.value.initVisual
  186. ? currentScene.value.initVisual.vlookat
  187. : 0,
  188. "view.org_hlookat": currentScene.value.initVisual
  189. ? currentScene.value.initVisual.hlookat
  190. : 0,
  191. "autorotate.enabled": !!data.isAuto,
  192. "skin_settings.littleplanetintro":
  193. typeof data.openingAnimationType === "number"
  194. ? data.openingAnimationType
  195. : 1,
  196. "skin_settings.lptswitch": unref(isShowOpeningAnimation),
  197. },
  198. passQueryParameters: true,
  199. });
  200. if (app) {
  201. coverInfo.value = data.coverInfo || {};
  202. app.Scene.lock();
  203. //如果不需要开场封面就直接渲染
  204. if (!coverInfo.value?.isShowCover) {
  205. app.render();
  206. }
  207. if (isHavePano) {
  208. app.Scene.on("sceneReady", () => {
  209. if (app.krpanoDom) {
  210. const { sky, earth } = currentScene.value.customMask;
  211. handleMasksUpdate(sky, earth, app);
  212. app.krpanoDom.set(
  213. `layer[webvr_exitbutton].html`,
  214. t("common.exit_vr")
  215. );
  216. }
  217. let hotspots = [];
  218. if (currentScene.value.someData) {
  219. hotspots =
  220. typeof currentScene.value.someData == "string"
  221. ? JSON.parse(currentScene.value.someData).hotspots
  222. : currentScene.value.someData.hotspots;
  223. }
  224. app.Tags.initHotspot(hotspots, false);
  225. handleVisualLimit(app, currentScene.value);
  226. });
  227. }
  228. initWxShare(lang);
  229. // debugger
  230. console.log("初始化微信分享");
  231. const { initDefaultAudio } = useAudio();
  232. initDefaultAudio();
  233. }
  234. });
  235. });
  236. const handlePass = () => {
  237. hasPasswordLock.value = false;
  238. };
  239. const handleVisualLimit = (app, currentScene) => {
  240. const { vlookatmax, vlookatmin } = currentScene.initVisual;
  241. // console.log('initVisual',currentScene.initVisual)
  242. app.krpanoDom.set(`view.limitview`, "lookat");
  243. app.krpanoDom.set(`view.vlookatmin`, vlookatmin);
  244. app.krpanoDom.set(`view.vlookatmax`, vlookatmax);
  245. };
  246. const handleMasksUpdate = (skyMask, earthMask, app) => {
  247. const lang = getLocale();
  248. let defaultMask = `%SWFPATH%/skin/masking_${lang}.png`;
  249. if (skyMask) {
  250. if ("isShow" in skyMask) {
  251. app.krpanoDom.set(`hotspot[peaklogo].visible`, Boolean(skyMask.isShow));
  252. }
  253. if (skyMask.icon) {
  254. app.krpanoDom.set(
  255. `hotspot[peaklogo].url`,
  256. skyMask.icon + "?x-oss-process=image/resize,w_1000"
  257. );
  258. } else {
  259. app.krpanoDom.set(`hotspot[peaklogo].url`, defaultMask);
  260. }
  261. if ("scale" in skyMask) {
  262. app.krpanoDom.set(`hotspot[peaklogo].scale`, skyMask.scale);
  263. }
  264. if ("antidistorted" in skyMask) {
  265. app.krpanoDom.set(`hotspot[peaklogo].distorted`, skyMask.antidistorted);
  266. if (!skyMask.antidistorted) {
  267. app.krpanoDom.set(`hotspot[peaklogo].scale`, skyMask.scale * 1.5);
  268. }
  269. }
  270. }
  271. if (earthMask) {
  272. if ("isShow" in earthMask) {
  273. app.krpanoDom.set(
  274. `hotspot[nadirlogo].visible`,
  275. Boolean(earthMask.isShow)
  276. );
  277. }
  278. if (earthMask.icon) {
  279. app.krpanoDom.set(
  280. `hotspot[nadirlogo].url`,
  281. earthMask.icon + "?x-oss-process=image/resize,w_1000"
  282. );
  283. }
  284. if ("scale" in earthMask) {
  285. app.krpanoDom.set(`hotspot[nadirlogo].scale`, earthMask.scale);
  286. }
  287. if ("antidistorted" in earthMask) {
  288. app.krpanoDom.set(
  289. `hotspot[nadirlogo].distorted`,
  290. earthMask.antidistorted
  291. );
  292. if (!earthMask.antidistorted) {
  293. app.krpanoDom.set(`hotspot[nadirlogo].scale`, earthMask.scale * 1.5);
  294. }
  295. }
  296. }
  297. };
  298. </script>
  299. <style lang="scss" scoped>
  300. .ui-view-layout {
  301. position: relative;
  302. z-index: 0;
  303. }
  304. </style>