吉安感知网项目-前端
罗广辉
2026-03-11 a3f920c3aa61a1bbbdf042163ea194f092ae466d
feat: 退出登录
21 files modified
696 ■■■■ changed files
applications/drone-command/src/axios.js 17 ●●●● patch | view | raw | blame | history
applications/drone-command/src/components/third-register/main.vue 244 ●●●● patch | view | raw | blame | history
applications/drone-command/src/mac/index.vue 6 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/mac/lock.vue 5 ●●●● patch | view | raw | blame | history
applications/drone-command/src/page/index/top/index.vue 11 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/page/index/useGlobalWS.js 7 ●●●● patch | view | raw | blame | history
applications/drone-command/src/page/lock/index.vue 197 ●●●● patch | view | raw | blame | history
applications/drone-command/src/permission.js 13 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/store/modules/user.js 17 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/utils/auth.js 20 ●●●● patch | view | raw | blame | history
applications/drone-command/src/utils/util.js 63 ●●●●● patch | view | raw | blame | history
applications/task-work-order/src/axios.js 17 ●●●● patch | view | raw | blame | history
applications/task-work-order/src/components/third-register/main.vue 4 ●●●● patch | view | raw | blame | history
applications/task-work-order/src/mac/index.vue 5 ●●●● patch | view | raw | blame | history
applications/task-work-order/src/mac/lock.vue 5 ●●●●● patch | view | raw | blame | history
applications/task-work-order/src/page/index/top/index.vue 9 ●●●● patch | view | raw | blame | history
applications/task-work-order/src/page/index/useGlobalWS.js 7 ●●●● patch | view | raw | blame | history
applications/task-work-order/src/page/lock/index.vue 8 ●●●● patch | view | raw | blame | history
applications/task-work-order/src/permission.js 12 ●●●●● patch | view | raw | blame | history
applications/task-work-order/src/store/modules/user.js 11 ●●●● patch | view | raw | blame | history
applications/task-work-order/src/utils/util.js 18 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/axios.js
@@ -9,7 +9,7 @@
import axios from 'axios'
import store from '@/store/'
import router from '@/router/'
import { serialize } from '@/utils/util'
import { logOutFun, serialize } from '@/utils/util'
import { getToken, removeToken, removeRefreshToken } from '@/utils/auth'
import { isURL, validatenull } from '@/utils/validate'
import { ElMessage } from 'element-plus'
@@ -30,15 +30,6 @@
//跨域请求,允许保存cookie
axios.defaults.withCredentials = true
function logOutFun() {
    store.dispatch('FedLogOut').then(() =>{
        const {VITE_APP_PARENT_SYSTEM,VITE_APP_ENV} = import.meta.env
        const isDev = VITE_APP_ENV === 'development'
        isDev
            ? router.push({ path: '/login' })
            : window.location.replace(`${VITE_APP_PARENT_SYSTEM}/#/login`)
    })
}
//http request拦截
axios.interceptors.request.use(
@@ -115,11 +106,7 @@
      const currentRouteName = router.currentRoute.value.name
      // 如果当前路由不是登录页,则跳转到登录页
      if (currentRouteName !== '登录页') {
        store.dispatch('FedLogOut').then(() =>
          router.push({
            path: '/login',
          })
        )
                logOutFun()
      }
      return Promise.reject(new Error(message))
    }
