Skip to content

Commit

Permalink
feat(bc-qiankun) add qiankun in emqx-dashboard as subapp
Browse files Browse the repository at this point in the history
  • Loading branch information
ljemq committed Oct 9, 2022
1 parent 276f1bc commit 7b7013b
Show file tree
Hide file tree
Showing 37 changed files with 492 additions and 110 deletions.
22 changes: 16 additions & 6 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
const path = require('path')

module.exports = {
root: true,
env: {
node: true,
},
extends: [
'plugin:vue/essential',
'@vue/airbnb',
'@vue/prettier',
],
extends: ['plugin:vue/essential', '@vue/airbnb', '@vue/prettier', 'plugin:vue/base'],
rules: {
'prettier/prettier': 'error',
'no-console': 'off',
'no-debugger': 'off',
'import/extensions': 0,
'vue/max-attributes-per-line': [
4,
2,
{
singleline: 6,
multiline: {
Expand All @@ -39,4 +37,16 @@ module.exports = {
parserOptions: {
parser: 'babel-eslint',
},
settings: {
'import/resolver': {
alias: {
map: [['@', path.resolve(__dirname, 'src')]],
extensions: ['.js', '.jsx'],
},
node: {
paths: ['src'],
extensions: ['.js', '.ts', '.d.ts', '.tsx'],
},
},
},
}
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
"scripts": {
"dev-cloud": "export VUE_APP_BUILD_ENV=cloud && yarn serve",
"serve": "vue-cli-service serve",
"serve:sub-app": "VUE_APP_BUILD_ENV=sub-app && vue-cli-service serve",
"build": "vue-cli-service build",
"build:sub-app": "VUE_SUB_APP_BUILD_ENV=sub-app vue-cli-service build",
"build:config": "node ./script/build.config.js",
"lint": "vue-cli-service lint",
"format": "prettier --write \"src/**/*.js\" \"src/**/*.vue\" \"src/**/*.scss\""
Expand All @@ -20,6 +22,7 @@
"dateformat": "^3.0.3",
"echarts": "^4.2.1",
"element-ui": "^2.9.1",
"eslint-import-resolver-alias": "^1.1.2",
"highlight.js": "^9.15.8",
"js-sql-parser": "^1.3.0",
"jsonwebtoken": "^8.5.1",
Expand Down
12 changes: 12 additions & 0 deletions script/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,17 @@
"rules.schema"
]
}
},
"sub-app": {
"baseURL": "/api/v4",
"httpTimeout": 15000,
"useRelativeResourcePath": true,
"publicPath": "/",
"hide": {
"routes": [
"usersAcl"
],
"children": ["monitor.license"]
}
}
}
4 changes: 4 additions & 0 deletions src/common/forToBeSubApp.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const SING_NODE_VALUE = 'single-node'
export const isSingNode = (node) => node === SING_NODE_VALUE

export const isSubApp = window.__POWERED_BY_QIANKUN__
64 changes: 49 additions & 15 deletions src/common/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'nprogress/nprogress.css'
import { getBasicAuthInfo, toLogin } from '@/common/utils'
import store from '@/stores'
import router from '@/routes'
import { isSubApp } from '../common/forToBeSubApp.js'

let timer = 0

Expand All @@ -33,6 +34,7 @@ const httpCode = {
115: '主题错误',
'-1': '需要登录',
'-2': '相关插件未开启',
'-3': 'dashbard 没有权限',
},
en: {
0: 'Success',
Expand All @@ -53,37 +55,57 @@ const httpCode = {
115: 'Bad topic',
'-1': 'Login Required',
'-2': 'Plugin not started',
'-3': 'dashbard not allowed',
},
}

const httpMap = httpCode[lang]

const pluginPages = ['schemas', 'rules', 'resources', 'setting']

Object.assign(axios.defaults, {
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'no-cache',
},
baseURL: store.getters.httpBaseUrl,
timeout: store.state.httpTimeout,
auth: {},
})
if (!isSubApp) {
Object.assign(axios.defaults, {
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'no-cache',
},
baseURL: store.getters.httpBaseUrl,
timeout: store.state.httpTimeout,
auth: {},
})
} else {
Object.assign(axios.defaults, {
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'no-cache',
},
baseURL: '',
timeout: store.state.httpTimeout,
})
}

