master
fwb 7 months ago
commit f074bef41e
  1. 5
      teaching_integration_platform_admin_template/.env.development
  2. 1
      teaching_integration_platform_admin_template/.env.production
  3. 24
      teaching_integration_platform_admin_template/src/App.vue
  4. 28
      teaching_integration_platform_admin_template/src/layout/tabbar/setting/index.vue
  5. 2
      teaching_integration_platform_admin_template/src/permission.ts
  6. 1
      teaching_integration_platform_admin_template/src/store/modules/type/types.ts
  7. 11
      teaching_integration_platform_admin_template/src/store/modules/user.ts
  8. 7
      teaching_integration_platform_admin_template/src/utils/token.ts
  9. 94
      teaching_integration_platform_admin_template/src/views/home/index.vue
  10. 221
      teaching_integration_platform_admin_template/src/views/login/index.vue
  11. 3
      teaching_integration_platform_admin_template/vite.config.ts
  12. 5
      teaching_integration_platform_template/.env.development
  13. 1
      teaching_integration_platform_template/.env.production
  14. 2
      teaching_integration_platform_template/src/App.vue
  15. 47
      teaching_integration_platform_template/src/Layout/tabbar/index.vue
  16. 28
      teaching_integration_platform_template/src/store/module/user.ts

@ -1,6 +1,7 @@
# 变量必须以 VITE_ 为前缀才能暴露给外部读取 # 变量必须以 VITE_ 为前缀才能暴露给外部读取
NODE_ENV = 'development' NODE_ENV = 'development'
VITE_APP_TITLE = '无糖运营平台' VITE_APP_TITLE = '无糖运营平台'
# VITE_APP_BASE_API = 'http://127.0.0.1:8080' VITE_APP_BASE_API = 'http://127.0.0.1:8080'
VITE_APP_BASE_API = 'http://39.106.16.162:8080' VITE_APP_OTHER_ORIGIN = 'http://127.0.0.1:8866'
# VITE_APP_BASE_API = 'http://39.106.16.162:8080'

@ -1,3 +1,4 @@
NODE_ENV = 'production' NODE_ENV = 'production'
VITE_APP_TITLE = '无糖运营平台' VITE_APP_TITLE = '无糖运营平台'
VITE_APP_OTHER_ORIGIN = 'http://39.106.16.162:8866'
# VITE_APP_BASE_API = '/prod-api' # VITE_APP_BASE_API = '/prod-api'

@ -3,7 +3,6 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
// import { useRouter, useRoute } from 'vue-router' // import { useRouter, useRoute } from 'vue-router'
// vue3 compositionAPI // vue3 compositionAPI
// 1. router useRouter // 1. router useRouter
@ -17,6 +16,29 @@
// import {} from 'vue' // import {} from 'vue'
// import { useUserStore } from '@/stores/user.js' // import { useUserStore } from '@/stores/user.js'
// const userStore = useUserStore() // const userStore = useUserStore()
// ====================
import useUserStore from './store/modules/user'
import { nextTick } from 'vue'
const userStore = useUserStore()
nextTick(() => {
const opener = window.opener
if (opener) {
const handle = (token: any) => {
// 退使退
opener.postMessage(token, import.meta.env.VITE_APP_OTHER_ORIGIN)
}
handle(userStore.token)
userStore.loginE.onLogin = handle
}
})
window.onmessage = e => {
if (e.origin === import.meta.env.VITE_APP_OTHER_ORIGIN) {
userStore.logout()
location.reload()
}
}
// ====================
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>

