diff --git a/README.md b/README.md
index 31255839..35efb3e2 100644
--- a/README.md
+++ b/README.md
@@ -97,3 +97,6 @@ eg:
`el.style.padding = 'xxx'`
`el.style.margin = 'xxx'`
`el.style.border = 'xxx'`
+
+- **布局**
+避免使用float,视情况使用position,建议使用flex和grid
\ No newline at end of file
diff --git a/src/App.vue b/src/App.vue
index 037ec056..fece3380 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -5,14 +5,10 @@
+
+
diff --git a/src/components/charts/chart-options.js b/src/components/charts/chart-options.js
index a34108ec..7f2a58d1 100644
--- a/src/components/charts/chart-options.js
+++ b/src/components/charts/chart-options.js
@@ -117,9 +117,11 @@ const lineStack = {
}
]
}
+const pieWithTable = {}
const typeOptionMappings = [
{ value: 11, option: line }, // 常规折线图
{ value: 13, option: lineStack }, // 常规折线图
+ { value: 31, option: pieWithTable }, // 常规折线图
{ value: 91, option: line }, // tab容器
{ value: 92, option: line }, // tab页
{ value: 93, option: line } // 大标题
@@ -157,6 +159,10 @@ export function isSingleValue (type) {
export function isSingleValueWithEcharts (type) {
return type === 52
}
+/* 带Table的饼图 */
+export function isEchartsWithTable (type) {
+ return type === 31
+}
/* table */
export function isTable (type) {
return type >= 61 && type <= 70
@@ -183,4 +189,4 @@ export function getLayout (type) {
}
return layout
}
-export const heightUnit = 150
+export const heightUnit = 50
diff --git a/src/components/charts/panel.scss b/src/components/charts/panel.scss
index 93a51e61..605f485a 100644
--- a/src/components/charts/panel.scss
+++ b/src/components/charts/panel.scss
@@ -1,11 +1,20 @@
.cn-panel {
display: grid;
grid-template-columns: repeat(12, 1fr);
- grid-template-rows: repeat(auto-fill, 50px);
+ grid-auto-flow: row;
+ grid-auto-rows: 50px;
grid-gap: 10px;
- padding: 20px;
height: 100%;
width: 100%;
+ overflow: auto;
+ padding-right: 20px;
+ position: relative;
+
+ .panel__time {
+ position: absolute;
+ right: 20px;
+ top: 20px;
+ }
.cn-chart {
background-color: #FFFFFF;
@@ -169,8 +178,8 @@
}
.option__select {
.el-input__inner {
+ width: 80px;
padding-right: 20px;
- width: 120px;
border: none;
height: 100%;
line-height: 20px;
@@ -193,9 +202,10 @@
}
}
}
- .option__select.select__topn {
+ .option__select.select-column {
.el-input__inner {
- width: 80px;
+ width: 86px;
+ padding-left: 8px;
}
}
.icon-group-divide {
@@ -236,7 +246,7 @@
}
}
}
-.option__topn-popper {
+.option-popper {
.el-select-dropdown__item {
height: 24px;
line-height: 24px;
diff --git a/src/i18n/index.js b/src/i18n/index.js
index 710154f1..2d1e60d1 100644
--- a/src/i18n/index.js
+++ b/src/i18n/index.js
@@ -1,11 +1,16 @@
import { createI18n } from 'vue-i18n'
-import cn from './cn'
-import en from './en'
+import { storageKey } from '@/utils/constants'
+import { getI18n } from '@/utils/api'
+
const i18n = createI18n({
- locale: localStorage.getItem('cn-language') || 'en',
- messages: {
- cn: cn,
- en: en
- }
+ locale: localStorage.getItem(storageKey.language) || 'en',
+ messages: {}
})
+export async function loadI18n () {
+ const items = await getI18n()
+ sessionStorage.setItem(storageKey.i18n, 'true')
+ Object.keys(items).forEach(lang => {
+ i18n.global.mergeLocaleMessage(lang, items[lang])
+ })
+}
export default i18n
diff --git a/src/permission.js b/src/permission.js
index bc1965d3..1f0bff46 100644
--- a/src/permission.js
+++ b/src/permission.js
@@ -1,38 +1,42 @@
import router from './router'
import store from './store'
-import { get, post } from './utils/http'
import { ElMessage } from 'element-plus'
+import { getConfigJson, getPermission } from '@/utils/api'
+import axios from 'axios'
+import { storageKey } from '@/utils/constants'
+import { loadI18n } from '@/i18n'
const loginWhiteList = ['/login'] // 免登陆白名单
const permissionWhiteList = [...loginWhiteList] // 权限白名单
-router.beforeEach((to, from, next) => {
- if (sessionStorage.getItem('cn-token')) {
+router.beforeEach(async (to, from, next) => {
+ // 加载baseUrl
+ if (!axios.defaults.baseURL) {
+ const config = await getConfigJson()
+ axios.defaults.baseURL = config.baseUrl
+ }
+ if (sessionStorage.getItem(storageKey.token)) {
+ // 加载i18n
+ if (!sessionStorage.getItem(storageKey.i18n)) {
+ await loadI18n()
+ }
+
if (permissionWhiteList.indexOf(to.path) !== -1) {
next()
} else {
- new Promise(resolve => {
- if (store.getters.menuList.length === 0) {
- get(`${process.env.BASE_URL}config.json?Timestamp=${new Date().getTime()}`).then(config => {
- post(config.baseUrl + 'sys/user/permissions', { token: sessionStorage.getItem('cn-token') }).then(res => {
- store.commit('setMenuList', sortByOrderNum(res.data.menus))
- store.commit('setButtonList', res.data.buttons)
- store.commit('setRoleList', res.data.roles)
- resolve()
- })
- })
+ if (store.getters.menuList.length === 0) {
+ const { menuList, buttonList, roleList } = await getPermission()
+ store.commit('setMenuList', menuList)
+ store.commit('setButtonList', buttonList)
+ store.commit('setRoleList', roleList)
+ }
+ if (to.path) {
+ if (hasMenu(store.getters.menuList, to.path)) {
+ next()
} else {
- resolve()
+ ElMessage.error('No access') // TODO 国际化
}
- }).then(res => {
- if (to.path) {
- if (hasMenu(store.getters.menuList, to.path)) {
- next()
- } else {
- ElMessage.error('No access') // TODO 国际化
- }
- }
- })
+ }
}
} else {
if (loginWhiteList.indexOf(to.path) !== -1) {
diff --git a/src/utils/api.js b/src/utils/api.js
index c081b784..3465fad0 100644
--- a/src/utils/api.js
+++ b/src/utils/api.js
@@ -1,11 +1,17 @@
/**
* @author 陈劲松
* @date 2021/6/11
- * @description 1.定义api;2.定义通用查询函数,函数名应为 获取详情getItem、获取列表getItemList。例如getUser、getUserList
+ * @description 1.定义api;2.定义通用查询方法,函数名应为 获取详情getItem、获取列表getItemList。例如getUser、getUserList
*/
-import { get } from '@/utils/http'
+import { get, post } from '@/utils/http'
+import { sortByOrderNum } from '@/permission'
export const api = {
+ // 系统相关
+ permission: '/sys/user/permissions',
+ i18n: '/sys/i18n/lang',
+ dict: '/sys/dict',
+ // 业务
panel: '/visual/panel',
chart: '/visual/chart'
}
@@ -23,9 +29,13 @@ export async function getChartList (params) {
export async function getChart (id) {
return await getData(`${api.chart}/${id}`)
}
+/* 字典 */
+export async function getDictList (params) {
+ return await getData(api.dict, params, true)
+}
export async function getData (url, params = {}, isQueryList) {
- const request = new Promise((resolve, reject) => {
+ const request = new Promise(resolve => {
get(url, params).then(response => {
if (response.code === 200) {
resolve(isQueryList ? response.data.list : response.data)
@@ -34,3 +44,36 @@ export async function getData (url, params = {}, isQueryList) {
})
return await request
}
+
+export async function getConfigJson () {
+ const request = new Promise(resolve => {
+ get(`${process.env.BASE_URL}config.json?Timestamp=${new Date().getTime()}`).then(config => {
+ resolve(config)
+ })
+ })
+ return await request
+}
+
+export async function getPermission () {
+ const request = new Promise(resolve => {
+ post(api.permission, { token: sessionStorage.getItem('cn-token') }).then(response => {
+ resolve({
+ menuList: sortByOrderNum(response.data.menus),
+ buttonList: response.data.buttons,
+ roleList: response.data.roles
+ })
+ })
+ })
+ return await request
+}
+
+export async function getI18n () {
+ const dictData = await getDictList()
+ const langs = dictData.map(d => d.value).join(',')
+ const request = new Promise(resolve => {
+ get(api.i18n, { l: langs }).then(response => {
+ resolve(response.data)
+ })
+ })
+ return await request
+}
diff --git a/src/utils/constants.js b/src/utils/constants.js
index 5f49c33d..9fbbf211 100644
--- a/src/utils/constants.js
+++ b/src/utils/constants.js
@@ -1,5 +1,21 @@
export const defaultPageSize = 20
+export const storageKey = {
+ i18n: 'cn-i18n',
+ language: 'cn-language',
+ timezone: 'cn-timezone',
+ timezoneOffset: 'cn-timezone-offset',
+ timezoneLocalOffset: 'cn-timezone-local-offset',
+ token: 'cn-token',
+ username: 'cn-username',
+ sysName: 'cn-sys-name',
+ sysLogo: 'cn-sys-logo',
+ tableTitlePrefix: 'cn-table-title',
+ tablePageSizePrefix: 'cn-page-size',
+ leftMenuShrink: 'cn-left-menu-shrink',
+ unsavedChange: 'cn-unsaved-change'
+}
+
// 统一定义跳转来源
export const fromRoute = {
trafficSummary: 'trafficSummary',
@@ -22,4 +38,4 @@ export const position = {
}
export const chartTableDefaultPageSize = 10 // table类型图表默认每页数据量
-export const chartTableTopOptions = [10, 50, 100] // table类型图表的TOP-N选项
+export const chartTableTopOptions = [10, 100] // table类型图表的TOP-N选项
diff --git a/src/views/charts/Chart.vue b/src/views/charts/Chart.vue
index eca6196d..4f922102 100644
--- a/src/views/charts/Chart.vue
+++ b/src/views/charts/Chart.vue
@@ -1,4 +1,5 @@
+
-
+
+
+
+
+
+
+
{{chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name}}
-