main.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. import { createApp } from 'vue';
  2. import App from './App.vue';
  3. import router from './router';
  4. import store from './store';
  5. import Vant from 'vant';
  6. import { ConfigProvider } from 'vant';
  7. import 'vant/lib/index.css';
  8. import './styles/app.less';
  9. import './styles/font.less';
  10. import http from './plugins/http';
  11. import colors from './plugins/colors';
  12. // import ElementUI from 'element-ui';
  13. // import 'element-ui/lib/theme-chalk/index.css';
  14. import PageTitle from './components/PageTitle';
  15. import LikeButton from './components/LikeButton.vue';
  16. import Driver from './components/Driver.vue';
  17. import common from './mixins/common';
  18. import VueClipboard from 'vue-clipboard2';
  19. import queryString from 'query-string';
  20. import PageBar from './components/PageBar';
  21. import eruda from 'eruda';
  22. import mitt from 'mitt';
  23. import dayjs from 'dayjs';
  24. import relativeTime from 'dayjs/plugin/relativeTime';
  25. import calendar from 'dayjs/plugin/calendar';
  26. import duration from 'dayjs/plugin/duration';
  27. import isSameOrBefore from 'dayjs/plugin/isSameOrBefore';
  28. import customParseFormat from 'dayjs/plugin/customParseFormat';
  29. import { Toast, Dialog } from 'vant';
  30. import { useCssVar } from '@vueuse/core';
  31. import { computed } from 'vue';
  32. const appHeight = useCssVar('--app-height', document.documentElement);
  33. const onWindowResize = () => {
  34. if (navigator.userAgent.includes('#cordova#')) {
  35. appHeight.value = `${window.screen.height}px`;
  36. } else {
  37. appHeight.value = `${window.innerHeight}px`;
  38. }
  39. };
  40. window.addEventListener('resize', onWindowResize);
  41. Toast.setDefaultOptions('loading', { duration: 0 });
  42. require('dayjs/locale/zh-cn');
  43. const emitter = mitt();
  44. dayjs.locale('zh-cn');
  45. dayjs.extend(relativeTime);
  46. dayjs.extend(calendar);
  47. dayjs.extend(duration);
  48. dayjs.extend(isSameOrBefore);
  49. dayjs.extend(customParseFormat);
  50. let showConsole = localStorage.getItem('showConsole');
  51. if (showConsole && parseInt(showConsole) > new Date().getTime()) {
  52. eruda.init();
  53. }
  54. store.commit('setFirstUrl', location.href);
  55. import ImgContent from './components/ImgContent.vue';
  56. const safeTop = useCssVar('--safe-top', document.documentElement);
  57. const safeBottom = useCssVar('--safe-bottom', document.documentElement);
  58. const safeLeft = useCssVar('--safe-left', document.documentElement);
  59. const safeRight = useCssVar('--safe-right', document.documentElement);
  60. const calcSafeArea = () => {
  61. safeTop.value = getComputedStyle(document.documentElement).getPropertyValue('--sat').replaceAll(' ', '');
  62. safeBottom.value = getComputedStyle(document.documentElement).getPropertyValue('--sab').replaceAll(' ', '');
  63. safeLeft.value = getComputedStyle(document.documentElement).getPropertyValue('--sal').replaceAll(' ', '');
  64. safeRight.value = getComputedStyle(document.documentElement).getPropertyValue('--sar').replaceAll(' ', '');
  65. if (navigator.userAgent.includes('#testSafeTop#')) {
  66. safeTop.value = '30px';
  67. }
  68. };
  69. const barHeight = computed(() => Number((safeTop.value || '0').replace('px', '')) + 46);
  70. const app = createApp(App)
  71. .use(Vant)
  72. .use(http)
  73. .use(colors)
  74. // .use(ElementUI)
  75. .use(ConfigProvider)
  76. .use(VueClipboard)
  77. .mixin(common)
  78. .component('page-title', PageTitle)
  79. .component('like-button', LikeButton)
  80. .component('driver', Driver)
  81. // .component('van-image', ImgContent)
  82. .component('page-bar', PageBar)
  83. .use(store)
  84. .use(router)
  85. .provide('appHeight', appHeight)
  86. .provide('safeTop', safeTop)
  87. .provide('safeBottom', safeBottom)
  88. .provide('safeLeft', safeLeft)
  89. .provide('safeRight', safeRight)
  90. .provide('barHeight', barHeight.value);
  91. app.config.globalProperties.emitter = emitter;
  92. app.config.globalProperties.dayjs = dayjs;
  93. let query = queryString.parse(location.search);
  94. if (query.code) {
  95. http.http.post('/user/code2openId', { code: query.code }).then(res => {
  96. localStorage.setItem('openId', res);
  97. });
  98. } else {
  99. if (/micromessenger/i.test(navigator.userAgent) && !/localhost|(192\.168)/i.test(location.host)) {
  100. // document.location.replace(location.origin + '/wx/redirect?redirectUrl=' + location.href);
  101. }
  102. }
  103. // store.dispatch('getTime');
  104. if (query.invitor) {
  105. store.commit('setInvitor', query.invitor);
  106. if (query.id) {
  107. store.commit('setProductId', query.id);
  108. }
  109. }
  110. if (query.from) {
  111. store.commit('setFrom', query.from);
  112. }
  113. if (query.inviteCode) {
  114. store.commit('setInviteCode', query.inviteCode);
  115. }
  116. if (query.review === 'true' || query.review === true) {
  117. store.commit('setReview', true);
  118. }
  119. if (query.reviewPay === 'true' || query.reviewPay === true || sessionStorage.getItem('reviewPay')) {
  120. store.commit('setReviewPay', true);
  121. sessionStorage.setItem('reviewPay', true);
  122. }
  123. const style = document.documentElement.style;
  124. style.setProperty('--safe-top', 'env(safe-area-inset-top)');
  125. style.setProperty('--safe-bottom', 'env(safe-area-inset-bottom)');
  126. style.setProperty('--safe-left', 'env(safe-area-inset-left)');
  127. style.setProperty('--safe-right', 'env(safe-area-inset-right)');
  128. const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent);
  129. const loadSplash = (onload, onerror) =>
  130. new Promise((resolve, reject) => {
  131. let isHide = false;
  132. function hideSplash() {
  133. if (isHide) return;
  134. isHide = true;
  135. splash.style.opacity = 0;
  136. setTimeout(() => {
  137. // document.body.removeChild(splash);
  138. }, 800);
  139. resolve();
  140. }
  141. const splash = document.createElement('img');
  142. splash.className = 'splash-screen';
  143. splash.onload = () => {
  144. onload && onload();
  145. setTimeout(() => {
  146. hideSplash();
  147. }, 2000);
  148. };
  149. splash.onerror = () => {
  150. hideSplash();
  151. onerror && onerror();
  152. };
  153. setTimeout(() => {
  154. hideSplash();
  155. }, 5000);
  156. splash.src = 'https://nanjingnft.oss-cn-hangzhou.aliyuncs.com/font/splash.jpg?ts=' + new Date().getTime();
  157. // document.body.append(splash);
  158. });
  159. if (navigator.userAgent.includes('#cordova#')) {
  160. document.addEventListener(
  161. 'deviceready',
  162. function () {
  163. StatusBar.overlaysWebView(true);
  164. if ('1' === window.localStorage.getItem('AppTips')) {
  165. try {
  166. window.cordova.plugins.UmengPlugin.initPush(deviceToken => {
  167. console.log('deviceToken=' + deviceToken);
  168. });
  169. } catch (e) {}
  170. }
  171. function mountApp() {
  172. window.$vm = app.mount('#app');
  173. http.http
  174. .get('/appVersion/checkUpdate', {
  175. platform: window.cordova.platformId,
  176. version: navigator.appInfo.version
  177. })
  178. .then(res => {
  179. if (res.needUpdate) {
  180. window.$vm.$dialog.alert({
  181. message: '检测到新版本,请下载更新',
  182. confirmButtonText: '下载更新',
  183. beforeClose(action, done) {
  184. console.log(action);
  185. location.href = 'http://download.raex.vip';
  186. }
  187. });
  188. }
  189. });
  190. }
  191. loadSplash(
  192. () => {
  193. setTimeout(() => {
  194. navigator.splashscreen.hide();
  195. }, 100);
  196. mountApp();
  197. },
  198. () => {
  199. navigator.splashscreen.hide();
  200. mountApp();
  201. }
  202. ).then(res => {
  203. StatusBar.styleDefault();
  204. });
  205. calcSafeArea();
  206. if ('android' === window.cordova.platformId) {
  207. window.AndroidNotch.getInsetTop(
  208. px => {
  209. console.log('getInsetTop=' + px);
  210. safeTop.value = px + 'px';
  211. },
  212. err => console.error('Failed to get insets top:', err)
  213. );
  214. window.AndroidNotch.getInsetRight(
  215. px => {
  216. safeRight.value = px + 'px';
  217. },
  218. err => console.error('Failed to get insets right:', err)
  219. );
  220. window.AndroidNotch.getInsetBottom(
  221. px => {
  222. safeBottom.value = px + 'px';
  223. },
  224. err => console.error('Failed to get insets bottom:', err)
  225. );
  226. window.AndroidNotch.getInsetLeft(
  227. px => {
  228. safeLeft.value = px + 'px';
  229. },
  230. err => console.error('Failed to get insets left:', err)
  231. );
  232. } else {
  233. calcSafeArea();
  234. setTimeout(() => {
  235. calcSafeArea();
  236. }, 500);
  237. }
  238. let t = 0;
  239. document.addEventListener(
  240. 'backbutton',
  241. e => {
  242. if (window.$vm.$route.matched.find(i => i.name === 'index')) {
  243. e.preventDefault();
  244. let t1 = new Date().getTime();
  245. console.log(t1 - t);
  246. if (t1 - t < 1000) {
  247. navigator.app.exitApp();
  248. } else {
  249. t = t1;
  250. window.$vm.$toast('再按一次退出');
  251. }
  252. } else {
  253. window.$vm.$router.go(-1);
  254. }
  255. },
  256. false
  257. );
  258. if ('ios' === window.cordova.platformId) {
  259. window.store.register(
  260. ['68', '108', '198', '288', '588', '998'].map(id => {
  261. return {
  262. id,
  263. alias: id,
  264. type: window.store.CONSUMABLE
  265. };
  266. })
  267. );
  268. window.store.error(function (error) {
  269. console.log('ERROR ' + error.code + ': ' + error.message);
  270. });
  271. ['68', '108', '198', '288', '588', '998'].forEach(id => {
  272. window.store
  273. .when(id)
  274. .updated(product => {
  275. emitter.emit('iapEvent', { event: 'updated', product });
  276. })
  277. .requested(product => {
  278. emitter.emit('iapEvent', { event: 'requested', product });
  279. })
  280. .initiated(product => {
  281. emitter.emit('iapEvent', { event: 'initiated', product });
  282. })
  283. .cancelled(product => {
  284. emitter.emit('iapEvent', { event: 'cancelled', product });
  285. })
  286. .approved(product => {
  287. product.finish();
  288. emitter.emit('iapEvent', { event: 'approved', product });
  289. })
  290. .verified(product => {
  291. emitter.emit('iapEvent', { event: 'verified', product });
  292. })
  293. .finished(product => {
  294. emitter.emit('iapEvent', { event: 'finished', product });
  295. });
  296. });
  297. window.store.refresh();
  298. }
  299. },
  300. false
  301. );
  302. } else {
  303. window.$vm = app.mount('#app');
  304. // loadSplash().then(res => {
  305. // });
  306. }