@ -11,18 +11,11 @@
/> --> /> -->
<el-button size="small" icon="refresh" circle @click="refresh" /> <el-button size="small" icon="refresh" circle @click="refresh" />
<el-button size="small" icon="FullScreen" circle @click="fullScreen" /> <el-button size="small" icon="FullScreen" circle @click="fullScreen" />
<el-button v-if="userStore.userInfo.roleId[0] === '1'" size="small" icon="Setting" circle @click="$router.push('/configurationPage')" /> <el-button v-if="userStore.userInfo.roleId[0] === '1'" size="small" icon="Setting" circle
<el-button @click="$router.push('/configurationPage')" />
size="small" <el-button size="small" icon="Link" circle @click="openWeb" />
icon="Link" <img :src="userStore.data.icon || defImg" alt=""
circle style="width: 24px; height: 24px; margin: 0 10px; border-radius: 50%" />
@click="openWeb"
/>
<img
:src="userStore.data.icon || defImg"
alt=""
style="width: 24px; height: 24px; margin: 0 10px; border-radius: 50%"
/>
<!-- <img <!-- <img
src="@/assets/images/default.jpg src="@/assets/images/default.jpg
alt="" alt=""
@ -48,11 +41,11 @@
// import { useDark, useToggle } from '@vueuse/core' // import { useDark, useToggle } from '@vueuse/core'
import useLayoutSettingStoe from '@/store/modules/setting' import useLayoutSettingStoe from '@/store/modules/setting'
import useUserStore from '@/store/modules/user' import useUserStore from '@/store/modules/user'
import { onMounted,ref } from 'vue' import { onMounted, ref } from 'vue'
import { useRouter, useRoute } from 'vue-router' import { useRouter, useRoute } from 'vue-router'
// import default from '@/assets/images/default.jpg' // import default from '@/assets/images/default.jpg'
import defImg from '@/assets/images/default.png' import defImg from '@/assets/images/default.png'
import {getSysSettingApi} from '@/api/configuration' import { getSysSettingApi } from '@/api/configuration'
// import { Moon, Sunny } from '@element-plus/icons-vue' // import { Moon, Sunny } from '@element-plus/icons-vue'
const useStore = useLayoutSettingStoe() const useStore = useLayoutSettingStoe()
@ -75,7 +68,7 @@ const refresh = () => {
} }
const setting = ref() const setting = ref()
const getSysSettingApiEvent = async () => { const getSysSettingApiEvent = async () => {
const res =await getSysSettingApi() const res = await getSysSettingApi()
setting.value = res.data setting.value = res.data
console.log(res); console.log(res);
@ -99,10 +92,13 @@ onMounted(() => {
userStore.getUserInfo() userStore.getUserInfo()
// console.log(userStore.data.icon, 'icon') // console.log(userStore.data.icon, 'icon')
}) })
const channel = new BroadcastChannel('logout')
channel.onmessage = () => location.reload()
const logout = () => { const logout = () => {
// console.log($route) // console.log($route)
channel.postMessage('')
userStore.logout() userStore.logout()
$router.push({ $router.push({
path: '/login', path: '/login',
query: { redirect: $route.path }, query: { redirect: $route.path },

@ -6,7 +6,7 @@ import permissionStore from '@/store/modules/permission'
//@ts-expect-error 修复ts校验 //@ts-expect-error 修复ts校验
import nprogress from 'nprogress' import nprogress from 'nprogress'
import 'nprogress/nprogress.css' import 'nprogress/nprogress.css'
const userStore :any = useUserStore(pinia) const userStore: any = useUserStore(pinia)
const usePermissionStore = permissionStore(pinia) const usePermissionStore = permissionStore(pinia)
// const whitelist = ['/login', '/404'] // const whitelist = ['/login', '/404']
router.beforeEach(async (to, form, next) => { router.beforeEach(async (to, form, next) => {

@ -8,4 +8,5 @@ export interface LoginStoreType {
phone: string phone: string
userInfo: object userInfo: object
data: object data: object
loginE: Record<'onLogin', null | (() => void)>
} }

@ -11,7 +11,7 @@ import { GET_TKOEN, SET_TKOEN, REMOVE_TOKEN } from '@/utils/token'
// 引入常量路由 // 引入常量路由
import { constantRoute } from '@/router/routers' import { constantRoute } from '@/router/routers'
import permissionStore from './permission' import permissionStore from './permission'
import {useRouter} from 'vue-router' import { useRouter } from 'vue-router'
// 引入路由 // 引入路由
import { import {
userLoginService, userLoginService,
@ -32,6 +32,7 @@ const useUserStore = defineStore('User', {
phone: '', phone: '',
userInfo: {}, // 当前用户相关信息 userInfo: {}, // 当前用户相关信息
data: {}, data: {},
loginE: { onLogin: null }
} }
}, },
actions: { actions: {
@ -44,7 +45,7 @@ const useUserStore = defineStore('User', {
}) })
if (res.code === 200) { if (res.code === 200) {
this.token = res.data.token as string this.token = res.data.token as string
SET_TKOEN('TOKEN', this.token) SET_TKOEN('TOKEN', this.token, this.loginE.onLogin)
// localStorage.setItem('TOKEN', this.token) // localStorage.setItem('TOKEN', this.token)
ElNotification({ ElNotification({
type: 'success', type: 'success',
@ -68,7 +69,7 @@ const useUserStore = defineStore('User', {
if (res.code === 200) { if (res.code === 200) {
this.token = res.data.token as string //接收返回的token this.token = res.data.token as string //接收返回的token
// @ts-expect-error // @ts-expect-error
SET_TKOEN('TOKEN', this.token) SET_TKOEN('TOKEN', this.token, this.loginE.onLogin)
// localStorage.setItem('TOKEN', this.token) // localStorage.setItem('TOKEN', this.token)
ElNotification({ ElNotification({
type: 'success', type: 'success',
@ -107,7 +108,7 @@ const useUserStore = defineStore('User', {
const usePermissionStore = permissionStore() const usePermissionStore = permissionStore()
// console.log(usePermissionStore) // console.log(usePermissionStore)
// 清除token // 清除token
REMOVE_TOKEN('TOKEN'), REMOVE_TOKEN('TOKEN', this.loginE.onLogin),
// ;(this.userName = ''), (this.avatar = '') // ;(this.userName = ''), (this.avatar = '')
// @ts-expect-error // @ts-expect-error
(this.userName = ''), (this.userName = ''),
@ -125,7 +126,7 @@ const useUserStore = defineStore('User', {
}, },
}, },
getters: {}, getters: {},
}, },
{ {
persist: true, // 持久化 persist: true, // 持久化
}, },

@ -1,12 +1,15 @@
// 设置token // 设置token
export const SET_TKOEN = (name: string, data: string) => { type OnLogin = null | ((token: any) => void)
export const SET_TKOEN = (name: string, data: string, onLogin: OnLogin) => {
localStorage.setItem(name, data) localStorage.setItem(name, data)
if (onLogin) onLogin(data)
} }
// 获取token // 获取token
export const GET_TKOEN = (name: string) => { export const GET_TKOEN = (name: string) => {
return localStorage.getItem(name) return localStorage.getItem(name)
} }
// 移除token // 移除token
export const REMOVE_TOKEN = (name: string) => { export const REMOVE_TOKEN = (name: string, onLogin: OnLogin) => {
localStorage.removeItem(name) localStorage.removeItem(name)
if (onLogin) onLogin('')
} }

@ -123,14 +123,8 @@ onMounted(() => {
<el-row> <el-row>
<el-col :span="24"> <el-col :span="24">
<div class="nav"> <div class="nav">
<welcome <welcome :data="infoData" :userData="userStore.data" :name="name" @get-message="getMessage"
:data="infoData" @userInfoModified="fetchNewUserInfo" v-if="flag"></welcome>
:userData="userStore.data"
:name="name"
@get-message="getMessage"
@userInfoModified="fetchNewUserInfo"
v-if="flag"
></welcome>
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
@ -142,41 +136,31 @@ onMounted(() => {
</el-col> </el-col>
<el-col :span="6"> <el-col :span="6">
<div class="info"> <div class="info">
<status <status :data="userStore.data" :userData="infoData" @get-avater="getAvater" @getInfo="getInfo" v-if="flag">
:data="userStore.data" </status>
:userData="infoData"
@get-avater="getAvater"
@getInfo="getInfo"
v-if="flag"
></status>
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="6"> <el-col :span="6">
<div class="lesson"> <div class="lesson">
<a <a href="#" style="
href="#"
style="
font-size: 14px; font-size: 14px;
display: flex; display: flex;
width: 90%; width: 90%;
margin: 0px auto; margin: 0px auto;
/* margin: 0px 10px; */ /* margin: 0px 10px; */
margin-bottom: 5px; margin-bottom: 5px;
" ">
> <conheader :title="`学习最多知识点`" :urouter="'/curriculumCenter/knowledgePoints'"></conheader>
<conheader
:title="`学习最多知识点`"
:urouter="'/curriculumCenter/knowledgePoints'"
></conheader>
</a> </a>
<div class="contt"> <div class="contt">
<!-- <p class="button" round v-for="item in topKnow" :key="item.id"> <!-- <p class="button" round v-for="item in topKnow" :key="item.id">
{{ item.label }} {{ item.label }}
</p> --> </p> -->
<el-table :data="topKnow" border style="width: 100%" height="240" :header-cell-style="{'text-align':'center'}"> <el-table :data="topKnow" border style="width: 100%" height="240"
<el-table-column type="index" align=center label="序号" width="80"/> :header-cell-style="{ 'text-align': 'center' }">
<el-table-column type="index" align=center label="序号" width="80" />
<el-table-column prop="label" align=center label="课程名称" /> <el-table-column prop="label" align=center label="课程名称" />
</el-table> </el-table>
</div> </div>
@ -184,24 +168,22 @@ onMounted(() => {
</el-col> </el-col>
<el-col :span="6"> <el-col :span="6">
<div class="lesson"> <div class="lesson">
<a <a href="#" style="
href="#"
style="
width: 90%; width: 90%;
font-size: 14px; font-size: 14px;
display: flex; display: flex;
margin: 0 auto; margin: 0 auto;
margin-bottom: 5px; margin-bottom: 5px;
" ">
>
<conheader :title="`推荐知识点`"></conheader> <conheader :title="`推荐知识点`"></conheader>
</a> </a>
<div class="contt"> <div class="contt">
<!-- <p class="button" round v-for="item in maxKnow" :key="item.id"> <!-- <p class="button" round v-for="item in maxKnow" :key="item.id">
{{ item.label }} {{ item.label }}
</p> --> </p> -->
<el-table :data="maxKnow" border style="width: 100%" height="240" :header-cell-style="{'text-align':'center'}"> <el-table :data="maxKnow" border style="width: 100%" height="240"
<el-table-column type="index" align=center label="序号" width="80"/> :header-cell-style="{ 'text-align': 'center' }">
<el-table-column type="index" align=center label="序号" width="80" />
<el-table-column prop="label" align=center label="课程名称" /> <el-table-column prop="label" align=center label="课程名称" />
</el-table> </el-table>
</div> </div>
@ -209,14 +191,8 @@ onMounted(() => {
</el-col> </el-col>
<el-col :span="6"> <el-col :span="6">
<div class="lesson"> <div class="lesson">
<a <a href="#" style="width: 90%; font-size: 14px; display: flex; margin: 0 auto">
href="#" <conheader :title="`推荐课程`" :urouter="'/curriculumCenter/basicCourseInformation'"></conheader>
style="width: 90%; font-size: 14px; display: flex; margin: 0 auto"
>
<conheader
:title="`推荐课程`"
:urouter="'/curriculumCenter/basicCourseInformation'"
></conheader>
</a> </a>
<div class="con"> <div class="con">
<!-- <ul> <!-- <ul>
@ -231,8 +207,9 @@ onMounted(() => {
</div> </div>
</li> </li>
</ul> --> </ul> -->
<el-table :data="toplist" border style="width: 100%" height="240" :header-cell-style="{'text-align':'center'}"> <el-table :data="toplist" border style="width: 100%" height="240"
<el-table-column type="index" align=center label="序号" width="80"/> :header-cell-style="{ 'text-align': 'center' }">
<el-table-column type="index" align=center label="序号" width="80" />
<el-table-column prop="name" align=center label="课程名称" /> <el-table-column prop="name" align=center label="课程名称" />
</el-table> </el-table>
</div> </div>
@ -240,14 +217,8 @@ onMounted(() => {
</el-col> </el-col>
<el-col :span="6"> <el-col :span="6">
<div class="lesson"> <div class="lesson">
<a <a href="#" style="width: 90%; font-size: 12px; display: flex; margin: 0 auto">
href="#" <conheader :title="`最新收藏课程`" :urouter="'/curriculumCenter/basicCourseInformation'"></conheader>
style="width: 90%; font-size: 12px; display: flex; margin: 0 auto"
>
<conheader
:title="`最新收藏课程`"
:urouter="'/curriculumCenter/basicCourseInformation'"
></conheader>
</a> </a>
<div class="con"> <div class="con">
<!-- <ul> <!-- <ul>
@ -262,8 +233,9 @@ onMounted(() => {
</div> </div>
</li> </li>
</ul> --> </ul> -->
<el-table :data="courselist" border style="width: 100%" height="240" :header-cell-style="{'text-align':'center'}"> <el-table :data="courselist" border style="width: 100%" height="240"
<el-table-column type="index" align=center label="序号" width="80"/> :header-cell-style="{ 'text-align': 'center' }">
<el-table-column type="index" align=center label="序号" width="80" />
<el-table-column prop="name" align=center label="课程名称" /> <el-table-column prop="name" align=center label="课程名称" />
</el-table> </el-table>
</div> </div>
@ -287,6 +259,7 @@ onMounted(() => {
* { * {
box-sizing: border-box; box-sizing: border-box;
} }
.nav { .nav {
height: 92px; height: 92px;
background: #ffffff; background: #ffffff;
@ -298,6 +271,7 @@ onMounted(() => {
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }
.classList, .classList,
.info { .info {
// background-color: yellow; // background-color: yellow;
@ -309,10 +283,12 @@ onMounted(() => {
align-items: center; align-items: center;
margin-bottom: 16px; margin-bottom: 16px;
} }
.classList { .classList {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
} }
.lesson { .lesson {
padding-top: 30px; padding-top: 30px;
// padding-bottom: 30px; // padding-bottom: 30px;
@ -326,6 +302,7 @@ onMounted(() => {
text-overflow: ellipsis; text-overflow: ellipsis;
// flex-direction: column; // flex-direction: column;
} }
.con { .con {
display: flex; display: flex;
// justify-content: space-between; // justify-content: space-between;
@ -340,6 +317,7 @@ onMounted(() => {
justify-content: space-evenly; justify-content: space-evenly;
padding-bottom: 30px; padding-bottom: 30px;
} }
.contt { .contt {
// background-color: yellow; // background-color: yellow;
padding: 5px; padding: 5px;
@ -348,9 +326,11 @@ onMounted(() => {
// grid-template-columns: repeat(2, 1fr); // grid-template-columns: repeat(2, 1fr);
// grid-gap: 11px; // grid-gap: 11px;
} }
:deep(.el-scrollbar__wrap) { :deep(.el-scrollbar__wrap) {
padding: 0; padding: 0;
} }
.button { .button {
justify-content: space-between; justify-content: space-between;
@ -367,13 +347,16 @@ onMounted(() => {
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
} }
.button :hover { .button :hover {
overflow: visible; overflow: visible;
white-space: normal; white-space: normal;
} }
a { a {
text-decoration: none; text-decoration: none;
} }
.some, .some,
.stu { .stu {
padding-top: 5px; padding-top: 5px;
@ -387,6 +370,7 @@ a {
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }
// .lessonlist-content { // .lessonlist-content {
// display: flex; // display: flex;
// justify-content: center; // justify-content: center;
@ -417,12 +401,14 @@ ul {
justify-content: space-between; justify-content: space-between;
// align-items: center; // align-items: center;
} }
.lessonlist-item-img { .lessonlist-item-img {
width: 17%; width: 17%;
height: 40px; height: 40px;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }
.lessonlist-item-info { .lessonlist-item-info {
margin-left: 15px; margin-left: 15px;
width: 80%; width: 80%;
@ -432,11 +418,13 @@ ul {
// flex-direction: column; // flex-direction: column;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
h5 { h5 {
// font-weight: bold; // font-weight: bold;
width: 80%; width: 80%;
text-align: center; text-align: center;
} }
p { p {
font-size: small; font-size: small;
width: 20%; width: 20%;

@ -22,23 +22,13 @@
</el-col> </el-col>
</el-row> </el-row>
<el-row> <el-row>
<el-col <el-col :span="12" :xs="24" style="
:span="12"
:xs="24"
style="
width: 100%; width: 100%;
height: 100%; height: 100%;
display: flex; display: flex;
justify-content: center; justify-content: center;
" ">
> <el-form class="loin_form" :model="formModel" ref="form" :rules="rules" v-if="isRegister">
<el-form
class="loin_form"
:model="formModel"
ref="form"
:rules="rules"
v-if="isRegister"
>
<h1>课图开源智慧课程管理系统</h1> <h1>课图开源智慧课程管理系统</h1>
<div class="taggle"> <div class="taggle">
<h2 @click="isToggle = true">账号</h2> <h2 @click="isToggle = true">账号</h2>
@ -47,31 +37,14 @@
<!-- 账号登录 --> <!-- 账号登录 -->
<div v-if="isToggle"> <div v-if="isToggle">
<el-form-item prop="username"> <el-form-item prop="username">
<el-input <el-input v-model="formModel.username" :prefix-icon="User" size="large" placeholder="请输入账号"></el-input>
v-model="formModel.username"
:prefix-icon="User"
size="large"
placeholder="请输入账号"
></el-input>
</el-form-item> </el-form-item>
<el-form-item prop="password"> <el-form-item prop="password">
<el-input <el-input v-model="formModel.password" type="password" :prefix-icon="Lock" size="large"
v-model="formModel.password" placeholder="请输入密码" show-password></el-input>
type="password"
:prefix-icon="Lock"
size="large"
placeholder="请输入密码"
show-password
></el-input>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button <el-button :loading="isBtnLoading" size="large" class="login-btn" type="primary" @click="login">
:loading="isBtnLoading"
size="large"
class="login-btn"
type="primary"
@click="login"
>
登录 登录
</el-button> </el-button>
</el-form-item> </el-form-item>
@ -79,44 +52,21 @@
<!-- 手机号登录 --> <!-- 手机号登录 -->
<div v-else> <div v-else>
<el-form-item prop="phone" class="content"> <el-form-item prop="phone" class="content">
<el-input <el-input type="text" v-model="formModel.phone" :prefix-icon="Phone" placeholder="请输入手机号" size="large"
type="text" style="flex: 1" />
v-model="formModel.phone"
:prefix-icon="Phone"
placeholder="请输入手机号"
size="large"
style="flex: 1"
/>
</el-form-item> </el-form-item>
<el-form-item prop="code" class="content"> <el-form-item prop="code" class="content">
<el-input <el-input type="text" v-model="formModel.code" placeholder="请输入验证码" @click="userCodeLogin" size="large"
type="text" style="flex: 1" />
v-model="formModel.code"
placeholder="请输入验证码"
@click="userCodeLogin"
size="large"
style="flex: 1"
/>
<div class="p" v-if="countdown > 0"> <div class="p" v-if="countdown > 0">
<p>{{ countdown }} </p> <p>{{ countdown }} </p>
</div> </div>
<el-button <el-button class="code" v-if="countdown <= 0" :disabled="countdown > 0" @click="codeSubmit">
class="code"
v-if="countdown <= 0"
:disabled="countdown > 0"
@click="codeSubmit"
>
发送验证码 发送验证码
</el-button> </el-button>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button <el-button :loading="isBtnLoading" size="large" class="login-btn" type="primary" @click="phoneLogin">
:loading="isBtnLoading"
size="large"
class="login-btn"
type="primary"
@click="phoneLogin"
>
登录 登录
</el-button> </el-button>
</el-form-item> </el-form-item>
@ -128,13 +78,7 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
<!-- 注册 --> <!-- 注册 -->
<el-form <el-form class="loin_form" :model="formModel" ref="form" :rules="rules" v-else>
class="loin_form"
:model="formModel"
ref="form"
:rules="rules"
v-else
>
<h1>Hello</h1> <h1>Hello</h1>
<div class="taggle"> <div class="taggle">
<h2 @click="isToggle = true">账号</h2> <h2 @click="isToggle = true">账号</h2>
@ -143,51 +87,24 @@
<!-- 账号注册 --> <!-- 账号注册 -->
<div v-if="isToggle"> <div v-if="isToggle">
<el-form-item prop="username"> <el-form-item prop="username">
<el-input <el-input v-model="formModel.username" placeholder="请输入用户名" :prefix-icon="User" size="large"></el-input>
v-model="formModel.username"
placeholder="请输入用户名"
:prefix-icon="User"
size="large"
></el-input>
</el-form-item> </el-form-item>
<el-form-item prop="password"> <el-form-item prop="password">
<el-input <el-input v-model="formModel.password" placeholder="请输入密码" type="password" :prefix-icon="Lock"
v-model="formModel.password" size="large" show-password></el-input>
placeholder="请输入密码"
type="password"
:prefix-icon="Lock"
size="large"
show-password
></el-input>
</el-form-item> </el-form-item>
<el-form-item prop="repassword"> <el-form-item prop="repassword">
<el-input <el-input v-model="formModel.repassword" placeholder="请再次输入密码" type="password" :prefix-icon="Check"
v-model="formModel.repassword" size="large" show-repassword @change="checkPasswordMatch"></el-input>
placeholder="请再次输入密码"
type="password"
:prefix-icon="Check"
size="large"
show-repassword
@change="checkPasswordMatch"
></el-input>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button <el-button size="large" class="login-btn" type="primary" @click="handleSubmit">
size="large"
class="login-btn"
type="primary"
@click="handleSubmit"
>
注册 注册
</el-button> </el-button>
</el-form-item> </el-form-item>
<el-form-item class="flex"> <el-form-item class="flex">
<el-link <el-link type="info" :underline="false" @click="isRegister = true">
type="info"
:underline="false"
@click="isRegister = true"
>
登录 登录
</el-link> </el-link>
</el-form-item> </el-form-item>
@ -196,99 +113,58 @@
<div v-else> <div v-else>
<div v-if="isinfo"> <div v-if="isinfo">
<el-form-item prop="phone"> <el-form-item prop="phone">
<el-input <el-input v-model="formModel.phone" :prefix-icon="Phone" size="large" placeholder="请输入手机号"></el-input>
v-model="formModel.phone"
:prefix-icon="Phone"
size="large"
placeholder="请输入手机号"
></el-input>
</el-form-item> </el-form-item>
<el-form-item prop="code" class="content"> <el-form-item prop="code" class="content">
<el-input <el-input type="text" v-model="formModel.code" placeholder="请输入验证码" size="large" style="
type="text"
v-model="formModel.code"
placeholder="请输入验证码"
size="large"
style="
flex: 1; flex: 1;
/* height: 40px; /* height: 40px;
line-height: 40px; line-height: 40px;
border: 1px solid #dcdfe6; border: 1px solid #dcdfe6;
width: 50%; width: 50%;
color: #dcdfe6; */ color: #dcdfe6; */
" " />
/>
<div class="p" v-if="countdown > 0"> <div class="p" v-if="countdown > 0">
<p>{{ countdown }} </p> <p>{{ countdown }} </p>
</div> </div>
<el-button <el-button class="code1" v-if="countdown <= 0" @click="codeSubmit" :disabled="countdown > 0">
class="code1"
v-if="countdown <= 0"
@click="codeSubmit"
:disabled="countdown > 0"
>
发送验证码 发送验证码
</el-button> </el-button>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button <el-button size="large" class="login-btn" type="primary" @click="phoneChange">
size="large"
class="login-btn"
type="primary"
@click="phoneChange"
>
注册 注册
</el-button> </el-button>
</el-form-item> </el-form-item>
</div> </div>
<div v-else> <div v-else>
<el-form-item prop="password"> <el-form-item prop="password">
<el-input <el-input v-model="formModel.password" type="password" :prefix-icon="Lock" size="large"
v-model="formModel.password" placeholder="请输入密码" show-password></el-input>
type="password"
:prefix-icon="Lock"
size="large"
placeholder="请输入密码"
show-password
></el-input>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<div <div style="display: flex; justify-content: space-between; flex: 1">
style="display: flex; justify-content: space-between; flex: 1" <el-button class="code" @click="phoneReturn" style="
>
<el-button
class="code"
@click="phoneReturn"
style="
background-color: #5577ff; background-color: #5577ff;
color: #fff; color: #fff;
justify-content: center; justify-content: center;
" ">
>
返回 返回
</el-button> </el-button>
</div> </div>
<div style="display: flex; justify-content: end; flex: 1"> <div style="display: flex; justify-content: end; flex: 1">
<el-button <el-button class="code" @click="phoneSubmit" style="
class="code"
@click="phoneSubmit"
style="
background-color: #5577ff; background-color: #5577ff;
color: #fff; color: #fff;
justify-content: center; justify-content: center;
" ">
>
确认 确认
</el-button> </el-button>
</div> </div>
</el-form-item> </el-form-item>
</div> </div>
<el-form-item class="flex"> <el-form-item class="flex">
<el-link <el-link type="info" :underline="false" @click="isRegister = true">
type="info"
:underline="false"
@click="isRegister = true"
>
登录 登录
</el-link> </el-link>
</el-form-item> </el-form-item>
@ -323,6 +199,7 @@ const goToPage = (event) => {
// window.open('https:www.baidu.com', '_blank') // window.open('https:www.baidu.com', '_blank')
window.location.href = 'https:www.baidu.com' window.location.href = 'https:www.baidu.com'
} }
const fold = ref(false) const fold = ref(false)
const LayoutSettingStoe = useLayoutSettingStoe() const LayoutSettingStoe = useLayoutSettingStoe()
// //
@ -330,6 +207,10 @@ let userStore = useUserStore()
// //
const $router = useRouter() const $router = useRouter()
const $route = useRoute() const $route = useRoute()
const channel = new BroadcastChannel('login')
channel.onmessage = () => location.reload()
const isBtnLoading = ref<boolean>(false) const isBtnLoading = ref<boolean>(false)
// //
//model,form //model,form
@ -524,10 +405,17 @@ const login = async () => {
await userStore.userLogin(formModel.value).then(() => { await userStore.userLogin(formModel.value).then(() => {
isBtnLoading.value = false isBtnLoading.value = false
$router.push('/curriculumCenter/basicCourseInformation') $router.push('/curriculumCenter/basicCourseInformation')
channel.postMessage('')
if ($route.query.redirect) { if ($route.query.redirect) {
$router.push($route.query.redirect as string) $router.push($route.query.redirect as string)
channel.postMessage('')
} else { } else {
$router.push('/') $router.push('/')
channel.postMessage('')
} }
}) })
} catch (error) { } catch (error) {
@ -548,10 +436,16 @@ const phoneLogin = async () => {
.then(() => { .then(() => {
isBtnLoading.value = false isBtnLoading.value = false
$router.push('/curriculumCenter/basicCourseInformation') $router.push('/curriculumCenter/basicCourseInformation')
channel.postMessage('')
if ($route.query.redirect) { if ($route.query.redirect) {
$router.push($route.query.redirect as string) $router.push($route.query.redirect as string)
channel.postMessage('')
} else { } else {
$router.push('/') $router.push('/')
channel.postMessage('')
} }
}) })
.catch((error) => { .catch((error) => {
@ -597,15 +491,18 @@ onUnmounted(() => {
height: 100vh; height: 100vh;
position: absolute; position: absolute;
top: 0; top: 0;
.logo { .logo {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
padding: 5px 35px 0px 20px; padding: 5px 35px 0px 20px;
.logo_main { .logo_main {
display: flex; display: flex;
align-items: center; align-items: center;
} }
.font { .font {
font-size: 20px; font-size: 20px;
font-family: 'YourChosenArtisticFont', sans-serif; font-family: 'YourChosenArtisticFont', sans-serif;
@ -615,6 +512,7 @@ onUnmounted(() => {
margin-left: 5px; margin-left: 5px;
} }
} }
// background: url('../../assets/images/background.jpg') no-repeat; // background: url('../../assets/images/background.jpg') no-repeat;
.loin_form { .loin_form {
position: relative; position: relative;
@ -629,32 +527,39 @@ onUnmounted(() => {
padding: 40px; padding: 40px;
border-radius: 10px; border-radius: 10px;
box-shadow: 7px 7px 42px rgba(0, 0, 0, 0.17); box-shadow: 7px 7px 42px rgba(0, 0, 0, 0.17);
.taggle { .taggle {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
} }
h1 { h1 {
font-size: 40px; font-size: 40px;
color: #5577ff; color: #5577ff;
} }
h2 { h2 {
font-size: 20px; font-size: 20px;
color: #5577ff; color: #5577ff;
margin: 20px 0; margin: 20px 0;
} }
.login-btn { .login-btn {
width: 100%; width: 100%;
} }
.p { .p {
height: 40px; height: 40px;
text-align: center; text-align: center;
line-height: 40px; line-height: 40px;
width: 90px; width: 90px;
} }
.codeVerify { .codeVerify {
display: flex; display: flex;
justify-content: end; justify-content: end;
} }
.code, .code,
.code1 { .code1 {
height: 40px; height: 40px;

@ -20,6 +20,9 @@ export default ({ command }: any) => {
symbolId: 'icon-[dir]-[name]', symbolId: 'icon-[dir]-[name]',
}), }),
], ],
server: {
host: '0.0.0.0',
},
resolve: { resolve: {
alias: { alias: {
'@': path.resolve('./src'), // 相对路径别名配置,使用 @ 代替 src '@': path.resolve('./src'), // 相对路径别名配置,使用 @ 代替 src

@ -1,5 +1,6 @@
# 变量必须以 VITE_ 为前缀才能暴露给外部读取 # 变量必须以 VITE_ 为前缀才能暴露给外部读取
NODE_ENV = 'development' NODE_ENV = 'development'
VITE_APP_TITLE = '教学一体化平台' VITE_APP_TITLE = '教学一体化平台'
# VITE_APP_BASE_API = 'http://127.0.0.1:8080' VITE_APP_BASE_API = 'http://127.0.0.1:8080'
VITE_APP_BASE_API = 'http://39.106.16.162:8080' VITE_APP_OTHER_ORIGIN = 'http://127.0.0.1:5173'
# VITE_APP_BASE_API = 'http://39.106.16.162:8080'

@ -1,3 +1,4 @@
NODE_ENV = 'production' NODE_ENV = 'production'
VITE_APP_TITLE = '教学一体化平台' VITE_APP_TITLE = '教学一体化平台'
VITE_APP_OTHER_ORIGIN = 'http://39.106.16.162:5173'
# VITE_APP_BASE_API = '/api' # VITE_APP_BASE_API = '/api'

@ -3,7 +3,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import {} from 'vue' import { } from 'vue'
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>

@ -12,11 +12,12 @@
v-show="!item.meta.hidden" @click="goToRouter(item, index)" :key="item.path"> v-show="!item.meta.hidden" @click="goToRouter(item, index)" :key="item.path">
<div>{{ item.meta.title }}</div> <div>{{ item.meta.title }}</div>
</li> </li>
<div v-if="isLogin"> <div v-if="userStore.isLogin">
<img :src="data.icon" alt="" style="width: 24px; height: 24px; margin: 0 10px; border-radius: 50%" /> <img :src="userStore.userInfo.icon" alt=""
style="width: 24px; height: 24px; margin: 0 10px; border-radius: 50%" />
<el-dropdown @command="handleCommand"> <el-dropdown @command="handleCommand">
<span class="el-dropdown-link" style="color: #fff;"> <span class="el-dropdown-link" style="color: #fff;">
{{ data.username }} {{ userStore.userInfo.username }}
<el-icon class="el-icon--right"> <el-icon class="el-icon--right">
<arrow-down /> <arrow-down />
</el-icon> </el-icon>
@ -28,7 +29,8 @@
</template> </template>
</el-dropdown> </el-dropdown>
</div> </div>
<li v-else @click="skip('http://localhost:5173/#/login?redirect=/configurationPage')">登录注册</li> <li v-else @click="send">登录注册</li>
<!-- skip('http://localhost:5173/#/login?redirect=/configurationPage') -->
<!-- <li v-if="$route.path != '/home'" @click="$router.push('/')">回到首页</li> --> <!-- <li v-if="$route.path != '/home'" @click="$router.push('/')">回到首页</li> -->
</ul> </ul>
<div class="entry"> <div class="entry">
@ -50,7 +52,7 @@ import useUserStore from '@/store/module/user';
const userStore = useUserStore() const userStore = useUserStore()
import { constRouter } from '@/router/module/constRouter' import { constRouter } from '@/router/module/constRouter'
import { useRouter, useRoute } from 'vue-router' import { useRouter, useRoute } from 'vue-router'
import { onMounted, ref } from 'vue' import { computed, onMounted, ref } from 'vue'
import useSettingStore from '@/store/module/setting' import useSettingStore from '@/store/module/setting'
const $router = useRouter() const $router = useRouter()
const $route = useRoute() const $route = useRoute()
@ -72,23 +74,38 @@ onMounted(() => {
} }
}) })
}) })
const isLogin = ref(false)
const data = ref<any>({})
userGetInfoService(userStore.token).then(res => {
// @ts-ignore
if (res.code === 200) {
isLogin.value = true
data.value = res.data
}
})
function skip(url: string) { function skip(url: string) {
location.assign(url) location.assign(url)
} }
// ========================
let otherWin: any = null;
function send() {
if (otherWin) {
otherWin.focus();
return
}
otherWin = window.open(import.meta.env.VITE_APP_OTHER_ORIGIN)
}
window.onmessage = e => {
if (e.origin === import.meta.env.VITE_APP_OTHER_ORIGIN) {
userStore.setToken(e.data)
userStore.setUserInfo()
}
}
// ========================
// 退 // 退
function logout() { function logout() {
isLogin.value = false try {
otherWin.postMessage('logout', import.meta.env.VITE_APP_OTHER_ORIGIN)
} catch (error) {
send()
setTimeout(() => {
otherWin.postMessage('logout', import.meta.env.VITE_APP_OTHER_ORIGIN)
}, 500)
}
} }
const handleCommand = (command: string) => { const handleCommand = (command: string) => {
switch (command) { switch (command) {

@ -4,21 +4,39 @@ import { ref, reactive } from 'vue'
const userStore = defineStore('userStore', () => { const userStore = defineStore('userStore', () => {
const userInfo = reactive<any>({}) const userInfo = reactive<any>({})
const isLogin = ref(false) const isLogin = ref(false)
const token = ref('') const token = ref(sessionStorage.getItem('TOKEN') || '')
const verifyToken = () => { } const verifyToken = () => { }
const clearUserInfo = () => {
userGetInfoService(token.value).then(res => { Object.keys(userInfo).forEach(function (prop) {
delete userInfo[prop];
});
}
const setToken = (data: string) => {
token.value = data
sessionStorage.setItem('TOKEN', data)
}
const setUserInfo = async () => {
try {
const res = await userGetInfoService(token.value)
// @ts-ignore // @ts-ignore
if (res.code === 200) { if (res.code === 200) {
Object.assign(userInfo, res.data) Object.assign(userInfo, res.data)
isLogin.value = true isLogin.value = true
} else isLogin.value = false
} catch (error) {
isLogin.value = false
clearUserInfo()
}
} }
}) setUserInfo()
return { return {
token, token,
setToken,
userInfo, userInfo,
isLogin, isLogin,
verifyToken verifyToken,
setUserInfo,
clearUserInfo
} }
}) })
export default userStore export default userStore

Loading…
Cancel
Save