applications/drone-command/src/components/third-register/main.vue
@@ -1,129 +1,129 @@
<template>
  <el-dialog
    title="账号注册"
    append-to-body
    v-model="accountBox"
    :close-on-click-modal="false"
    :close-on-press-escape="false"
    :show-close="false"
    width="20%"
  >
    <el-form :model="form" ref="form" label-width="80px">
      <el-form-item v-if="tenantMode" label="租户编号">
        <el-input v-model="form.tenantId" placeholder="请输入租户编号"></el-input>
      </el-form-item>
      <el-form-item label="用户姓名">
        <el-input v-model="form.name" placeholder="请输入用户姓名"></el-input>
      </el-form-item>
      <el-form-item label="账号名称">
        <el-input v-model="form.account" placeholder="请输入账号名称"></el-input>
      </el-form-item>
      <el-form-item label="账号密码">
        <el-input v-model="form.password" placeholder="请输入账号密码"></el-input>
      </el-form-item>
      <el-form-item label="确认密码">
        <el-input v-model="form.password2" placeholder="请输入确认密码"></el-input>
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button type="primary" :loading="loading" @click="handleRegister">确 定</el-button>
      </span>
    </template>
  </el-dialog>
    <el-dialog
        title="账号注册"
        append-to-body
        v-model="accountBox"
        :close-on-click-modal="false"
        :close-on-press-escape="false"
        :show-close="false"
        width="20%"
    >
        <el-form :model="form" ref="form" label-width="80px">
            <el-form-item v-if="tenantMode" label="租户编号">
                <el-input v-model="form.tenantId" placeholder="请输入租户编号"></el-input>
            </el-form-item>
            <el-form-item label="用户姓名">
                <el-input v-model="form.name" placeholder="请输入用户姓名"></el-input>
            </el-form-item>
            <el-form-item label="账号名称">
                <el-input v-model="form.account" placeholder="请输入账号名称"></el-input>
            </el-form-item>
            <el-form-item label="账号密码">
                <el-input v-model="form.password" placeholder="请输入账号密码"></el-input>
            </el-form-item>
            <el-form-item label="确认密码">
                <el-input v-model="form.password2" placeholder="请输入确认密码"></el-input>
            </el-form-item>
        </el-form>
        <template #footer>
            <span class="dialog-footer">
                <el-button type="primary" :loading="loading" @click="handleRegister">确 定</el-button>
            </span>
        </template>
    </el-dialog>
