main.js 12 KB

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