App.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. <template>
  2. <div
  3. v-loading="pageLoading"
  4. :class="{
  5. 'app-wrap': showWrap
  6. }"
  7. >
  8. <template v-if="showWrap && route.query.hideTopBar !== '1'">
  9. <div
  10. v-show="isShowTopBar"
  11. class="top-bar"
  12. >
  13. <img
  14. class="logo"
  15. src="@/assets/images/logo.png"
  16. alt=""
  17. draggable="false"
  18. @click="router.push({name: 'Banner'})"
  19. >
  20. <menu
  21. class="tab-bar"
  22. >
  23. <button
  24. :class="{
  25. active: $route.meta.tabIdx === 1
  26. }"
  27. @click="$router.push({
  28. name: 'HomeView'
  29. })"
  30. >
  31. 要素地图
  32. </button>
  33. <button
  34. :class="{
  35. active: $route.meta.tabIdx === 2
  36. }"
  37. @click="$router.push({
  38. name: 'CityOfXishan'
  39. })"
  40. >
  41. 锡善云城
  42. </button>
  43. <button
  44. :class="{
  45. active: $route.meta.tabIdx === 3
  46. }"
  47. @click="$router.push({
  48. name: 'MuseumView'
  49. })"
  50. >
  51. 慈善博物馆
  52. </button>
  53. <!-- <button
  54. :class="{
  55. active: $route.meta.tabIdx === 4
  56. }"
  57. @click="$router.push({
  58. name: 'CloudSchool'
  59. })"
  60. >
  61. 慈善云学校
  62. </button>
  63. <button
  64. :class="{
  65. active: $route.meta.tabIdx === 5
  66. }"
  67. @click="$router.push({
  68. name: 'SquareView'
  69. })"
  70. >
  71. 慈善广场
  72. </button>
  73. <button
  74. :class="{
  75. active: $route.meta.tabIdx === 6
  76. }"
  77. @click="onClickLoveForest"
  78. >
  79. 爱心林场
  80. </button>
  81. <button
  82. :class="{
  83. active: $route.meta.tabIdx === 7
  84. }"
  85. @click=" router.push({
  86. name: 'CharityHall'
  87. })"
  88. >
  89. 慈善堂
  90. </button> -->
  91. <button
  92. :class="{
  93. active: $route.meta.tabIdx === 8
  94. }"
  95. @click="onClickFeedBack"
  96. >
  97. 留言反馈
  98. </button>
  99. </menu>
  100. <div class="right-button-wrap">
  101. <button
  102. class="shop"
  103. :class="{
  104. active: $route.meta.tabIdx === 9
  105. }"
  106. @click="onClickShop"
  107. />
  108. <button
  109. class="hide-top-bar"
  110. @click="isShowTopBar = false"
  111. />
  112. </div>
  113. </div>
  114. <button
  115. v-show="!isShowTopBar"
  116. class="show-top-bar"
  117. @click="isShowTopBar = true"
  118. />
  119. </template>
  120. <FeedBack
  121. v-if="isShowFeedBack"
  122. @close="isShowFeedBack = false"
  123. />
  124. <div class="content-area">
  125. <router-view />
  126. </div>
  127. </div>
  128. </template>
  129. <script setup>
  130. import { computed, ref, watch } from "vue"
  131. import { useRoute, useRouter } from "vue-router"
  132. import { useStore } from "vuex"
  133. import { ElMessage } from 'element-plus'
  134. import FeedBack from "@/components/FeedBack.vue"
  135. import {
  136. // checkLoginStatusAndProcess,
  137. getUserFromStorageIfNeed,
  138. getShopContact
  139. } from '@/api.js'
  140. import { app } from './main'
  141. let init = false
  142. const route = useRoute()
  143. const router = useRouter()
  144. const store = useStore()
  145. const isDev = process.env.VUE_APP_CLI_MODE === 'dev'
  146. const showWrap = computed(() => route.name && route.name !== 'Banner')
  147. watch(route, () => {
  148. if (!init) {
  149. const cache = Number(localStorage.getItem('$isTablet'))
  150. const isTablet = cache === 1 || route.query.device === 'tablet'
  151. app.provide('$isTablet', isTablet)
  152. if (isTablet) {
  153. localStorage.setItem('$isTablet', 1)
  154. }
  155. init = true
  156. }
  157. })
  158. store.commit('getPageVisitRecordFromStorage')
  159. // checkLoginStatusAndProcess()
  160. getUserFromStorageIfNeed()
  161. const isShowTopBar = ref(true)
  162. const isShowFeedBack = ref(false)
  163. function onClickFeedBack() {
  164. if (process.env.VUE_APP_CLI_MODE === 'dev' || store.state.loginStatus === store.getters.loginStatusEnum.wxUser) {
  165. isShowFeedBack.value = true
  166. } else {
  167. location.href = `https://open.weixin.qq.com/connect/qrconnect?appid=wx3d4f2e0cfc3b8e54&redirect_uri=https%3A%2F%2Fsit-wuxicishan.4dage.com%2F%23%2Flogin-temp&response_type=code&scope=snsapi_login&state=${encodeURIComponent(route.name)}#wechat_redirect`
  168. }
  169. }
  170. const pageLoading = ref(false)
  171. async function onClickShop() {
  172. try {
  173. pageLoading.value = true
  174. const data = await getShopContact()
  175. if (data.display === 0) {
  176. ElMessage({
  177. message: '商城暂未开启,敬请期待',
  178. type: 'warning',
  179. })
  180. return
  181. }
  182. if (isDev || store.state.loginStatus === store.getters.loginStatusEnum.wxUser) {
  183. router.push({
  184. name: 'ShopView'
  185. })
  186. } else {
  187. location.href = `https://open.weixin.qq.com/connect/qrconnect?appid=wx3d4f2e0cfc3b8e54&redirect_uri=https%3A%2F%2Fsit-wuxicishan.4dage.com%2F%23%2Flogin-temp&response_type=code&scope=snsapi_login&state=${encodeURIComponent('ShopView')}#wechat_redirect`
  188. }
  189. } finally {
  190. pageLoading.value = false
  191. }
  192. }
  193. </script>
  194. <style lang="less">
  195. html, body {
  196. // overscroll-behavior: none;
  197. // overflow: hidden;
  198. height: 100%;
  199. }
  200. // * {
  201. // user-select: none;
  202. // -webkit-touch-callout: none;
  203. // }
  204. #app {
  205. height: 100%;
  206. }
  207. // // 360浏览器不支持not()
  208. // input, textarea {
  209. // user-select: initial;
  210. // }
  211. // 字体
  212. @font-face {
  213. font-family: 'Source Han Sans CN';
  214. src: url('@/assets/style/SOURCEHANSANSCN-LIGHT.OTF');
  215. // src: url('@/assets/style/SourceHanSansCN-Regular.otf');
  216. }
  217. @font-face {
  218. font-family: 'Source Han Sans CN-Bold';
  219. src: url('@/assets/style/SourceHanSansSCBold.otf');
  220. }
  221. @font-face{
  222. font-family: 'Source Han Serif CN';
  223. src: url('@/assets/style/SourceHanSerifCN-Regular.otf');
  224. }
  225. // i {
  226. // font-style: italic;
  227. // }
  228. @font-face{
  229. font-family: 'Alibaba PuHuiTi-Bold';
  230. src: url('@/assets/style/ALIBABA-PUHUITI-MEDIUM.OTF');
  231. }
  232. // 滚动条,只设置某一项可能导致不生效。
  233. &::-webkit-scrollbar { background: transparent; width: 6px; height: 0; }
  234. &::-webkit-scrollbar-thumb { background: #589498; opacity: 0.5; border-radius: 3px;}
  235. // vue组件过渡效果
  236. .fade-out-leave-active {
  237. transition: opacity 1s;
  238. pointer-events: none;
  239. }
  240. .fade-out-leave-to {
  241. opacity: 0;
  242. }
  243. // vue组件过渡效果
  244. .fade-in-enter-active {
  245. transition: opacity 1s;
  246. }
  247. .fade-in-enter-from {
  248. opacity: 0;
  249. }
  250. .fade-in-out-enter-active {
  251. transition: opacity 2s;
  252. }
  253. .fade-in-out-leave-active {
  254. transition: opacity 2s;
  255. pointer-events: none;
  256. }
  257. .fade-in-out-enter-from {
  258. opacity: 0;
  259. }
  260. .fade-in-out-leave-to {
  261. opacity: 0;
  262. }
  263. // 不断渐变显隐 animation
  264. .animation-show-hide {
  265. animation: show-hide 1.8s infinite;
  266. }
  267. @keyframes show-hide {
  268. 0% {
  269. opacity: 0;
  270. }
  271. 50% {
  272. opacity: 1;
  273. }
  274. 100% {
  275. opacity: 0;
  276. }
  277. }
  278. // // vue-viewer
  279. // .viewer-container {
  280. // background-color: rgba(0, 0, 0, 80%) !important;
  281. // }
  282. // 或者
  283. // .viewer-backdrop {
  284. // background-color: rgba(0, 0, 0, 90%) !important;
  285. // }
  286. </style>
  287. <style lang="less" scoped>
  288. .app-wrap{
  289. height: 100%;
  290. display: flex;
  291. flex-direction: column;
  292. background-image: url(@/assets/images/bg.jpg);
  293. background-size: cover;
  294. background-repeat: no-repeat;
  295. background-position: center center;
  296. font-size: 14px;
  297. >.top-bar{
  298. flex: 0 0 auto;
  299. height: 89px;
  300. background: linear-gradient( 180deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0) 50%, rgba(255,255,255,0.3) 100%);
  301. border-bottom: 1px solid rgba(255, 255, 255, 0.5);
  302. display: flex;
  303. align-items: center;
  304. justify-content: space-around;
  305. >img.logo{
  306. flex: 0 0 auto;
  307. width: 131px;
  308. cursor: pointer;
  309. }
  310. >menu.tab-bar{
  311. flex: 0 0 auto;
  312. display: flex;
  313. align-items: center;
  314. gap: 55px;
  315. @media only screen and (max-width: 1500px) {
  316. gap: 20px;
  317. }
  318. @media only screen and (max-width: 1250px) {
  319. gap: 10px;
  320. }
  321. >button{
  322. font-family: Source Han Sans CN, Source Han Sans CN;
  323. font-weight: 400;
  324. font-size: 22px;
  325. color: #FFFFFF;
  326. line-height: 26px;
  327. position: relative;
  328. z-index: 0;
  329. &:hover{
  330. font-weight: bold;
  331. color: #589498;
  332. }
  333. &.active{
  334. font-weight: bold;
  335. color: #589498;
  336. perspective: 1000px;
  337. &::before{
  338. content: '';
  339. display: block;
  340. position: absolute;
  341. width: 127px;
  342. height: 8px;
  343. background: #589498;
  344. clip-path: polygon(0 0, 100% 0, 97% 100%, 3% 100%);
  345. left: 50%;
  346. top: -31px;
  347. transform: translate(-50%, 0);
  348. }
  349. &::after{
  350. content: '';
  351. display: block;
  352. position: absolute;
  353. z-index: -1;
  354. width: 100%;
  355. top: 100%;
  356. height: 12px;
  357. background: #FFE794;
  358. filter: blur(15.945178985595703px);
  359. }
  360. }
  361. }
  362. }
  363. >.right-button-wrap{
  364. flex: 0 0 auto;
  365. display: flex;
  366. align-items: center;
  367. gap: 14px;
  368. >button.shop{
  369. width: 42px;
  370. height: 42px;
  371. background-image: url(@/assets/images/icon_shop.png);
  372. background-size: cover;
  373. background-repeat: no-repeat;
  374. background-position: center center;
  375. &.active{
  376. background-image: url(@/assets/images/icon_shop-active.png);
  377. background-size: cover;
  378. background-repeat: no-repeat;
  379. background-position: center center;
  380. }
  381. }
  382. >button.hide-top-bar{
  383. width: 42px;
  384. height: 42px;
  385. background-image: url(@/assets/images/button-hide-top-bar.png);
  386. background-size: cover;
  387. background-repeat: no-repeat;
  388. background-position: center center;
  389. }
  390. }
  391. }
  392. >button.show-top-bar{
  393. position: fixed;
  394. top: 0px;
  395. right: 10px;
  396. width: 60px;
  397. height: 60px;
  398. background-image: url(@/assets/images/button-show-top-bar.png);
  399. background-size: cover;
  400. background-repeat: no-repeat;
  401. background-position: center center;
  402. z-index: 2;
  403. }
  404. >.content-area{
  405. flex: 1 0 1px;
  406. position: relative;
  407. z-index: 1;
  408. }
  409. }
  410. </style>