</template>
<script>
import { mapGetters } from 'vuex';
import { validatenull } from 'utils/validate';
import { registerGuest } from '@/api/user';
import { getTopUrl } from 'utils/util';
import { info } from '@/api/system/tenant';
import { resetRouter } from '@/router/index';
import { mapGetters } from 'vuex'
import { validatenull } from 'utils/validate'
import { registerGuest } from '@/api/user'
import { getTopUrl, logOutFun } from 'utils/util'
import { info } from '@/api/system/tenant'
import { resetRouter } from '@/router/index'
export default {
  name: 'thirdRegister',
  data() {
    return {
      form: {
        tenantId: '',
        name: '',
        account: '',
        password: '',
        password2: '',
      },
      loading: false,
      tenantMode: true,
      accountBox: false,
    };
  },
  computed: {
    ...mapGetters(['userInfo']),
  },
  created() {
    this.getTenant();
  },
  mounted() {
    // 若未登录则弹出框进行绑定
    if (validatenull(this.userInfo.user_id) || this.userInfo.user_id < 0) {
      this.form.name = this.userInfo.user_name;
      this.form.account = this.userInfo.account;
      this.accountBox = true;
    }
  },
  methods: {
    handleRegister() {
      if (this.form.tenantId === '') {
        this.$message.warning('请先输入租户编号');
        return;
      }
      if (this.form.account === '') {
        this.$message.warning('请先输入账号名称');
        return;
      }
      if (this.form.password === '' || this.form.password2 === '') {
        this.$message.warning('请先输入密码');
        return;
      }
      if (this.form.password !== this.form.password2) {
        this.$message.warning('两次密码输入不一致');
        return;
      }
      this.loading = true;
      registerGuest(this.form, this.userInfo.oauth_id).then(
        res => {
          this.loading = false;
          const data = res.data;
          if (data.success) {
            this.accountBox = false;
            this.$alert('注册申请已提交,请耐心等待管理员通过!', '注册提示').then(() => {
              this.$store.dispatch('LogOut').then(() => {
                resetRouter();
                this.$router.push({ path: '/login' });
              });
            });
          } else {
            this.$message.error(data.msg || '提交失败');
          }
        },
        error => {
          window.console.log(error);
          this.loading = false;
        }
      );
    },
    getTenant() {
      let domain = getTopUrl();
      // 临时指定域名,方便测试
      //domain = "https://bladex.cn";
      info(domain).then(res => {
        const data = res.data;
        if (data.success && data.data.tenantId) {
          this.form.tenantId = data.data.tenantId;
          this.tenantMode = false;
        }
      });
    },
  },
};
    name: 'thirdRegister',
    data() {
        return {
            form: {
                tenantId: '',
                name: '',
                account: '',
                password: '',
                password2: '',
            },
            loading: false,
            tenantMode: true,
            accountBox: false,
        }
    },
    computed: {
        ...mapGetters(['userInfo']),
    },
    created() {
        this.getTenant()
    },
    mounted() {
        // 若未登录则弹出框进行绑定
        if (validatenull(this.userInfo.user_id) || this.userInfo.user_id < 0) {
            this.form.name = this.userInfo.user_name
            this.form.account = this.userInfo.account
            this.accountBox = true
        }
    },
    methods: {
        handleRegister() {
            if (this.form.tenantId === '') {
                this.$message.warning('请先输入租户编号')
                return
            }
            if (this.form.account === '') {
                this.$message.warning('请先输入账号名称')
                return
            }
            if (this.form.password === '' || this.form.password2 === '') {
                this.$message.warning('请先输入密码')
                return
            }
            if (this.form.password !== this.form.password2) {
                this.$message.warning('两次密码输入不一致')
                return
            }
            this.loading = true
            registerGuest(this.form, this.userInfo.oauth_id).then(
                res => {
                    this.loading = false
                    const data = res.data
                    if (data.success) {
                        this.accountBox = false
                        this.$alert('注册申请已提交,请耐心等待管理员通过!', '注册提示').then(() => {
                            this.$store.dispatch('LogOut').then(() => {
                                resetRouter()
                                logOutFun()
                            })
                        })
                    } else {
                        this.$message.error(data.msg || '提交失败')
                    }
                },
                error => {
                    window.console.log(error)
                    this.loading = false
                }
            )
        },
        getTenant() {
            let domain = getTopUrl()
            // 临时指定域名,方便测试
            //domain = "https://bladex.cn";
            info(domain).then(res => {
                const data = res.data
                if (data.success && data.data.tenantId) {
                    this.form.tenantId = data.data.tenantId
                    this.tenantMode = false
                }
            })
        },
    },
}
</script>
applications/drone-command/src/mac/index.vue
@@ -60,6 +60,9 @@
import index from '@/mixins/index'
import topLock from '@/page/index/top/top-lock.vue'
import { logOutFun } from '@/utils/util'
export default {
  mixins: [index],
  components: {
@@ -132,8 +135,7 @@
    logout () {
      this.$store.commit('SET_THEME_NAME', '')
      this.$store.dispatch('LogOut').then(() => {
        this.$router.push({ path: '/login' })
        setTimeout(() => location.reload())
                logOutFun()
      })
    },
    startTimer () {
applications/drone-command/src/mac/lock.vue
@@ -20,6 +20,9 @@
<script>
import { mapGetters } from 'vuex';
import { logOutFun } from '@/utils/util'
export default {
  data() {
    return {
@@ -34,7 +37,7 @@
  methods: {
    handleLogout() {
      this.$store.dispatch('LogOut').then(() => {
        this.$router.push({ path: '/login' });
                logOutFun()
      });
    },
    handleLogin() {
applications/drone-command/src/page/index/top/index.vue
@@ -63,6 +63,9 @@
import topQna from './top-qna.vue'
import topSetting from '../setting.vue'
import { logOutFun } from '@/utils/util'
export default {
  components: {
    topLock,
@@ -132,13 +135,7 @@
        confirmButtonClass: 'command-message-box-confirm',
        cancelButtonClass: 'command-message-box-cancel',
      }).then(() => {
        this.$store.dispatch('LogOut').then(() => {
          const { VITE_APP_PARENT_SYSTEM, VITE_APP_ENV } = import.meta.env
          const isDev = VITE_APP_ENV === 'development'
          isDev
            ? this.$router.push({ path: '/login' })
            : window.location.replace(`${VITE_APP_PARENT_SYSTEM}/#/login`)
        })
                logOutFun()
      })
    },
    jumpMH () {
applications/drone-command/src/page/index/useGlobalWS.js
@@ -3,7 +3,7 @@
import { useConnectWebSocket } from '@/utils/websocket/connect-websocket'
import { useStore } from 'vuex'
import dayjs from 'dayjs'
import { aLinkDownloadUtil } from '@/utils/util'
import { aLinkDownloadUtil, logOutFun } from '@/utils/util'
import EventBus from '@/utils/eventBus'
import { getStore, setStore } from '@/utils/store'
@@ -41,10 +41,7 @@
    const logOut = () => {
        store.commit('SET_THEME_NAME', '')
        store.dispatch('LogOut').then(() => {
            router.push({ path: '/login' })
            setTimeout(() => location.reload())
        })
        logOutFun()
    }
    function messageHandler(payload) {
        switch (payload.biz_code) {
applications/drone-command/src/page/lock/index.vue
@@ -1,109 +1,110 @@
<template>
  <div class="login-container" @keyup.enter="handleLogin">
    <div class="login-time">
      {{ time }}
    </div>
    <div class="login-weaper">
      <div class="login-left animate__animated animate__fadeInLeft">
        <img class="img" src="/img/logo.png" alt="" />
        <p class="title">{{ $t('login.info') }}</p>
      </div>
      <div class="login-border animate__animated animate__fadeInRight">
        <div class="login-main">
          <div class="lock-form animate__animated animate__bounceInDown">
            <div class="animate__animated" :class="{ shake: passwdError, animate__bounceOut: pass }">
              <h3 style="color: #333">{{ userInfo.username }}</h3>
              <el-input placeholder="请输入登录密码" type="password" class="input-with-select animated" v-model="passwd"
                @keyup.enter="handleLogin">
                <template #append>
                  <i class="icon-bofangqi-suoping" @click="handleLogin"></i>
                  &nbsp; &nbsp;
                  <i class="icon-tuichu" @click="handleLogout"></i>
                </template>
              </el-input>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
    <div class="login-container" @keyup.enter="handleLogin">
        <div class="login-time">
            {{ time }}
        </div>
        <div class="login-weaper">
            <div class="login-left animate__animated animate__fadeInLeft">
                <img class="img" src="/img/logo.png" alt="" />
                <p class="title">{{ $t('login.info') }}</p>
            </div>
            <div class="login-border animate__animated animate__fadeInRight">
                <div class="login-main">
                    <div class="lock-form animate__animated animate__bounceInDown">
                        <div class="animate__animated" :class="{ shake: passwdError, animate__bounceOut: pass }">
                            <h3 style="color: #333">{{ userInfo.username }}</h3>
                            <el-input
                                placeholder="请输入登录密码"
                                type="password"
                                class="input-with-select animated"
                                v-model="passwd"
                                @keyup.enter="handleLogin"
                            >
                                <template #append>
                                    <i class="icon-bofangqi-suoping" @click="handleLogin"></i>
                                    &nbsp; &nbsp;
                                    <i class="icon-tuichu" @click="handleLogout"></i>
                                </template>
                            </el-input>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>
<script>
import { mapGetters } from 'vuex'
import { removeRefreshToken, removeToken } from '@/utils/auth'
import { ElMessage, ElMessageBox } from 'element-plus'
import { logOutFun } from '@/utils/util'
export default {
  name: 'lock',
  data () {
    return {
      time: '',
      timeTimer: null,
      passwd: '',
      passwdError: false,
      pass: false,
    }
  },
  created () {
    this.getTime()
    if (this.timeTimer) clearInterval(this.timeTimer)
    this.timeTimer = setInterval(() => {
      this.getTime()
    }, 1000)
  },
  beforeDestroy () {
    if (this.timeTimer) {
      clearInterval(this.timeTimer)
      this.timeTimer = null
    }
  },
  mounted () { },
  computed: {
    ...mapGetters(['userInfo', 'tag', 'lockPasswd']),
  },
  props: [],
  methods: {
    getTime () {
      this.time = this.$dayjs().format('YYYY年MM月DD日 HH:mm:ss')
    },
    handleLogout () {
      ElMessageBox.confirm(`是否退出系统, 是否继续?`, '提示', {
        type: 'warning',
        customClass: 'command-page-view-message-box',
        confirmButtonClass: 'command-message-box-confirm',
        cancelButtonClass: 'command-message-box-cancel',
      }).then(() => {
        this.$store.dispatch('LogOut').then(() => {
          // 清除token信息
          removeToken()
          removeRefreshToken()
          this.$router.push({ path: '/login' })
        })
      })
    },
    handleLogin () {
      if (this.passwd !== this.lockPasswd) {
        this.passwd = ''
        this.$message({
          message: '解锁密码错误,请重新输入',
          type: 'error',
        })
        this.passwdError = true
        setTimeout(() => {
          this.passwdError = false
        }, 1000)
        return
      }
      this.pass = true
      setTimeout(() => {
        this.$store.commit('CLEAR_LOCK')
        this.$router.push({
          path: this.tag.path,
        })
      }, 1000)
    },
  },
  components: {},
    name: 'lock',
    data() {
        return {
            time: '',
            timeTimer: null,
            passwd: '',
            passwdError: false,
            pass: false,
        }
    },
    created() {
        this.getTime()
        if (this.timeTimer) clearInterval(this.timeTimer)
        this.timeTimer = setInterval(() => {
            this.getTime()
        }, 1000)
    },
    beforeDestroy() {
        if (this.timeTimer) {
            clearInterval(this.timeTimer)
            this.timeTimer = null
        }
    },
    mounted() {},
    computed: {
        ...mapGetters(['userInfo', 'tag', 'lockPasswd']),
    },
    props: [],
    methods: {
        getTime() {
            this.time = this.$dayjs().format('YYYY年MM月DD日 HH:mm:ss')
        },
        handleLogout() {
            ElMessageBox.confirm(`是否退出系统, 是否继续?`, '提示', {
                type: 'warning',
                customClass: 'command-page-view-message-box',
                confirmButtonClass: 'command-message-box-confirm',
                cancelButtonClass: 'command-message-box-cancel',
            }).then(() => {
                logOutFun()
            })
        },
        handleLogin() {
            if (this.passwd !== this.lockPasswd) {
                this.passwd = ''
                this.$message({
                    message: '解锁密码错误,请重新输入',
                    type: 'error',
                })
                this.passwdError = true
                setTimeout(() => {
                    this.passwdError = false
                }, 1000)
                return
            }
            this.pass = true
            setTimeout(() => {
                this.$store.commit('CLEAR_LOCK')
                this.$router.push({
                    path: this.tag.path,
                })
            }, 1000)
        },
    },
    components: {},
}
</script>
applications/drone-command/src/permission.js
@@ -14,7 +14,9 @@
import { getToken } from '@/utils/auth'
import { getUrlParams } from './utils/validate'
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style
import 'nprogress/nprogress.css'
import { logOutFun } from '@/utils/util'
// progress bar style
NProgress.configure({ showSpinner: false })
const lockPage = '/lock' //锁屏页
const urlParams = getUrlParams(window.location.href)
@@ -91,13 +93,7 @@
    } else {
      const systemToken = store.getters.token || urlParams?.token
      if (systemToken === 0) {
                store.dispatch('FedLogOut').then(() =>{
                    const {VITE_APP_PARENT_SYSTEM,VITE_APP_ENV} = import.meta.env
                    const isDev = VITE_APP_ENV === 'development'
                    isDev
                        ? router.push({ path: '/login' })
                        : window.location.replace(`${VITE_APP_PARENT_SYSTEM}/#/login`)
                })
                logOutFun()
      } else {
        const meta = to.meta || {}
        const query = to.query || {}
@@ -123,6 +119,7 @@
      next()
    } else {
            next('/login')
            logOutFun()
    }
  }
})
applications/drone-command/src/store/modules/user.js
@@ -239,28 +239,13 @@
            commit('CLEAR_LOCK')
            removeToken()
            removeRefreshToken()
                        removeToken()
            resolve()
                        localStorage.clear()
          })
          .catch(error => {
            reject(error)
          })
      })
    },
    //注销session
    FedLogOut ({ commit }) {
      return new Promise(resolve => {
        commit('SET_TOKEN', '')
        commit('SET_MENU_ALL_NULL', [])
        commit('SET_MENU', [])
        commit('SET_ROLES', [])
        commit('DEL_ALL_TAG', [])
        commit('CLEAR_LOCK')
        removeToken()
        removeRefreshToken()
        removeToken()
        resolve()
                localStorage.clear()
      })
    },
    GetTopMenu () {
applications/drone-command/src/utils/auth.js
@@ -1,20 +1,9 @@
/*
 * @Author       : yuan
 * @Date         : 2026-01-06 09:47:09
 * @LastEditors  : yuan
 * @LastEditTime : 2026-01-06 11:03:04
 * @FilePath     : \applications\drone-command\src\utils\auth.js
 * @Description  :
 * Copyright 2026 OBKoro1, All Rights Reserved.
 * 2026-01-06 09:47:09
 */
import Cookies from 'js-cookie';
import Cookies from 'js-cookie'
const TokenKey = 'command-access-token';
const TokenKey = 'command-access-token'
const RefreshTokenKey = 'command-refresh-token';
const SessionId = 'JSESSIONID';
const UserId = 'b-user-id';
export function getToken() {
    return Cookies.get(TokenKey, {
        path: '/'
@@ -46,5 +35,6 @@
}
export function removeRefreshToken() {
    return Cookies.remove(RefreshTokenKey);
}
    return Cookies.remove(RefreshTokenKey)
}
applications/drone-command/src/utils/util.js
@@ -469,33 +469,50 @@
    return `${url.substring(0, lastDotIndex)}_show.jpeg`
}
// key驼峰转换为下划线
export function camelToSnake (obj) {
  if (typeof obj !== 'object' || obj === null) {
    return obj
  }
export function camelToSnake(obj) {
    if (typeof obj !== 'object' || obj === null) {
        return obj
    }
  if (Array.isArray(obj)) {
    return obj.map(item => camelToSnake(item))
  }
    if (Array.isArray(obj)) {
        return obj.map(item => camelToSnake(item))
    }
  const newObj = {}
  for (const key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
      const newKey = key.replace(/([a-z])([A-Z])/g, '$1_$2').toLowerCase()
      newObj[newKey] = camelToSnake(obj[key])
    }
  }
  return newObj
    const newObj = {}
    for (const key in obj) {
        if (Object.prototype.hasOwnProperty.call(obj, key)) {
            const newKey = key.replace(/([a-z])([A-Z])/g, '$1_$2').toLowerCase()
            newObj[newKey] = camelToSnake(obj[key])
        }
    }
    return newObj
}
// a链接直接下载
export const aLinkDownloadUtil = (url, name) => {
  let a = document.createElement('a')
  a.style.display = 'none'
  a.href = url
  a.download = name
  document.body.appendChild(a)
  a.click()
  document.body.removeChild(a)
  a = null
    let a = document.createElement('a')
    a.style.display = 'none'
    a.href = url
    a.download = name
    document.body.appendChild(a)
    a.click()
    document.body.removeChild(a)
    a = null
}
// 统一退出登录
export function logOutFun() {
    // 延迟导入 store 和 router,避免循环依赖:
    // auth.js → router → store → user.js → auth.js
    const store = require('@/store').default
    const router = require('@/router').default
    const { VITE_APP_PARENT_SYSTEM, VITE_APP_ENV } = import.meta.env
    store.dispatch('LogOut').then(() => {
        const isDev = VITE_APP_ENV === 'development'
        if (isDev) {
            router.push({ path: '/login' })
            setTimeout(() => location.reload())
        } else {
            window.location.replace(`${VITE_APP_PARENT_SYSTEM}/#/login`)
        }
    })
}
applications/task-work-order/src/axios.js
@@ -9,7 +9,7 @@
import axios from 'axios'
import store from '@/store/'
import router from '@/router/'
import { serialize } from '@/utils/util'
import { logOutFun, serialize } from '@/utils/util'
import { getToken, removeToken, removeRefreshToken } from '@/utils/auth'
import { isURL, validatenull } from '@/utils/validate'
import { ElMessage } from 'element-plus'
@@ -34,15 +34,6 @@
    withCredentials: true,
})
function logOutFun() {
    store.dispatch('FedLogOut').then(() =>{
        const {VITE_APP_PARENT_SYSTEM,VITE_APP_ENV} = import.meta.env
        const isDev = VITE_APP_ENV === 'development'
        isDev
            ? router.push({ path: '/login' })
            : window.location.replace(`${VITE_APP_PARENT_SYSTEM}/#/login`)
    })
}
//http request拦截
@@ -118,11 +109,7 @@
            const currentRouteName = router.currentRoute.value.name
            // 如果当前路由不是登录页,则跳转到登录页
            if (currentRouteName !== '登录页') {
                store.dispatch('FedLogOut').then(() =>
                    router.push({
                        path: '/login',
                    })
                )
                logOutFun()
            }
            return Promise.reject(new Error(message))
        }
