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 @@ - + + +