Home.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. <template>
  2. <div class="common-layout">
  3. <el-container style="height: 100%;">
  4. <el-header>
  5. <el-menu :default-active="activeIndex" class="el-menu-demo" mode="horizontal">
  6. <el-menu-item v-for="(item, index) in menuList.list" :key="index" :index="item.menuName" v-show="item.isShow">
  7. <router-link :to="{name: item.router}">{{ item.name }}</router-link>
  8. </el-menu-item>
  9. </el-menu>
  10. <span class="website-name">{{ store.website.name }}</span>
  11. <div class="head-photo" v-show="userInfo?.exp">
  12. <el-dropdown>
  13. <el-avatar :size="35" :src="userInfo?.picture" />
  14. <template #dropdown>
  15. <el-dropdown-menu v-if="userInfo?.name">
  16. <div style="margin: 5px 10px;">
  17. <p>{{ userInfo.name }}</p>
  18. <p>ID: {{ userInfo.sub }}</p>
  19. </div>
  20. <el-dropdown-item @click="gotoInfo()">
  21. <el-icon><Postcard /></el-icon>
  22. {{ $t('home.baseInfo') }}
  23. </el-dropdown-item>
  24. <!-- <el-dropdown-item @click="websiteChange = true">
  25. <el-icon><Postcard /></el-icon>
  26. 切换站点
  27. </el-dropdown-item> -->
  28. <el-dropdown-item @click="loginOut()">
  29. <el-icon><SwitchButton /></el-icon>
  30. {{ $t('home.logout') }}
  31. </el-dropdown-item>
  32. </el-dropdown-menu>
  33. <el-dropdown-menu v-else>
  34. <el-dropdown-item @click="toTeammodel()">
  35. <el-icon><Position /></el-icon>
  36. {{ $t('home.toLogin') }}
  37. </el-dropdown-item>
  38. </el-dropdown-menu>
  39. </template>
  40. </el-dropdown>
  41. </div>
  42. <div class="head-photo" v-show="!userInfo?.exp">
  43. <p @click="toTeammodel()" style="height: 35px; line-height: 35px;">{{ $t('home.login') }}</p>
  44. </div>
  45. </el-header>
  46. <el-main>
  47. <router-view></router-view>
  48. </el-main>
  49. </el-container>
  50. <el-dialog v-model="websiteChange" title="切换站点" width="30%">
  51. <el-select v-model="webSelect" class="m-2" placeholder="请选择要切换的站点">
  52. <el-option v-for="item in otherWebsite" :disabled="item.route === currentSite" :key="item.route" :label="item.name" :value="item.route" />
  53. </el-select>
  54. <template #footer>
  55. <span class="dialog-footer">
  56. <!-- <el-button @click="dialogVisible = false">Cancel</el-button> -->
  57. <el-button type="primary" @click="webSelChange()">切换</el-button>
  58. </span>
  59. </template>
  60. </el-dialog>
  61. </div>
  62. </template>
  63. <script setup>
  64. import { computed, getCurrentInstance, onMounted, reactive, ref, toRaw, watch } from "vue"
  65. import { useRoute, useRouter } from 'vue-router'
  66. // import { useStore } from "vuex"
  67. import { SwitchButton, Postcard, Position } from '@element-plus/icons-vue'
  68. import { useStore } from "@/pinia/common"
  69. import { ElLoading, ElMessage } from "element-plus"
  70. import jwtDecode from "jwt-decode"
  71. const router = useRouter()
  72. const route = useRoute()
  73. let store = useStore()
  74. let { proxy } = getCurrentInstance()
  75. let activeIndex = ref(route.meta.activeName)
  76. let websiteChange = ref(false)
  77. let webSelect = ref("")
  78. let otherWebsite = ref([])
  79. let userInfo = ref({})
  80. let isExpert = computed(() => {
  81. if(store.userInfo.roles && store.userInfo.roles.includes('expert')) {
  82. return true
  83. } else {
  84. return false
  85. }
  86. })
  87. let menuList = reactive({list: [
  88. {
  89. name: proxy.$t('home.menulist.homepage'),
  90. menuName: 'home',
  91. router: 'homePage',
  92. isShow: true
  93. },
  94. {
  95. name: proxy.$t('home.menulist.myActivity'),
  96. menuName: 'myActivity',
  97. router: 'myActivity',
  98. isShow: true
  99. },
  100. {
  101. name: proxy.$t('home.menulist.myReview'),
  102. menuName: 'myReview',
  103. router: 'myReview',
  104. isShow: isExpert
  105. }
  106. ]})
  107. onMounted(() => {
  108. if(localStorage.getItem("auth_token")) {
  109. let infos = jwtDecode(localStorage.getItem("auth_token"))
  110. userInfo.value = infos
  111. store.setUserInfo(infos)
  112. let schools = JSON.parse(localStorage.getItem("schools"))
  113. store.setSchoolList(schools)
  114. }
  115. })
  116. await getWebsite()
  117. function gotoInfo() {
  118. activeIndex.value = '-1'
  119. router.push("/home/basicInfo")
  120. }
  121. function loginOut() {
  122. localStorage.removeItem("auth_token")
  123. localStorage.removeItem("access_token")
  124. localStorage.removeItem("access_token")
  125. localStorage.removeItem("expires_in")
  126. store.setSchoolList([])
  127. store.setUserInfo({})
  128. userInfo.value = {}
  129. menuList.list.splice(2, 1)
  130. router.push({path: '/home/homePage'})
  131. ElMessage({
  132. type: 'warning',
  133. message: proxy.$t('elMessage.logout')
  134. })
  135. // location.href = "https://account.teammodel.cn/?callback=" + window.location.href
  136. }
  137. function getWebsite() {
  138. return new Promise((r, j) => {
  139. /* const loading = ElLoading.service({
  140. lock: true,
  141. text: '加载中',
  142. background: 'rgba(0, 0, 0, 0.7)'
  143. }) */
  144. let areaRoute = window.location.pathname.split('/')
  145. let params = {
  146. route: areaRoute[1]
  147. }
  148. proxy.$api.getWebsite(params).then(res => {
  149. if(res.code === 200) {
  150. // res.website.blobUrl = res.blobUrl
  151. store.setWebsite(res.website)
  152. otherWebsite.value = res.websites
  153. } else if(res.code === 2) {
  154. ElMessage({
  155. type: 'error',
  156. message: proxy.$t('elMessage.noRoute')
  157. })
  158. }
  159. r(200)
  160. }).finally(() => {
  161. // loading.close()
  162. })
  163. })
  164. }
  165. function webSelChange() {
  166. /* let host = window.location.host
  167. location.href = host + '/' + webSelect.value + '/home/homePage' */
  168. // 切换到对应站点???
  169. }
  170. function toTeammodel() {
  171. location.href = "https://account.teammodel.cn/?callback=" + window.location.href
  172. }
  173. function login() {
  174. /* const loading = ElLoading.service({
  175. lock: true,
  176. text: '登录中',
  177. background: 'rgba(0, 0, 0, 0.7)'
  178. }) */
  179. // 获取登录后返回的ticket
  180. let search = window.location.search
  181. let ticket = ''
  182. let token = ''
  183. if(search.includes('ticket')) {
  184. ticket = search.split('?')[1].split("&")[0].split('ticket=')[1]
  185. } else if(search.includes('token')) {
  186. token = search.split('?token=')[1]
  187. }
  188. let areaRoute = window.location.pathname.split('/')
  189. // ticket 只用一次,不用存在localStorage
  190. // token token过期或从其他活动跳转过来传
  191. let params = {
  192. route: areaRoute[1],
  193. }
  194. if(ticket) {
  195. params.ticket = ticket
  196. } else if(token) {
  197. params.token = token
  198. } else {
  199. params.token = localStorage.getItem("auth_token")
  200. }
  201. proxy.$api.loginPortal(params).then(res => {
  202. if(res.code === 200) {
  203. if(ticket || token) router.push({path: '/home/homePage'})
  204. if(!localStorage.getItem("auth_token")) localStorage.setItem("auth_token", res.token)
  205. localStorage.setItem("access_token", res.auth_token.access_token)
  206. localStorage.setItem("schools", JSON.stringify(res.schools))
  207. localStorage.setItem("expires_in", res.auth_token.expires_in)
  208. store.setSchoolList(res.schools)
  209. store.setUserInfo(jwtDecode(res.token))
  210. userInfo.value = jwtDecode(res.token)
  211. } else {
  212. localStorage.removeItem("auth_token")
  213. localStorage.removeItem("access_token")
  214. localStorage.removeItem("access_token")
  215. localStorage.removeItem("expires_in")
  216. sessionStorage.setItem('loginOut', res.msg)
  217. store.setSchoolList([])
  218. store.setUserInfo({})
  219. userInfo.value = {}
  220. router.push({path: '/home/homePage'})
  221. ElMessage({
  222. type: 'warning',
  223. message: '请重新登录'
  224. })
  225. }
  226. }).finally(() => {
  227. // loginLoad.close()
  228. })
  229. }
  230. let currentSite = computed(() => {
  231. return window.location.pathname.split('/')[1]
  232. })
  233. // 监听是否带参数,
  234. let ticket = computed(() => {
  235. let search = window.location.search
  236. if(search.includes('ticket')) {
  237. return search.split('?')[1].split("&")[0].split('ticket=')[1]
  238. } else {
  239. return ''
  240. }
  241. })
  242. // 监听是否带参数,
  243. let authToken = computed(() => {
  244. let search = window.location.search
  245. if(search.includes('token')) {
  246. return search.split('?token=')[1]
  247. } else {
  248. return ''
  249. }
  250. })
  251. watch(route, (newVal, oldVal) => {
  252. activeIndex.value = newVal.meta.activeName
  253. }, {deep: true}, {immediate: true})
  254. watch([ticket, authToken], ([newValue1, newValue2], [oldValue1, oldValue2]) => {
  255. if([newValue1, newValue2]) {
  256. login()
  257. }
  258. }, {immediate: true})
  259. </script>
  260. <style lang="less">
  261. .common-layout {
  262. height: 100%;
  263. .el-main {
  264. padding: 0;
  265. height: 100%;
  266. }
  267. .head-photo {
  268. position: absolute;
  269. top: 11px;
  270. right: 40px;
  271. margin-right: 40px;
  272. cursor: pointer;
  273. .user_avatar{
  274. width: 36px;
  275. height: 36px;
  276. border-radius: 50%;
  277. background-color: #72727f;
  278. }
  279. }
  280. .website-name {
  281. position: absolute;
  282. left: 50%;
  283. top: 50%;
  284. transform: translate(-50%, -50%);
  285. font-size: 1.5rem;
  286. }
  287. .el-header {
  288. position: relative;
  289. // padding: 0;
  290. // border-bottom: solid 1px var(--el-menu-border-color);
  291. background-color: #15559a;
  292. color: #fff;
  293. a {
  294. text-decoration: none; /* 移除链接默认的下划线 */
  295. }
  296. .el-menu {
  297. background-color: #15559a;
  298. min-width: 350px;
  299. }
  300. .el-menu--horizontal.el-menu {
  301. border-bottom: none;
  302. }
  303. .el-menu--horizontal>.el-menu-item {
  304. color: #F1F1E6;
  305. }
  306. .el-menu--horizontal>.el-menu-item.is-active {
  307. border-bottom-color: #fff;
  308. // border-bottom: none;
  309. color: #fff !important;
  310. // font-size: 16px;
  311. font-weight: bold;
  312. }
  313. .el-menu--horizontal .el-menu-item:not(.is-disabled):focus, .el-menu--horizontal .el-menu-item:not(.is-disabled):hover {
  314. background-color: #15559a;
  315. // font-size: 16px;
  316. // font-weight: bold;
  317. border-bottom: 2px solid #fff;
  318. }
  319. }
  320. .el-avatar {
  321. outline: none;
  322. }
  323. }
  324. </style>