applications/task-work-order/src/components/third-register/main.vue
@@ -37,7 +37,7 @@
import { mapGetters } from 'vuex';
import { validatenull } from 'utils/validate';
import { registerGuest } from '@/api/user';
import { getTopUrl } from 'utils/util';
import { getTopUrl, logOutFun } from 'utils/util';
import { info } from '@/api/system/tenant';
import { resetRouter } from '@/router/index';
@@ -99,7 +99,7 @@
            this.$alert('注册申请已提交,请耐心等待管理员通过!', '注册提示').then(() => {
              this.$store.dispatch('LogOut').then(() => {
                resetRouter();
                this.$router.push({ path: '/login' });
                                logOutFun();
              });
            });
          } else {
applications/task-work-order/src/mac/index.vue
@@ -124,10 +124,7 @@
    },
    logout () {
      this.$store.commit('SET_THEME_NAME', '')
      this.$store.dispatch('LogOut').then(() => {
        this.$router.push({ path: '/login' })
        setTimeout(() => location.reload())
      })
            logOutFun()
    },
    startTimer () {
      setInterval(() => {
applications/task-work-order/src/mac/lock.vue
@@ -19,6 +19,7 @@
</template>
<script>
import { mapGetters } from 'vuex';
import { logOutFun } from '@/utils/util'
export default {
  data() {
@@ -33,9 +34,7 @@
  },
  methods: {
    handleLogout() {
      this.$store.dispatch('LogOut').then(() => {
        this.$router.push({ path: '/login' });
      });
            logOutFun()
    },
    handleLogin() {
      if (this.passwd != this.lockPasswd) {
applications/task-work-order/src/page/index/top/index.vue
@@ -46,6 +46,7 @@
import topFull from './top-full.vue'
import topQna from './top-qna.vue'
import topSetting from '../setting.vue'
import { logOutFun } from '@/utils/util'
export default {
  components: {
@@ -87,13 +88,7 @@
        cancelButtonText: this.$t('cancelText'),
        type: 'warning',
      }).then(() => {
        this.$store.dispatch('LogOut').then(() => {
                    const {VITE_APP_PARENT_SYSTEM,VITE_APP_ENV} = import.meta.env
            const isDev = VITE_APP_ENV === 'development'
                    isDev
                        ? this.$router.push({ path: '/login' })
                        : window.location.replace(`${VITE_APP_PARENT_SYSTEM}/#/login`)
        })
                logOutFun()
      })
    },
    jumpMH () {
applications/task-work-order/src/page/index/useGlobalWS.js
@@ -3,7 +3,7 @@
import { useConnectWebSocket } from '@/utils/websocket/connect-websocket'
import { useStore } from 'vuex'
import dayjs from 'dayjs'
import { aLinkDownloadUtil } from '@/utils/util'
import { aLinkDownloadUtil, logOutFun } from '@/utils/util'
import EventBus from '@/utils/eventBus'
import { getStore, setStore } from '@/utils/store'
@@ -41,10 +41,7 @@
    const logOut = () => {
        store.commit('SET_THEME_NAME', '')
        store.dispatch('LogOut').then(() => {
            router.push({ path: '/login' })
            setTimeout(() => location.reload())
        })
        logOutFun()
    }
    function messageHandler(payload) {
        switch (payload.biz_code) {
applications/task-work-order/src/page/lock/index.vue
@@ -39,6 +39,7 @@
<script>
import { mapGetters } from 'vuex';
import { removeRefreshToken, removeToken } from '@/utils/auth';
import { logOutFun } from '@/utils/util'
export default {
  name: 'lock',
@@ -72,12 +73,7 @@
        cancelButtonText: '取消',
        type: 'warning',
      }).then(() => {
        this.$store.dispatch('LogOut').then(() => {
          // 清除token信息
          removeToken();
          removeRefreshToken();
          this.$router.push({ path: '/login' });
        });
                logOutFun()
      });
    },
    handleLogin() {
applications/task-work-order/src/permission.js
@@ -14,7 +14,8 @@
import { getToken } from '@/utils/auth'
import { getUrlParams } from './utils/validate'
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style
import 'nprogress/nprogress.css'
import { logOutFun } from '@/utils/util' // progress bar style
NProgress.configure({ showSpinner: false })
const lockPage = '/lock' //锁屏页
const urlParams = getUrlParams(window.location.href)
@@ -92,13 +93,7 @@
    } else {
      const systemToken = store.getters.token || urlParams?.token
      if (systemToken === 0) {
                store.dispatch('FedLogOut').then(() =>{
                    const {VITE_APP_PARENT_SYSTEM,VITE_APP_ENV} = import.meta.env
                    const isDev = VITE_APP_ENV === 'development'
                    isDev
                        ? router.push({ path: '/login' })
                        : window.location.replace(`${VITE_APP_PARENT_SYSTEM}/#/login`)
                })
                logOutFun()
      } else {
        const meta = to.meta || {}
        const query = to.query || {}
@@ -124,6 +119,7 @@
      next()
    } else {
            next('/login')
            logOutFun()
      // env === 'development' ? next('/login') : window.location.replace(`${adminUrl}#/login`)
    }
  }
applications/task-work-order/src/store/modules/user.js
@@ -1,7 +1,7 @@
import { setToken, setRefreshToken, removeToken, removeRefreshToken, getRefreshToken } from '@/utils/auth'
import { setStore, getStore } from '@/utils/store'
import { validatenull } from '@/utils/validate'
import { deepClone } from '@/utils/util'
import { deepClone, logOutFun } from '@/utils/util'
import defaultAva from '@/assets/images/defaultava.png'
import {
    loginByUsername,
@@ -261,14 +261,7 @@
        },
        GetMenu({ commit, dispatch }, tenantId) {
            const errLogOut = () => {
                dispatch('LogOut').then(() => {
                    const env = import.meta.env.VITE_APP_ENV
                    const adminUrl = import.meta.env.VITE_APP_DASHBOARD_URL
                    (window.location.href = '/task-work-order/login')
                    // env === 'development'
                    //     ? (window.location.href = '/task-work-order/login')
                    //     : window.location.replace(`${adminUrl}#/login`)
                })
                logOutFun()
            }
            return new Promise(resolve => {
                getRoutes({ tenantId, sysType: 6 })
applications/task-work-order/src/utils/util.js
@@ -500,3 +500,21 @@
  document.body.removeChild(a)
  a = null
}
// 统一退出登录
export function logOutFun() {
    // 延迟导入 store 和 router,避免循环依赖:
    // auth.js → router → store → user.js → auth.js
    const store = require('@/store').default
    const router = require('@/router').default
    const { VITE_APP_PARENT_SYSTEM, VITE_APP_ENV } = import.meta.env
    store.dispatch('LogOut').then(() => {
        const isDev = VITE_APP_ENV === 'development'
        if (isDev) {
            router.push({ path: '/login' })
            setTimeout(() => location.reload())
        } else {
            window.location.replace(`${VITE_APP_PARENT_SYSTEM}/#/login`)
        }
    })
}