axios.interceptors.request.use(
(config) => {
if (store.state.isSubAppDestroyed) {
// console.log('是否退出=========')
throw new axios.Cancel('cancel')
}
const user = getBasicAuthInfo()
config.params = config.params || {}
// 如果是 subapp
const {
params: { _t: tokenRequired = true },
} = config
if (!user.username && tokenRequired) {
if (isSubApp) {
// do nothing
} else if (!user.username && tokenRequired) {
toLogin()
throw new Error(httpMap['-1'])
}
config.auth.username = user.username
config.auth.password = user.password

if (!isSubApp) {
config.auth.username = user.username
config.auth.password = user.password
}
store.dispatch('LOADING', true)
// lwm2m observe
if (!config.url.includes('?msgType=observe&path=')) {
Expand Down Expand Up @@ -111,6 +133,7 @@ function handleError(error) {
config: {
params: { _m: showMessage = true },
},
headers: {},
},
} = error
if (selfError) {
Expand All @@ -120,7 +143,18 @@ function handleError(error) {
}
const { name: currentPage, fullPath } = router.history.current
if (status === 401) {
toLogin()
if (!isSubApp) {
toLogin()
} else {
for (let i = 0; i <= timer; i++) {
clearTimeout(i)
}
Message.closeAll()
Message.error(httpMap['-3'])
if (window.orgId && window.projectId && window.deployId) {
router.push({ path: `/deploy/${window.orgId}/${window.projectId}/${window.deployId}/overview` })
}
}
} else if (status === 404 && pluginPages.includes(currentPage)) {
Message.error(httpMap['-2'])
} else if (showMessage) {
Expand Down Expand Up @@ -149,6 +183,7 @@ axios.interceptors.response.use((response) => {
let error = ''
let selfError = ''
if (typeof res === 'object') {
console.log(res, 'res')
const { status } = response
const { code = -100, meta, message } = response.data
let { data } = response.data
Expand All @@ -162,7 +197,6 @@ axios.interceptors.response.use((response) => {
}
res = { data, status }
}

clearTimeout(timer)
timer = setTimeout(() => {
store.dispatch('LOADING', false)
Expand Down
13 changes: 13 additions & 0 deletions src/common/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,22 @@ import { omit, cloneDeep, isObject } from 'lodash'

import { enDocsLink, zhDocsLink, pluginsZh, pluginsEn } from '@/common/link_urls'

import { isSubApp } from './forToBeSubApp.js'

const locale = store.state.lang
const VueI18n = lang[locale]

const isSubAppIn = isSubApp
//qiankun 处理路由
export function getPathForEmqxDashBoardPage(routePath, path) {
if (isSubAppIn) {
const pathPre = routePath.split('/').splice(0, 8).join('/')
return `${pathPre}${path}`
} else {
return path
}
}

/**
* 获取基础的验证信息
* @param null
Expand Down
22 changes: 14 additions & 8 deletions src/components/Breadcrumb.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
</a-breadcrumb-item>
</template>
<a-breadcrumb-item v-else>
<router-link to="/" tag="span" class="btn btn-default raw">
<router-link :to="{ name: 'monitor' }" tag="span" class="btn btn-default raw">
{{ $t('components.monitor') }}
</router-link>
</a-breadcrumb-item>
Expand All @@ -27,6 +27,9 @@
</template>

<script>
import { isSubApp } from '../common/forToBeSubApp.js'
import { getPathForEmqxDashBoardPage } from '../common/utils.js'
export default {
name: 'Breadcrumb',
Expand All @@ -48,28 +51,31 @@ export default {
created() {
this.getBreadcrumb()
},
methods: {
getBreadcrumb() {
const { path, query, name: routeName } = this.$route
const pathList = path.split('/')
const name = pathList[1]
const oper = query.oper || pathList[2]
this.isIndex = path === '/monitor'
const name = isSubApp ? pathList[8] : pathList[1]
const oper = query.oper || (isSubApp ? pathList[9] : pathList[2])
if (isSubApp) {
const subAppPre = `/${path.split('/')[8]}`
this.isIndex = subAppPre === '/monitor'
} else {
this.isIndex = path === '/monitor'
}
this.oper = ''
this.backPath = undefined
this.currentTitle = this.$t(`components.${name}`)
if (['create', 'view', 'detail', 'add', 'select', 'manage'].includes(oper)) {
this.oper = this.$t(`Base.${oper}`)
this.backPath = `/${name}`
this.backPath = getPathForEmqxDashBoardPage(path, `/${name}`)
} else if (oper === 'node') {
this.currentTitle = this.$t('Overview.nodeData')
}
if (routeName === 'pluginsName' && this.$route.params.pluginName) {
this.oper = this.$route.params.pluginName
this.backPath = `/${name}`
this.backPath = getPathForEmqxDashBoardPage(path, `/${name}`)
}
},
},
Expand Down
7 changes: 6 additions & 1 deletion src/components/Layout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<nav-header></nav-header>
</el-header>

<div :style="{ minHeight: '360px', minWidth: '600px', overflowX: 'hidden' }">
<div class="layout-container">
<transition name="fade-transform" mode="out-in">
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
Expand Down Expand Up @@ -162,6 +162,11 @@ export default {
.el-main {
transition: margin-left 0.3s;
}
.layout-container {
min-height: 360px;
min-width: 600px;
overflow-x: hidden;
}
</style>
<style lang="scss">
.default-pwd-tip {
Expand Down
Loading

0 comments on commit 7b7013b

Please sign in to comment.