From 09df3549318d2c002a18e87cc5d19adab7c40e6b Mon Sep 17 00:00:00 2001 From: pnoker Date: Sun, 26 Jan 2020 17:40:09 +0800 Subject: [PATCH] . --- package.json | 4 + public/img/bg/403.svg | 508 ++++++++++++++++++++++++ public/img/bg/404.svg | 314 +++++++++++++++ public/img/bg/500.svg | 208 ++++++++++ src/App.vue | 173 +------- src/api/index.js | 12 + src/api/user.js | 49 +++ src/components/basic-container/main.vue | 27 ++ src/components/error-page/403.vue | 24 ++ src/components/error-page/404.vue | 24 ++ src/components/error-page/500.vue | 24 ++ src/components/error-page/style.scss | 35 ++ src/components/iframe/main.vue | 129 ++++++ src/config/env.js | 21 + src/config/error.js | 25 ++ src/config/permission.js | 88 ++++ src/config/website.js | 39 ++ src/lang/en.js | 0 src/lang/index.js | 26 ++ src/lang/zh.js | 0 src/main.js | 35 +- src/mixins/color.js | 168 ++++++++ src/page/index/top/index.vue | 168 ++++++++ src/page/index/top/top-color.vue | 30 ++ src/page/index/top/top-lang.vue | 44 ++ src/page/index/top/top-lock.vue | 72 ++++ src/page/index/top/top-logs.vue | 43 ++ src/page/index/top/top-menu.vue | 75 ++++ src/page/index/top/top-search.vue | 128 ++++++ src/page/index/top/top-theme.vue | 91 +++++ src/page/login/authredirect.vue | 20 + src/page/login/codelogin.vue | 133 +++++++ src/page/login/index.vue | 102 +++++ src/page/login/thirdlogin.vue | 84 ++++ src/page/login/userlogin.vue | 115 ++++++ src/router/axios.js | 75 ++++ src/router/page/index.js | 50 +++ src/router/router.js | 26 +- src/store/getters.js | 28 ++ src/store/modules/common.js | 92 +++++ src/store/modules/logs.js | 43 ++ src/store/modules/tags.js | 73 ++++ src/store/modules/user.js | 200 ++++++++++ src/store/store.js | 41 +- src/styles/animate/vue-transition.scss | 65 +++ src/styles/common.scss | 28 ++ src/styles/element-ui.scss | 71 ++++ src/styles/login.scss | 163 ++++++++ src/styles/media.scss | 165 ++++++++ src/styles/mixin.scss | 73 ++++ src/styles/normalize.scss | 502 +++++++++++++++++++++++ src/styles/sidebar.scss | 90 +++++ src/styles/tags.scss | 92 +++++ src/styles/theme/d2.scss | 57 +++ src/styles/theme/hey.scss | 45 +++ src/styles/theme/index.scss | 15 + src/styles/theme/iview.scss | 79 ++++ src/styles/theme/star.scss | 92 +++++ src/styles/theme/white.scss | 120 ++++++ src/styles/top.scss | 102 +++++ src/styles/variables.scss | 2 + src/util/auth.js | 15 + src/util/date.js | 50 +++ src/util/store.js | 121 ++++++ src/util/util.js | 288 ++++++++++++++ src/util/validate.js | 253 ++++++++++++ 66 files changed, 5969 insertions(+), 185 deletions(-) create mode 100644 public/img/bg/403.svg create mode 100644 public/img/bg/404.svg create mode 100644 public/img/bg/500.svg create mode 100644 src/api/index.js create mode 100644 src/api/user.js create mode 100644 src/components/basic-container/main.vue create mode 100644 src/components/error-page/403.vue create mode 100644 src/components/error-page/404.vue create mode 100644 src/components/error-page/500.vue create mode 100644 src/components/error-page/style.scss create mode 100644 src/components/iframe/main.vue create mode 100644 src/config/env.js create mode 100644 src/config/error.js create mode 100644 src/config/permission.js create mode 100644 src/config/website.js create mode 100644 src/lang/en.js create mode 100644 src/lang/index.js create mode 100644 src/lang/zh.js create mode 100644 src/mixins/color.js create mode 100644 src/page/index/top/index.vue create mode 100644 src/page/index/top/top-color.vue create mode 100644 src/page/index/top/top-lang.vue create mode 100644 src/page/index/top/top-lock.vue create mode 100644 src/page/index/top/top-logs.vue create mode 100644 src/page/index/top/top-menu.vue create mode 100644 src/page/index/top/top-search.vue create mode 100644 src/page/index/top/top-theme.vue create mode 100644 src/page/login/authredirect.vue create mode 100644 src/page/login/codelogin.vue create mode 100644 src/page/login/index.vue create mode 100644 src/page/login/thirdlogin.vue create mode 100644 src/page/login/userlogin.vue create mode 100644 src/router/axios.js create mode 100644 src/router/page/index.js create mode 100644 src/store/getters.js create mode 100644 src/store/modules/common.js create mode 100644 src/store/modules/logs.js create mode 100644 src/store/modules/tags.js create mode 100644 src/store/modules/user.js create mode 100644 src/styles/animate/vue-transition.scss create mode 100644 src/styles/common.scss create mode 100644 src/styles/element-ui.scss create mode 100644 src/styles/login.scss create mode 100644 src/styles/media.scss create mode 100644 src/styles/mixin.scss create mode 100644 src/styles/normalize.scss create mode 100644 src/styles/sidebar.scss create mode 100644 src/styles/tags.scss create mode 100644 src/styles/theme/d2.scss create mode 100644 src/styles/theme/hey.scss create mode 100644 src/styles/theme/index.scss create mode 100644 src/styles/theme/iview.scss create mode 100644 src/styles/theme/star.scss create mode 100644 src/styles/theme/white.scss create mode 100644 src/styles/top.scss create mode 100644 src/styles/variables.scss create mode 100644 src/util/auth.js create mode 100644 src/util/date.js create mode 100644 src/util/store.js create mode 100644 src/util/util.js create mode 100644 src/util/validate.js diff --git a/package.json b/package.json index 50abf17..b748c1d 100644 --- a/package.json +++ b/package.json @@ -15,8 +15,12 @@ "core-js": "^3.6.2", "echarts": "^4.6.0", "element-ui": "^2.13.0", + "js-base64": "latest", + "js-cookie": "^2.2.1", + "nprogress": "^0.2.0", "vue": "^2.6.11", "vue-axios": "^2.1.5", + "vue-i18n": "^8.15.3", "vue-router": "^3.1.3", "vuex": "^3.1.2" }, diff --git a/public/img/bg/403.svg b/public/img/bg/403.svg new file mode 100644 index 0000000..610f136 --- /dev/null +++ b/public/img/bg/403.svg @@ -0,0 +1,508 @@ + + + + Group 9 + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/bg/404.svg b/public/img/bg/404.svg new file mode 100644 index 0000000..5531d05 --- /dev/null +++ b/public/img/bg/404.svg @@ -0,0 +1,314 @@ + + + + Group 4 + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/bg/500.svg b/public/img/bg/500.svg new file mode 100644 index 0000000..de723b1 --- /dev/null +++ b/public/img/bg/500.svg @@ -0,0 +1,208 @@ + + + + Group 4 + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/App.vue b/src/App.vue index ac71d4a..0176c10 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,171 +1,26 @@ - - + diff --git a/src/api/index.js b/src/api/index.js new file mode 100644 index 0000000..e07ceeb --- /dev/null +++ b/src/api/index.js @@ -0,0 +1,12 @@ +import request from '../router/axios' + +export const getUsualList = (current, size) => { + return request({ + url: '/api/blade-log/usual/list', + method: 'get', + params: { + current, + size + } + }) +} \ No newline at end of file diff --git a/src/api/user.js b/src/api/user.js new file mode 100644 index 0000000..e4d3993 --- /dev/null +++ b/src/api/user.js @@ -0,0 +1,49 @@ +import request from '../router/axios'; +import {baseUrl} from '../config/env'; + +export const loginByUsername = (tenantId, account, password, type) => request({ + url: '/api/blade-auth/token', + method: 'post', + params: { + tenantId, + account, + password, + type + } +}); + +export const getButtons = () => request({ + url: '/api/blade-system/menu/buttons', + method: 'get' +}); + +export const getUserInfo = () => request({ + url: baseUrl + '/user/getUserInfo', + method: 'get' +}); + +export const refeshToken = () => request({ + url: baseUrl + '/user/refesh', + method: 'post' +}); + +export const getMenu = () => request({ + url: '/api/blade-system/menu/routes', + method: 'get' +}); + +export const getTopMenu = () => request({ + url: baseUrl + '/user/getTopMenu', + method: 'get' +}); + +export const sendLogs = (list) => request({ + url: baseUrl + '/user/logout', + method: 'post', + data: list +}); + +export const logout = () => request({ + url: baseUrl + '/user/logout', + method: 'get' +}); diff --git a/src/components/basic-container/main.vue b/src/components/basic-container/main.vue new file mode 100644 index 0000000..d695d9f --- /dev/null +++ b/src/components/basic-container/main.vue @@ -0,0 +1,27 @@ + + + + + diff --git a/src/components/error-page/403.vue b/src/components/error-page/403.vue new file mode 100644 index 0000000..6b4bf9c --- /dev/null +++ b/src/components/error-page/403.vue @@ -0,0 +1,24 @@ + + + + diff --git a/src/components/error-page/404.vue b/src/components/error-page/404.vue new file mode 100644 index 0000000..11a2be8 --- /dev/null +++ b/src/components/error-page/404.vue @@ -0,0 +1,24 @@ + + + + diff --git a/src/components/error-page/500.vue b/src/components/error-page/500.vue new file mode 100644 index 0000000..9ccfda5 --- /dev/null +++ b/src/components/error-page/500.vue @@ -0,0 +1,24 @@ + + + + diff --git a/src/components/error-page/style.scss b/src/components/error-page/style.scss new file mode 100644 index 0000000..c41c163 --- /dev/null +++ b/src/components/error-page/style.scss @@ -0,0 +1,35 @@ +.error-page { + background: #f0f2f5; + margin-top: -30px; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + + .img { + margin-right: 80px; + height: 360px; + width: 100%; + max-width: 430px; + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: contain; + } + + .content { + h1 { + color: #434e59; + font-size: 72px; + font-weight: 600; + line-height: 72px; + margin-bottom: 24px; + } + + .desc { + color: rgba(0, 0, 0, 0.45); + font-size: 20px; + line-height: 28px; + margin-bottom: 16px; + } + } +} \ No newline at end of file diff --git a/src/components/iframe/main.vue b/src/components/iframe/main.vue new file mode 100644 index 0000000..e675457 --- /dev/null +++ b/src/components/iframe/main.vue @@ -0,0 +1,129 @@ + + + + + \ No newline at end of file diff --git a/src/config/env.js b/src/config/env.js new file mode 100644 index 0000000..e51c2ae --- /dev/null +++ b/src/config/env.js @@ -0,0 +1,21 @@ +// 配置编译环境和线上环境之间的切换 + +let baseUrl = ''; +let iconfontVersion = ['567566_pwc3oottzol', '1066523_v8rsbcusj5q']; +let iconfontUrl = `//at.alicdn.com/t/font_$key.css`; +let codeUrl = `${baseUrl}/code` +const env = process.env +if (env.NODE_ENV == 'development') { + baseUrl = ``; // 开发环境地址 +} else if (env.NODE_ENV == 'production') { + baseUrl = ``; //生产环境地址 +} else if (env.NODE_ENV == 'test') { + baseUrl = ``; //测试环境地址 +} +export { + baseUrl, + iconfontUrl, + iconfontVersion, + codeUrl, + env +} diff --git a/src/config/error.js b/src/config/error.js new file mode 100644 index 0000000..8c0c75a --- /dev/null +++ b/src/config/error.js @@ -0,0 +1,25 @@ +import Vue from 'vue'; +import store from '../store/store' + +Vue.config.errorHandler = function (err, vm, info) { + + Vue.nextTick(() => { + store.commit('ADD_LOGS', { + type: 'error', + message: err.message, + stack: err.stack, + info + }) + if (process.env.NODE_ENV === 'development') { + console.group('>>>>>> 错误信息 >>>>>>') + console.log(info) + console.groupEnd(); + console.group('>>>>>> Vue 实例 >>>>>>') + console.log(vm) + console.groupEnd(); + console.group('>>>>>> Error >>>>>>') + console.log(err) + console.groupEnd(); + } + }) +} \ No newline at end of file diff --git a/src/config/permission.js b/src/config/permission.js new file mode 100644 index 0000000..a0e4977 --- /dev/null +++ b/src/config/permission.js @@ -0,0 +1,88 @@ +/** + * 全站权限配置 + * + */ +import router from '../router/router' +import store from '../store/store' +import nprogress from 'nprogress' +import 'nprogress/nprogress.css' +import {validatenull} from '../util/validate' +import {getToken} from '../util/auth' + +nprogress.configure({showSpinner: false}); +const lockPage = store.getters.website.lockPage; //锁屏页 +router.beforeEach((to, from, next) => { + if (to.matched.length === 0 && to.fullPath.indexOf("?sec") === -1) { + next(to.path + "?sec"); + window.location.reload(); + } else { + next(); + } + //缓冲设置 + if (to.meta.keepAlive === true && store.state.tags.tagList.some(ele => { + return ele.value === to.fullPath; + })) { + to.meta.$keepAlive = true; + } else { + nprogress.start(); + if (to.meta.keepAlive === true && validatenull(to.meta.$keepAlive)) { + to.meta.$keepAlive = true; + } else { + to.meta.$keepAlive = false; + } + } + const meta = to.meta || {}; + if (getToken()) { + if (store.getters.isLock && to.path !== lockPage) { //如果系统激活锁屏,全部跳转到锁屏页 + next({path: lockPage}) + } else if (to.path === '/login') { //如果登录成功访问登录页跳转到主页 + next({path: '/'}) + } else { + //如果用户信息为空则获取用户信息,获取用户信息失败,跳转到登录页 + if (store.getters.token.length === 0) { + store.dispatch('FedLogOut').then(() => { + next({path: '/login'}) + }) + } else { + const value = to.query.src || to.fullPath; + const label = to.query.name || to.name; + const meta = to.meta || router.$avueRouter.meta || {}; + const i18n = to.query.i18n; + if (meta.isTab !== false && !validatenull(value) && !validatenull(label)) { + store.commit('ADD_TAG', { + label: label, + value: value, + params: to.params, + query: to.query, + meta: (() => { + if (!i18n) { + return meta + } + return { + i18n: i18n + } + })(), + group: router.$avueRouter.group || [] + }); + } + next() + } + } + } else { + //判断是否需要认证,没有登录访问去登录页 + if (meta.isAuth === false) { + next() + } else { + next('/login') + } + } +}); + +router.afterEach(() => { + nprogress.done(); + let title = store.getters.tag.label; + let i18n = store.getters.tag.meta.i18n; + title = router.$avueRouter.generateTitle(title, i18n) + //根据当前的标签也获取label的值动态设置浏览器标题 + router.$avueRouter.setTitle(title); +}); diff --git a/src/config/website.js b/src/config/website.js new file mode 100644 index 0000000..4dfc863 --- /dev/null +++ b/src/config/website.js @@ -0,0 +1,39 @@ +/** + * 全局配置文件 + */ +export default { + title: "dc3", + indexTitle: 'DC3 UI', + clientId: 'dc3', // 客户端id + clientSecret: 'dc3_secret', // 客户端密钥 + tenantMode: true, // 是否开启租户模式 + logo: "D", + key: 'dc3',//配置主键,目前用于存储 + lockPage: '/lock', + tokenTime: 6000, + //http的status默认放行不才用统一处理的, + statusWhiteList: [], + //配置首页不可关闭 + isFirstPage: false, + fistPage: { + label: "首页", + value: "/wel/index", + params: {}, + query: {}, + meta: { + i18n: 'dashboard' + }, + group: [], + close: false + }, + //配置菜单的属性 + menu: { + iconDefault: 'iconfont icon-caidan', + props: { + label: 'name', + path: 'path', + icon: 'source', + children: 'children' + } + } +} diff --git a/src/lang/en.js b/src/lang/en.js new file mode 100644 index 0000000..e69de29 diff --git a/src/lang/index.js b/src/lang/index.js new file mode 100644 index 0000000..126efbd --- /dev/null +++ b/src/lang/index.js @@ -0,0 +1,26 @@ +import Vue from 'vue' +import VueI18n from 'vue-i18n' +import elementEnLocale from 'element-ui/lib/locale/lang/en' // element-ui lang +import elementZhLocale from 'element-ui/lib/locale/lang/zh-CN' // element-ui lang +import enLocale from './en' +import zhLocale from './zh' +import {getStore} from '../util/store' + +Vue.use(VueI18n); +const messages = { + en: { + ...enLocale, + ...elementEnLocale + }, + zh: { + ...zhLocale, + ...elementZhLocale + } +} + +const i18n = new VueI18n({ + locale: getStore({name: 'language'}) || 'zh', + messages +}); + +export default i18n \ No newline at end of file diff --git a/src/lang/zh.js b/src/lang/zh.js new file mode 100644 index 0000000..e69de29 diff --git a/src/main.js b/src/main.js index ab41fae..a75885d 100644 --- a/src/main.js +++ b/src/main.js @@ -1,18 +1,47 @@ import Vue from 'vue' -import App from './App.vue' +import App from './App' import router from './router/router' import store from './store/store' //Element UI +import Element from 'element-ui' import './plugins/element/element.js' //Axios -import axios from 'axios' +import axios from './router/axios' import VueAxios from 'vue-axios' +//Util +import './config/permission' +import './config/error' +import i18n from './lang' +import {loadStyle} from './util/util' +import * as urls from './config/env' +import {iconfontUrl, iconfontVersion} from './config/env' +import './styles/common.scss'; +import basicContainer from './components/basic-container/main' -Vue.config.productionTip = false +Vue.use(router); Vue.use(VueAxios, axios); +Vue.use(Element, { + i18n: (key, value) => i18n.t(key, value) +}); + +//注册全局容器 +Vue.component('basicContainer', basicContainer); + +// 加载相关url地址 +Object.keys(urls).forEach(key => { + Vue.prototype[key] = urls[key]; +}); + +// 动态加载阿里云字体库 +iconfontVersion.forEach(ele => { + loadStyle(iconfontUrl.replace('$key', ele)); +}); + +Vue.config.productionTip = false; new Vue({ router, store, + i18n, render: h => h(App) }).$mount('#app') diff --git a/src/mixins/color.js b/src/mixins/color.js new file mode 100644 index 0000000..6d2cee9 --- /dev/null +++ b/src/mixins/color.js @@ -0,0 +1,168 @@ +import { mapGetters } from "vuex"; +const version = require("element-ui/package.json").version; // element-ui version from node_modules +const ORIGINAL_THEME = "#409EFF"; // default color +export default function () { + return { + data() { + return { + themeVal: ORIGINAL_THEME + } + }, + created() { + this.themeVal = this.colorName; + }, + watch: { + themeVal(val, oldVal) { + this.$store.commit("SET_COLOR_NAME", val); + this.updateTheme(val, oldVal); + } + }, + computed: { + ...mapGetters(["colorName"]) + }, + methods: { + updateTheme(val, oldVal) { + if (typeof val !== "string") return; + const head = document.getElementsByTagName("head")[0]; + const themeCluster = this.getThemeCluster(val.replace("#", "")); + const originalCluster = this.getThemeCluster(oldVal.replace("#", "")); + const getHandler = (variable, id) => { + return () => { + const originalCluster = this.getThemeCluster( + ORIGINAL_THEME.replace("#", "") + ); + const newStyle = this.updateStyle( + this[variable], + originalCluster, + themeCluster + ); + + let styleTag = document.getElementById(id); + if (!styleTag) { + styleTag = document.createElement("style"); + styleTag.setAttribute("id", id); + head.appendChild(styleTag); + } + styleTag.innerText = newStyle; + }; + }; + + const chalkHandler = getHandler("chalk", "chalk-style"); + + if (!this.chalk) { + const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css`; + this.getCSSString(url, chalkHandler, "chalk"); + } else { + chalkHandler(); + } + + const link = [].slice.call( + document.getElementsByTagName("head")[0].getElementsByTagName("link") + ); + for (let i = 0; i < link.length; i++) { + const style = link[i]; + if (style.href.includes('css')) { + this.getCSSString(style.href, innerText => { + const originalCluster = this.getThemeCluster( + ORIGINAL_THEME.replace("#", "") + ); + const newStyle = this.updateStyle( + innerText, + originalCluster, + themeCluster + ); + let styleTag = document.getElementById(i); + if (!styleTag) { + styleTag = document.createElement("style"); + styleTag.id = i; + styleTag.innerText = newStyle; + head.appendChild(styleTag); + } + }); + } + } + + const styles = [].slice.call(document.querySelectorAll("style")) + + styles.forEach(style => { + const { + innerText + } = style; + if (typeof innerText !== "string") return; + style.innerText = this.updateStyle( + innerText, + originalCluster, + themeCluster + ); + }); + }, + updateStyle(style, oldCluster, newCluster) { + let newStyle = style; + oldCluster.forEach((color, index) => { + newStyle = newStyle.replace(new RegExp(color, "ig"), newCluster[index]); + }); + return newStyle; + }, + + getCSSString(url, callback, variable) { + const xhr = new XMLHttpRequest(); + xhr.onreadystatechange = () => { + if (xhr.readyState === 4 && xhr.status === 200) { + if (variable) { + this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, ""); + } + callback(xhr.responseText); + } + }; + xhr.open("GET", url); + xhr.send(); + }, + + getThemeCluster(theme) { + const tintColor = (color, tint) => { + let red = parseInt(color.slice(0, 2), 16); + let green = parseInt(color.slice(2, 4), 16); + let blue = parseInt(color.slice(4, 6), 16); + + if (tint === 0) { + // when primary color is in its rgb space + return [red, green, blue].join(","); + } else { + red += Math.round(tint * (255 - red)); + green += Math.round(tint * (255 - green)); + blue += Math.round(tint * (255 - blue)); + + red = red.toString(16); + green = green.toString(16); + blue = blue.toString(16); + + return `#${red}${green}${blue}`; + } + }; + + const shadeColor = (color, shade) => { + let red = parseInt(color.slice(0, 2), 16); + let green = parseInt(color.slice(2, 4), 16); + let blue = parseInt(color.slice(4, 6), 16); + + red = Math.round((1 - shade) * red); + green = Math.round((1 - shade) * green); + blue = Math.round((1 - shade) * blue); + + red = red.toString(16); + green = green.toString(16); + blue = blue.toString(16); + + return `#${red}${green}${blue}`; + }; + + const clusters = [theme]; + for (let i = 0; i <= 9; i++) { + clusters.push(tintColor(theme, Number((i / 10).toFixed(2)))); + } + clusters.push(shadeColor(theme, 0.1)); + return clusters; + } + } + } +} \ No newline at end of file diff --git a/src/page/index/top/index.vue b/src/page/index/top/index.vue new file mode 100644 index 0000000..4067ad1 --- /dev/null +++ b/src/page/index/top/index.vue @@ -0,0 +1,168 @@ + + + + diff --git a/src/page/index/top/top-color.vue b/src/page/index/top/top-color.vue new file mode 100644 index 0000000..ab433c0 --- /dev/null +++ b/src/page/index/top/top-color.vue @@ -0,0 +1,30 @@ + + + + + diff --git a/src/page/index/top/top-lang.vue b/src/page/index/top/top-lang.vue new file mode 100644 index 0000000..e3e4b65 --- /dev/null +++ b/src/page/index/top/top-lang.vue @@ -0,0 +1,44 @@ + + + + + diff --git a/src/page/index/top/top-lock.vue b/src/page/index/top/top-lock.vue new file mode 100644 index 0000000..48ff32c --- /dev/null +++ b/src/page/index/top/top-lock.vue @@ -0,0 +1,72 @@ + + + + + diff --git a/src/page/index/top/top-logs.vue b/src/page/index/top/top-logs.vue new file mode 100644 index 0000000..d80f2d4 --- /dev/null +++ b/src/page/index/top/top-logs.vue @@ -0,0 +1,43 @@ + + + + + diff --git a/src/page/index/top/top-menu.vue b/src/page/index/top/top-menu.vue new file mode 100644 index 0000000..f92d474 --- /dev/null +++ b/src/page/index/top/top-menu.vue @@ -0,0 +1,75 @@ + + + \ No newline at end of file diff --git a/src/page/index/top/top-search.vue b/src/page/index/top/top-search.vue new file mode 100644 index 0000000..40efd97 --- /dev/null +++ b/src/page/index/top/top-search.vue @@ -0,0 +1,128 @@ + + + + + \ No newline at end of file diff --git a/src/page/index/top/top-theme.vue b/src/page/index/top/top-theme.vue new file mode 100644 index 0000000..b2713c2 --- /dev/null +++ b/src/page/index/top/top-theme.vue @@ -0,0 +1,91 @@ + + + + + + diff --git a/src/page/login/authredirect.vue b/src/page/login/authredirect.vue new file mode 100644 index 0000000..15cbce1 --- /dev/null +++ b/src/page/login/authredirect.vue @@ -0,0 +1,20 @@ + + + + + + diff --git a/src/page/login/codelogin.vue b/src/page/login/codelogin.vue new file mode 100644 index 0000000..dfd8061 --- /dev/null +++ b/src/page/login/codelogin.vue @@ -0,0 +1,133 @@ + + + + + diff --git a/src/page/login/index.vue b/src/page/login/index.vue new file mode 100644 index 0000000..39aa552 --- /dev/null +++ b/src/page/login/index.vue @@ -0,0 +1,102 @@ + + + + \ No newline at end of file diff --git a/src/page/login/thirdlogin.vue b/src/page/login/thirdlogin.vue new file mode 100644 index 0000000..eda4d96 --- /dev/null +++ b/src/page/login/thirdlogin.vue @@ -0,0 +1,84 @@ + + + + + diff --git a/src/page/login/userlogin.vue b/src/page/login/userlogin.vue new file mode 100644 index 0000000..61495c2 --- /dev/null +++ b/src/page/login/userlogin.vue @@ -0,0 +1,115 @@ + + + + + diff --git a/src/router/axios.js b/src/router/axios.js new file mode 100644 index 0000000..759ea4a --- /dev/null +++ b/src/router/axios.js @@ -0,0 +1,75 @@ +/** + * 全站http配置 + * + * axios参数说明 + * isSerialize是否开启form表单提交 + * isToken是否需要token + */ +import axios from 'axios' +import store from '../store/store'; +import router from '../router/router' +import website from '../config/website'; + +import nprogress from 'nprogress' +import 'nprogress/nprogress.css' +import {Message} from 'element-ui' +import {serialize} from '../util/util' +import {getToken} from '../util/auth' +import {Base64} from 'js-base64'; + +axios.defaults.timeout = 10000; +//返回其他状态吗 +axios.defaults.validateStatus = function (status) { + return status >= 200 && status <= 500; // 默认的 +}; + +//跨域请求,允许保存cookie +axios.defaults.withCredentials = true; +// nprogress Configuration +nprogress.configure({ + showSpinner: false +}); + +//http request拦截 +axios.interceptors.request.use(config => { + nprogress.start();// start progress bar + const meta = (config.meta || {}); + const isToken = meta.isToken === false; + config.headers['Authorization'] = `Basic ${Base64.encode(`${website.clientId}:${website.clientSecret}`)}`; + if (getToken() && !isToken) { + config.headers['Blade-Auth'] = 'bearer ' + getToken() // 让每个请求携带token--['Authorization']为自定义key 请根据实际情况自行修改 + } + //headers中配置serialize为true开启序列化 + if (config.method === 'post' && meta.isSerialize === true) { + config.data = serialize(config.data); + } + return config +}, error => { + return Promise.reject(error) +}); + +//http response拦截 +axios.interceptors.response.use(res => { + nprogress.done(); + const status = res.data.code || 200; + const statusWhiteList = website.statusWhiteList || []; + const message = res.data.msg || '未知错误'; + //如果在白名单里则自行catch逻辑处理 + if (statusWhiteList.includes(status)) return Promise.reject(res); + //如果是401则跳转到登录页面 + if (status === 401) store.dispatch('FedLogOut').then(() => router.push({path: '/login'})); + // 如果请求为非200否者默认统一处理 + if (status !== 200) { + Message({ + message: message, + type: 'error' + }); + return Promise.reject(new Error(message)) + } + return res; +}, error => { + nprogress.done(); + return Promise.reject(new Error(error)); +}); + +export default axios; diff --git a/src/router/page/index.js b/src/router/page/index.js new file mode 100644 index 0000000..1033358 --- /dev/null +++ b/src/router/page/index.js @@ -0,0 +1,50 @@ +export default [{ + path: '/login', + name: '登录页', + component: () => + import( /* webpackChunkName: "page" */ '@/page/login/index'), + meta: { + keepAlive: true, + isTab: false, + isAuth: false + } +}, + { + path: '/404', + component: () => + import( /* webpackChunkName: "page" */ '@/components/error-page/404'), + name: '404', + meta: { + keepAlive: true, + isTab: false, + isAuth: false + } + + }, + { + path: '/403', + component: () => + import( /* webpackChunkName: "page" */ '@/components/error-page/403'), + name: '403', + meta: { + keepAlive: true, + isTab: false, + isAuth: false + } + }, + { + path: '/500', + component: () => + import( /* webpackChunkName: "page" */ '@/components/error-page/500'), + name: '500', + meta: { + keepAlive: true, + isTab: false, + isAuth: false + } + }, + { + path: '*', + redirect: '/404' + } +] \ No newline at end of file diff --git a/src/router/router.js b/src/router/router.js index b3c5404..7360b5f 100644 --- a/src/router/router.js +++ b/src/router/router.js @@ -1,5 +1,5 @@ -import Vue from 'vue' import VueRouter from 'vue-router' +import PageRouter from './page/' import Home from '../views/Home.vue' import Things from '../views/Things.vue' import Template from '../views/Template.vue' @@ -11,8 +11,6 @@ import Picture from '../views/Picture.vue' import Video from '../views/Video.vue' import About from '../views/About.vue' -Vue.use(VueRouter) - const routes = [ { path: '/', @@ -64,10 +62,24 @@ const routes = [ name: 'about', component: About } -] +]; -const router = new VueRouter({ +let Router = new VueRouter({ + scrollBehavior(to, from, savedPosition) { + if (savedPosition) { + return savedPosition + } else { + if (from.meta.keepAlive) { + from.meta.savedPosition = document.body.scrollTop; + } + return { + x: 0, + y: to.meta.savedPosition || 0 + } + } + }, routes -}) +}); -export default router +Router.addRoutes([...PageRouter]); +export default Router diff --git a/src/store/getters.js b/src/store/getters.js new file mode 100644 index 0000000..b69b8c5 --- /dev/null +++ b/src/store/getters.js @@ -0,0 +1,28 @@ +const getters = { + nav: state => state.state.nav, + + tag: state => state.tags.tag, + language: state => state.common.language, + website: state => state.common.website, + userInfo: state => state.user.userInfo, + colorName: state => state.common.colorName, + themeName: state => state.common.themeName, + isShade: state => state.common.isShade, + isCollapse: state => state.common.isCollapse, + keyCollapse: (state, getters) => getters.screen > 1 ? getters.isCollapse : false, + screen: state => state.common.screen, + isLock: state => state.common.isLock, + isFullScren: state => state.common.isFullScren, + lockPasswd: state => state.common.lockPasswd, + tagList: state => state.tags.tagList, + tagWel: state => state.tags.tagWel, + token: state => state.user.token, + roles: state => state.user.roles, + permission: state => state.user.permission, + menu: state => state.user.menu, + menuAll: state => state.user.menuAll, + logsList: state => state.logs.logsList, + logsLen: state => state.logs.logsList.length || 0, + logsFlag: (state, getters) => getters.logsLen === 0 +}; +export default getters \ No newline at end of file diff --git a/src/store/modules/common.js b/src/store/modules/common.js new file mode 100644 index 0000000..cbcb463 --- /dev/null +++ b/src/store/modules/common.js @@ -0,0 +1,92 @@ +import {getStore, removeStore, setStore} from '../../util/store' +import website from '../../config/website' + +const common = { + + state: { + language: getStore({name: 'language'}) || 'zh', + isCollapse: false, + isFullScren: false, + isShade: false, + screen: -1, + isLock: getStore({name: 'isLock'}) || false, + showTag: true, + showDebug: true, + showCollapse: true, + showSearch: true, + showLock: true, + showFullScren: true, + showTheme: true, + showMenu: true, + showColor: true, + colorName: getStore({name: 'colorName'}) || '#409EFF', + themeName: getStore({name: 'themeName'}) || 'theme-default', + lockPasswd: getStore({name: 'lockPasswd'}) || '', + website: website, + }, + mutations: { + SET_LANGUAGE: (state, language) => { + state.language = language + setStore({ + name: 'language', + content: state.language + }) + }, + SET_SHADE: (state, active) => { + state.isShade = active; + }, + SET_COLLAPSE: (state) => { + state.isCollapse = !state.isCollapse; + }, + SET_FULLSCREN: (state) => { + state.isFullScren = !state.isFullScren; + }, + SET_LOCK: (state) => { + state.isLock = true; + setStore({ + name: 'isLock', + content: state.isLock, + type: 'session' + }) + }, + SET_SCREEN: (state, screen) => { + state.screen = screen; + }, + SET_COLOR_NAME: (state, colorName) => { + state.colorName = colorName; + setStore({ + name: 'colorName', + content: state.colorName, + }) + }, + SET_THEME_NAME: (state, themeName) => { + state.themeName = themeName; + setStore({ + name: 'themeName', + content: state.themeName, + }) + }, + SET_LOCK_PASSWD: (state, lockPasswd) => { + state.lockPasswd = lockPasswd; + setStore({ + name: 'lockPasswd', + content: state.lockPasswd, + type: 'session' + }) + }, + CLEAR_LOCK: (state) => { + state.isLock = false; + state.lockPasswd = ''; + removeStore({ + name: 'lockPasswd', + type: 'session' + }); + removeStore({ + name: 'isLock', + type: 'session' + }); + }, + } +}; + +export default common \ No newline at end of file diff --git a/src/store/modules/logs.js b/src/store/modules/logs.js new file mode 100644 index 0000000..fdf959d --- /dev/null +++ b/src/store/modules/logs.js @@ -0,0 +1,43 @@ +import {getStore, setStore} from '../../util/store' +import {dateFormat} from '../../util/date' +import {sendLogs} from '../../api/user' + +const logs = { + state: { + logsList: getStore({name: 'logsList'}) || [], + }, + actions: { + //发送错误日志 + SendLogs({state, commit}) { + return new Promise((resolve, reject) => { + sendLogs(state.logsList).then(() => { + commit('CLEAR_LOGS'); + resolve(); + }).catch(error => { + reject(error) + }) + }) + }, + }, + mutations: { + ADD_LOGS: (state, {type, message, stack, info}) => { + state.logsList.push(Object.assign({ + url: window.location.href, + time: dateFormat(new Date()) + }, { + type, + message, + stack, + info: info.toString() + })) + setStore({name: 'logsList', content: state.logsList}) + }, + CLEAR_LOGS: (state) => { + state.logsList = []; + setStore({name: 'logsList', content: state.logsList}) + } + } + +}; + +export default logs; \ No newline at end of file diff --git a/src/store/modules/tags.js b/src/store/modules/tags.js new file mode 100644 index 0000000..ecb9a80 --- /dev/null +++ b/src/store/modules/tags.js @@ -0,0 +1,73 @@ +import {getStore, setStore} from '../../util/store' +import {diff} from '../../util/util' +import website from '../../config/website' + +const isFirstPage = website.isFirstPage; +const tagWel = website.fistPage; +const tagObj = { + label: '', //标题名称 + value: '', //标题的路径 + params: '', //标题的路径参数 + query: '', //标题的参数 + meta: {},//额外参数 + group: [], //分组 +} + +//处理首个标签 +function setFistTag(list) { + if (list.length == 1) { + list[0].close = false; + } else { + list.forEach(ele => { + if (ele.value === tagWel.value && isFirstPage === false) { + ele.close = false + } else { + ele.close = true + } + }) + } +} + + +const navs = { + state: { + tagList: getStore({name: 'tagList'}) || [], + tag: getStore({name: 'tag'}) || tagObj, + tagWel: tagWel + }, + actions: {}, + mutations: { + ADD_TAG: (state, action) => { + state.tag = action; + setStore({name: 'tag', content: state.tag, type: 'session'}) + if (state.tagList.some(ele => diff(ele, action))) return + state.tagList.push(action) + setFistTag(state.tagList); + setStore({name: 'tagList', content: state.tagList, type: 'session'}) + }, + DEL_TAG: (state, action) => { + state.tagList = state.tagList.filter(item => { + return !diff(item, action); + }) + setFistTag(state.tagList); + setStore({name: 'tagList', content: state.tagList, type: 'session'}) + }, + DEL_ALL_TAG: (state) => { + state.tagList = [state.tagWel]; + setStore({name: 'tagList', content: state.tagList, type: 'session'}) + }, + DEL_TAG_OTHER: (state) => { + state.tagList = state.tagList.filter(item => { + if (item.value === state.tag.value) { + return true; + } else if (!website.isFirstPage && item.value === website.fistPage.value) { + return true; + } + }) + setFistTag(state.tagList); + setStore({name: 'tagList', content: state.tagList, type: 'session'}) + }, + } +}; + +export default navs \ No newline at end of file diff --git a/src/store/modules/user.js b/src/store/modules/user.js new file mode 100644 index 0000000..689c385 --- /dev/null +++ b/src/store/modules/user.js @@ -0,0 +1,200 @@ +import {removeToken, setToken} from '../../util/auth' +import {getStore, setStore} from '../../util/store' +import {isURL, validatenull} from '../../util/validate' +import {deepClone} from '../../util/util' +import website from '../../config/website' +import {getButtons, getMenu, getTopMenu, getUserInfo, loginByUsername, logout, refeshToken} from '../../api/user' + +function addPath(ele, first) { + const menu = website.menu; + const propsConfig = menu.props; + const propsDefault = { + label: propsConfig.label || 'name', + path: propsConfig.path || 'path', + icon: propsConfig.icon || 'icon', + children: propsConfig.children || 'children' + } + const icon = ele[propsDefault.icon]; + ele[propsDefault.icon] = validatenull(icon) ? menu.iconDefault : icon; + const isChild = ele[propsDefault.children] && ele[propsDefault.children].length !== 0; + if (!isChild) ele[propsDefault.children] = []; + if (!isChild && first && !isURL(ele[propsDefault.path])) { + ele[propsDefault.path] = ele[propsDefault.path] + '/index' + } else { + ele[propsDefault.children].forEach(child => { + addPath(child); + }) + } + +} + +const user = { + state: { + userInfo: getStore({name: 'userInfo'}) || [], + permission: getStore({name: 'permission'}) || {}, + roles: [], + menu: getStore({name: 'menu'}) || [], + menuAll: [], + token: getStore({name: 'token'}) || '', + }, + actions: { + //根据用户名登录 + LoginByUsername({commit}, userInfo) { + return new Promise((resolve, reject) => { + loginByUsername(userInfo.tenantId, userInfo.username, userInfo.password, userInfo.type).then(res => { + const data = res.data.data; + commit('SET_TOKEN', data.accessToken); + commit('SET_USERIFNO', data); + commit('DEL_ALL_TAG'); + commit('CLEAR_LOCK'); + resolve(); + }).catch(error => { + reject(error); + }) + }) + }, + GetButtons({commit}) { + return new Promise((resolve) => { + getButtons().then(res => { + const data = res.data.data; + commit('SET_PERMISSION', data); + resolve(); + }) + }) + }, + //根据手机号登录 + LoginByPhone({commit}, userInfo) { + return new Promise((resolve) => { + loginByUsername(userInfo.phone, userInfo.code).then(res => { + const data = res.data.data; + commit('SET_TOKEN', data); + commit('DEL_ALL_TAG'); + commit('CLEAR_LOCK'); + resolve(); + }) + }) + }, + GetUserInfo({commit}) { + return new Promise((resolve, reject) => { + getUserInfo().then((res) => { + const data = res.data.data; + commit('SET_ROLES', data.roles); + resolve(data); + }).catch(err => { + reject(err); + }) + }) + }, + //刷新token + RefeshToken({state, commit}) { + return new Promise((resolve, reject) => { + refeshToken(state.refeshToken).then(res => { + const data = res.data.data; + commit('SET_TOKEN', data); + resolve(data); + }).catch(error => { + reject(error) + }) + }) + }, + // 登出 + LogOut({commit}) { + return new Promise((resolve, reject) => { + logout().then(() => { + commit('SET_TOKEN', '') + commit('SET_MENU', []) + commit('SET_ROLES', []) + commit('DEL_ALL_TAG'); + commit('CLEAR_LOCK'); + removeToken() + resolve() + }).catch(error => { + reject(error) + }) + }) + }, + //注销session + FedLogOut({commit}) { + return new Promise(resolve => { + commit('SET_TOKEN', '') + commit('SET_MENU', []) + commit('SET_ROLES', []) + commit('DEL_ALL_TAG'); + commit('CLEAR_LOCK'); + removeToken() + resolve() + }) + }, + GetTopMenu() { + return new Promise(resolve => { + getTopMenu().then((res) => { + const data = res.data.data || [] + resolve(data) + }) + }) + }, + //获取系统菜单 + GetMenu({commit, dispatch}, parentId) { + return new Promise(resolve => { + getMenu(parentId).then((res) => { + const data = res.data.data + let menu = deepClone(data); + menu.forEach(ele => { + addPath(ele, true); + }) + commit('SET_MENU', menu) + dispatch('GetButtons'); + resolve(menu) + }) + }) + }, + }, + mutations: { + SET_TOKEN: (state, token) => { + setToken(token) + state.token = token; + setStore({name: 'token', content: state.token, type: 'session'}) + }, + SET_USERIFNO: (state, userInfo) => { + state.userInfo = userInfo; + setStore({name: 'userInfo', content: state.userInfo}) + }, + SET_MENU: (state, menu) => { + state.menu = menu + setStore({name: 'menu', content: state.menu, type: 'session'}) + }, + SET_MENU_ALL: (state, menuAll) => { + state.menuAll = menuAll; + }, + SET_ROLES: (state, roles) => { + state.roles = roles; + }, + SET_PERMISSION: (state, permission) => { + let result = []; + + function getCode(list) { + list.forEach(ele => { + if (typeof (ele) === 'object') { + const chiildren = ele.children; + const code = ele.code; + if (chiildren) { + getCode(chiildren) + } else { + result.push(code); + } + } + + }) + } + + getCode(permission); + state.permission = {}; + result.forEach(ele => { + state.permission[ele] = true; + }); + setStore({name: 'permission', content: state.permission, type: 'session'}) + } + } + +} +export default user diff --git a/src/store/store.js b/src/store/store.js index 5955c89..0f4a5a9 100644 --- a/src/store/store.js +++ b/src/store/store.js @@ -1,20 +1,29 @@ import Vue from 'vue' import Vuex from 'vuex' +import user from './modules/user' +import common from './modules/common' +import tags from './modules/tags' +import logs from './modules/logs' +import getters from './getters' -Vue.use(Vuex) +Vue.use(Vuex); -export default new Vuex.Store({ - state: { - nav: '/' - }, - mutations: { - handleSelect(state, index) { - state.nav = index; - } - }, - getters:{ - getNav(state){ - return state.nav; - } - } -}) +const store = new Vuex.Store({ + state: { + nav: '/' + }, + mutations: { + handleSelect(state, index) { + state.nav = index; + } + }, + modules: { + user, + common, + logs, + tags + }, + getters +}); + +export default store \ No newline at end of file diff --git a/src/styles/animate/vue-transition.scss b/src/styles/animate/vue-transition.scss new file mode 100644 index 0000000..c73902c --- /dev/null +++ b/src/styles/animate/vue-transition.scss @@ -0,0 +1,65 @@ +// 过渡动画 横向渐变 +.fade-transverse-leave-active, +.fade-transverse-enter-active { + transition: all .5s; +} + +.fade-transverse-enter { + opacity: 0; + transform: translateX(-30px); +} + +.fade-transverse-leave-to { + opacity: 0; + transform: translateX(30px); +} + +// 过渡动画 缩放渐变 +.fade-scale-leave-active, +.fade-scale-enter-active { + transition: all .5s; +} + +.fade-scale-enter { + opacity: 0; + transform: scale(1.2); +} + +.fade-scale-leave-to { + opacity: 0; + transform: scale(0.8); +} + +@-webkit-keyframes animate-cloud { + from { + background-position: 600px 100%; + } + to { + background-position: 0 100%; + } + } + @-moz-keyframes animate-cloud { + from { + background-position: 600px 100%; + } + to { + background-position: 0 100%; + } + } + @-ms-keyframes animate-cloud { + from { + background-position: 600px 100%; + } + to { + background-position: 0 100%; + } + } + @-o-keyframes animate-cloud { + from { + background-position: 600px 100%; + } + to { + background-position: 0 100%; + } + } + \ No newline at end of file diff --git a/src/styles/common.scss b/src/styles/common.scss new file mode 100644 index 0000000..82a1d0b --- /dev/null +++ b/src/styles/common.scss @@ -0,0 +1,28 @@ +// 全局变量 +@import './variables.scss'; +// ele样式覆盖 +@import './element-ui.scss'; +// 顶部右侧显示 +@import './top.scss'; +// 导航标签 +@import './tags.scss'; +// 工具类函数 +@import './mixin.scss'; +// 侧面导航栏 +@import './sidebar.scss'; +// 动画 +@import './animate/vue-transition.scss'; +//主题 +@import './theme/index.scss'; +//适配 +@import './media.scss'; +//通用配置 +@import './normalize.scss'; + +a{ + text-decoration: none; + color:#333; +} +*{ + outline: none; +} \ No newline at end of file diff --git a/src/styles/element-ui.scss b/src/styles/element-ui.scss new file mode 100644 index 0000000..71f33c5 --- /dev/null +++ b/src/styles/element-ui.scss @@ -0,0 +1,71 @@ +.el-dropdown-menu__item { + font-size: 12px !important; + line-height: 28px !important; +} +.el-card.is-always-shadow { + box-shadow: none; + border: none !important; +} + +.el-scrollbar__view { + height: 100%; +} + +.el-menu--horizontal { + border-bottom: none !important; +} + +.el-menu { + border-right: none !important; +} + +.el-menu--display, +.el-menu--display+.el-submenu__icon-arrow { + display: none; +} + + + +.el-message__icon, +.el-message__content { + display: inline-block; +} + +.el-date-editor .el-range-input, +.el-date-editor .el-range-separator { + height: auto; + overflow: hidden; +} + +.el-dialog__wrapper { + z-index: 2048; +} + +.el-scrollbar__wrap { + overflow-x: hidden; +} + +.el-col { + margin-bottom: 8px; +} + +.el-main { + padding: 0 !important; +} +.el-dropdown-menu__item--divided:before, .el-menu, .el-menu--horizontal>.el-menu-item:not(.is-disabled):focus, .el-menu--horizontal>.el-menu-item:not(.is-disabled):hover, .el-menu--horizontal>.el-submenu .el-submenu__title:hover { + background-color:transparent; +} + + +.el-dropdown-menu__item--divided:before, .el-menu, .el-menu--horizontal>.el-menu-item:not(.is-disabled):focus, .el-menu--horizontal>.el-menu-item:not(.is-disabled):hover, .el-menu--horizontal>.el-submenu .el-submenu__title:hover{ + background-color: transparent !important; +} + +.el-card__header { + padding: 6px 18px !important; +} + +.el-card__body { + padding: 16px !important; +} + diff --git a/src/styles/login.scss b/src/styles/login.scss new file mode 100644 index 0000000..98df885 --- /dev/null +++ b/src/styles/login.scss @@ -0,0 +1,163 @@ +.login-container { + display: flex; + align-items: center; + position: relative; + width: 100%; + height: 100%; + margin: 0 auto; + background: url("http://www.17sucai.com/preview/242158/2015-01-10/%E7%99%BB%E5%BD%95/images/cloud.jpg") + 0 bottom repeat-x #049ec4; + animation: animate-cloud 20s linear infinite; +} +.login-weaper { + margin: 0 auto; + width: 1000px; + box-shadow: -4px 5px 10px rgba(0, 0, 0, 0.4); + .el-input-group__append { + border: none; + } +} + +.login-left, +.login-border { + position: relative; + min-height: 500px; + align-items: center; + display: flex; +} +.login-left { + border-top-left-radius: 5px; + border-bottom-left-radius: 5px; + justify-content: center; + flex-direction: column; + background-color: #409EFF; + color: #fff; + float: left; + width: 50%; + position: relative; +} +.login-left .img { + width: 140px; +} +.login-time { + position: absolute; + left: 25px; + top: 25px; + width: 100%; + color: #fff; + font-weight: 200; + opacity: 0.9; + font-size: 18px; + overflow: hidden; +} +.login-left .title { + margin-top: 60px; + text-align: center; + color: #fff; + font-weight: 300; + letter-spacing: 2px; + font-size: 25px; +} + +.login-border { + border-left: none; + border-top-right-radius: 5px; + border-bottom-right-radius: 5px; + color: #fff; + background-color: #fff; + width: 50%; + float: left; + box-sizing: border-box; +} +.login-main { + margin: 0 auto; + width: 65%; + box-sizing: border-box; +} +.login-main > h3 { + margin-bottom: 20px; +} +.login-main > p { + color: #76838f; +} +.login-title { + color: #333; + margin-bottom: 40px; + font-weight: 500; + font-size: 22px; + text-align: center; + letter-spacing: 4px; +} +.login-menu { + margin-top: 40px; + width: 100%; + text-align: center; + a { + color: #999; + font-size: 12px; + margin: 0px 8px; + } +} +.login-submit { + width: 100%; + height: 45px; + border: 1px solid #409EFF; + background: none; + font-size: 18px; + letter-spacing: 2px; + font-weight: 300; + color: #409EFF; + cursor: pointer; + margin-top: 30px; + font-family: "neo"; + transition: 0.25s; +} +.login-form { + margin: 10px 0; + i { + color: #333; + } + .el-form-item__content { + width: 100%; + } + .el-form-item { + margin-bottom: 12px; + } + .el-input { + input { + padding-bottom: 10px; + text-indent: 5px; + background: transparent; + border: none; + border-radius: 0; + color: #333; + border-bottom: 1px solid rgb(235, 237, 242); + } + .el-input__prefix { + i { + padding: 0 5px; + font-size: 16px !important; + } + } + } +} +.login-code { + display: flex; + align-items: center; + justify-content: space-around; + margin: 0 0 0 10px; +} +.login-code-img { + margin-top: 2px; + width: 100px; + height: 38px; + background-color: #fdfdfd; + border: 1px solid #f0f0f0; + color: #333; + font-size: 14px; + font-weight: bold; + letter-spacing: 5px; + line-height: 38px; + text-indent: 5px; + text-align: center; +} \ No newline at end of file diff --git a/src/styles/media.scss b/src/styles/media.scss new file mode 100644 index 0000000..44bede4 --- /dev/null +++ b/src/styles/media.scss @@ -0,0 +1,165 @@ +.avue-left, +.avue-header, +.avue-top, +.avue-logo, +.avue-layout +.login-logo, +.avue-main { + transition: all .3s; +} +.avue-contail { + width: 100%; + height: 100%; + background: #f0f2f5; + background-size: 100%; + background-repeat: no-repeat; +} + + +.avue-left { + position: fixed; + left: 0; + top: 0; + width: 240px; + height: 100%; + z-index: 1025; +} + +.avue--collapse { + .avue-left, + .avue-logo { + width: 60px; + } + .avue-header { + padding-left: 60px; + } + .avue-main { + width: calc(100% - 60px); + left: 60px; + } +} + +.avue-header { + padding-left: 240px; + width: 100%; + background-color: #fff; + box-sizing: border-box; +} + +.avue-main { + position: absolute; + left: 240px; + padding: 0; + padding-bottom: 20px; + width: calc(100% - 240px); + height: calc(100% - 70px); + box-sizing: border-box; + overflow: hidden; +} + +.avue-view { + padding-bottom: 22px; + width: 100%; + box-sizing: border-box; +} + +.avue-footer { + margin: 0 auto; + padding: 0 22px; + width: 1300px; + display: flex; + align-items: center; + justify-content: space-between; + .logo { + margin-left: -50px; + } + .copyright { + color: #666; + line-height: 1.5; + font-size: 12px; + } +} + +.avue-shade { + position: fixed; + display: none; + width: 100%; + height: 100%; + left: 0; + right: 0; + top: 0; + bottom: 0; + background-color: rgba(0, 0, 0, .3); + z-index: 1024; + &--show { + display: block; + } +} + +@media screen and (max-width: 992px) { + $width: 240px; + // ele的自适应 + .el-dialog, + .el-message-box { + width: 98% !important; + } + //登录页面 + .login-left { + display: none !important; + } + .login-logo { + padding-top: 30px !important; + margin-left: -30px; + } + .login-weaper{ + margin: 0 auto; + width: 96% !important; + } + .login-border { + border-radius: 5px; + padding: 40px; + margin: 0 auto; + float: none !important; + width: 100% !important; + } + .login-main { + width: 100% !important; + } + //主框架 + .avue-tags { + display: none; + } + .avue-left, + .avue-logo { + left: -$width; + } + .avue-main { + left: 0; + width: 100%; + } + .avue-header { + margin-bottom: 15px; + padding-left: 15px; + } + .top-bar__item { + display: none; + } + .avue--collapse { + .avue-left, + .avue-logo { + width: $width; + left: 0; + } + .avue-main { + left: $width; + width: 100%; + } + .avue-header { + padding: 0; + transform: translate3d(230px, 0, 0); + } + .avue-shade { + display: block; + } + } +} \ No newline at end of file diff --git a/src/styles/mixin.scss b/src/styles/mixin.scss new file mode 100644 index 0000000..0523edd --- /dev/null +++ b/src/styles/mixin.scss @@ -0,0 +1,73 @@ +@mixin clearfix { + &:after { + content: ""; + display: table; + clear: both; + } +} + +@mixin scrollBar { + ::-webkit-scrollbar-track-piece { + background-color: transparent; + } + ::-webkit-scrollbar { + width: 7px; + height: 7px; + background-color: transparent; + } + ::-webkit-scrollbar-thumb { + border-radius: 5px; + background-color: hsla(220, 4%, 58%, .3); + } +} + +@mixin radius($width, $size, $color) { + width: $width; + height: $width; + line-height: $width; + border-radius: $width; + text-align: center; + border-width: $size; + border-style: solid; + border-color: $color; +} + +@mixin relative { + position: relative; + width: 100%; + height: 100%; +} + +@mixin pct($pct) { + width: #{$pct}; + position: relative; + margin: 0 auto; +} + +@mixin triangle($width, $height, $color, $direction) { + $width: $width/2; + $color-border-style: $height solid $color; + $transparent-border-style: $width solid transparent; + height: 0; + width: 0; + @if $direction==up { + border-bottom: $color-border-style; + border-left: $transparent-border-style; + border-right: $transparent-border-style; + } + @else if $direction==right { + border-left: $color-border-style; + border-top: $transparent-border-style; + border-bottom: $transparent-border-style; + } + @else if $direction==down { + border-top: $color-border-style; + border-left: $transparent-border-style; + border-right: $transparent-border-style; + } + @else if $direction==left { + border-right: $color-border-style; + border-top: $transparent-border-style; + border-bottom: $transparent-border-style; + } +} \ No newline at end of file diff --git a/src/styles/normalize.scss b/src/styles/normalize.scss new file mode 100644 index 0000000..e51d268 --- /dev/null +++ b/src/styles/normalize.scss @@ -0,0 +1,502 @@ +/*! normalize.css v2.1.2 | MIT License | git.io/normalize */ +/* +/*! 我就是自己看看,然后翻译下下,让大家看看 */ + +/* ========================================================================== + HTML5 display definitions + + HTML5 新增元素定义 + + ========================================================================== */ + +/** + * Correct `block` display not defined in IE 8/9. + * + * 修正IE 8/9 中未定义的块级元素。 + */ + + article, + aside, + details, + figcaption, + figure, + footer, + header, + hgroup, + main, + nav, + section, + summary { + display: block; + } + + /** + * Correct `inline-block` display not defined in IE 8/9. + * + * 修正在 IE 8/9 中未定义的 'inline-block' 元素。 + */ + + audio, + canvas, + video { + display: inline-block; + } + + /** + * Prevent modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + * + * 阻止现在浏览器显示未定义 control 播放控件的 'audio' 声音元素。 + * 删除 IOS 5 设备中显示的多余的高度。 + */ + + audio:not([controls]) { + display: none; + height: 0; + } + + /** + * Address styling not present in IE 8/9. + * + * 处理 IE 8/9 中不存在的样式。 + */ + + [hidden] { + display: none; + } + + /* ========================================================================== + Base + + 基本设置 + ========================================================================== */ + + /** + * 1. Set default font family to sans-serif. + * 2. Prevent iOS text size adjust after orientation change, without disabling + * user zoom. + * + * 1. 设置默认字体类型为 sans-serif. + * 2. 当用户放大或缩小页面时不改变字体大小。 + */ + + html { + font-family: sans-serif; /* 1 */ + -ms-text-size-adjust: 100%; /* 2 */ + -webkit-text-size-adjust: 100%; /* 2 */ + } + + /** + * Remove default margin. + * + * 删除默认边距。 + */ + + body { + margin: 0; + } + + /* ========================================================================== + Links + + 链接 + ========================================================================== */ + + /** + * Address `outline` inconsistency between Chrome and other browsers. + * + * 处理 Chrome 与其它浏览器中关于 'outline' 的不一致性。 + */ + + a:focus { + outline: thin dotted; + } + + /** + * Improve readability when focused and also mouse hovered in all browsers. + * + * 为所有浏览器改善当激活或悬停在元素上时元素内容的可读性。 + */ + + a:active, + a:hover { + outline: 0; + } + + /* ========================================================================== + Typography + + 排版 + ========================================================================== */ + + /** + * Address variable `h1` font-size and margin within `section` and `article` + * contexts in Firefox 4+, Safari 5, and Chrome. + * + * 处理多变的 'h1' 字体大小及其在 Firefox 4+, Safari 5, 及 Chrome时浏览器中的 + * 'section' 与 'article' 元素中的边距。 + */ + + h1 { + font-size: 2em; + margin: 0.67em 0; + } + + /** + * Address styling not present in IE 8/9, Safari 5, and Chrome. + * + * 处理在 IE 8/9, Safari 5, 及 Chrome 没有的样式。 + */ + + abbr[title] { + border-bottom: 1px dotted; + } + + /** + * Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome. + * + * 处理 Firefox 4+, Safari 5, 及 Chrome 中默认的 'bolder' 样式为 'bold'. + */ + + b, + strong { + font-weight: bold; + } + + /** + * Address styling not present in Safari 5 and Chrome. + * + * 处理在 Safari 5 和 Chrome 没有的样式。 + */ + + dfn { + font-style: italic; + } + + /** + * Address differences between Firefox and other browsers. + * + * 处理 Firefox 与其它浏览器的差异。 + */ + + hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; + } + + /** + * Address styling not present in IE 8/9. + * + * 处理在 IE 8/9 中没有的样式。 + */ + + mark { + background: #ff0; + color: #000; + } + + /** + * Correct font family set oddly in Safari 5 and Chrome. + * + * 修正确 Safari 5 和 Chrome 中古怪的默认字体。 + */ + + code, + kbd, + pre, + samp { + font-family: monospace, serif; + font-size: 1em; + } + + /** + * Improve readability of pre-formatted text in all browsers. + * + * 为所有浏览器改善预格式化文本的可读性。 + */ + + pre { + white-space: pre-wrap; + } + + /** + * Set consistent quote types. + * + * 设置一致的引用格式。 + */ + + q { + quotes: "\201C" "\201D" "\2018" "\2019"; + } + + /** + * Address inconsistent and variable font size in all browsers. + * + * 处理所有浏览器中字体大小的不一致性[译者注:原文直译为:处理所有 + * 浏览器中的不一致和多变的字体大小]。 + */ + + small { + font-size: 80%; + } + + /** + * Prevent `sub` and `sup` affecting `line-height` in all browsers. + * + * 阻止所有浏览器中 'sub' 和 'sup' 元素影响 'line-height'. + * [译者注:就是不让上标与下标影响行高。] + */ + + sub, + sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; + } + + sup { + top: -0.5em; + } + + sub { + bottom: -0.25em; + } + + /* ========================================================================== + Embedded content + + 嵌入的内容 + ========================================================================== */ + + /** + * Remove border when inside `a` element in IE 8/9. + * + * 删除 IE 8/9 中当内容位于 'a' 中出现的边框。 + */ + + img { + border: 0; + } + + /** + * Correct overflow displayed oddly in IE 9. + * + * 修正 IE 9 中显示古怪的溢出内容。 + */ + + svg:not(:root) { + overflow: hidden; + } + + /* ========================================================================== + Figures + + Figure 图像/图表/代码等 + ========================================================================== */ + + /** + * Address margin not present in IE 8/9 and Safari 5. + * + * 处理在 IE 8/9 和 Safari 5 没有的边距。 + */ + + figure { + margin: 0; + } + + /* ========================================================================== + Forms + ========================================================================== */ + + /** + * Define consistent border, margin, and padding. + * + * 定义一致的边框、外边距及内边距。 + */ + + fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; + } + + /** + * 1. Correct `color` not being inherited in IE 8/9. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + * 1. 修正在 IE 8/9 中没有继承的 'color'. + * + * [译者注:说是修正颜色嘛,可下面没有关于颜色的呀,这也行?求大神解释!] + * 2. 去掉内边距,避免当用户清空表单组时认为出错了。 + */ + + legend { + border: 0; /* 1 */ + padding: 0; /* 2 */ + } + + /** + * 1. Correct font family not being inherited in all browsers. + * 2. Correct font size not being inherited in all browsers. + * 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome. + * + * 1. 修正所有浏览器中未被继承的字体类型。 + * 2. 修正所有浏览器中未被继承的字体大小。 + * 3. 处理 Firefox 4+, Safari 5, 及 Chrome 中默认设置不同的外边距。 + */ + + button, + input, + select, + textarea { + font-family: inherit; /* 1 */ + font-size: 100%; /* 2 */ + margin: 0; /* 3 */ + } + + /** + * Address Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + * + * 处理 Firefox 4+ 中的客户端样式表里使用 '!important' 设置的 'line-height'. + */ + + button, + input { + line-height: normal; + } + + /** + * Address inconsistent `text-transform` inheritance for `button` and `select`. + * All other form control elements do not inherit `text-transform` values. + * Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+. + * Correct `select` style inheritance in Firefox 4+ and Opera. + * + * 处理 'button' 和 'select' 的 'text-transform' 继承的不一致性。 + * 所有其它表单控件元素不继承 'text-transform' 的值。 + * 修正 Chrome, Safari 5+, 及 IE 8+ 中 'button' 的继承样式。 + * 修正 Firefox 4+ 和 Opera 中 'select' 的继承样式。 + */ + + button, + select { + text-transform: none; + } + + /** + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Correct inability to style clickable `input` types in iOS. + * 3. Improve usability and consistency of cursor style between image-type + * `input` and others. + * + * 1. 避免 Android 4.0.* 中 WebKit 的一个bug, 防止 'audio' 与 'video' 的播放控件失效。 + * 2. 修正 iOS 中不可点击的 'input' 样式。 + * 3. 改善图片类型的 'input' 等光标样式的可用性与一致性。 + */ + + button, + html input[type="button"], /* 1 */ + input[type="reset"], + input[type="submit"] { + -webkit-appearance: button; /* 2 */ + cursor: pointer; /* 3 */ + } + + /** + * Re-set default cursor for disabled elements. + * + * 重置不可用元素的默认光标样式。 + */ + + button[disabled], + html input[disabled] { + cursor: default; + } + + /** + * 1. Address box sizing set to `content-box` in IE 8/9. + * 2. Remove excess padding in IE 8/9. + * + * 1. 处理 IE 8/9 中设置为 'content-box' 的盒子模型。 + * 2. 删除 IE 8/9 中多余的内边距。 + */ + + input[type="checkbox"], + input[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ + } + + /** + * 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome. + * 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome + * (include `-moz` to future-proof). + * + * 1. 处理 Safari 5 和 Chrome 中默认设置为 'appearance' 的 'searchfield'. + * 2. 处理 Safari 5 和 Chrome 中默认设置为 'box-sizing' 的 'border-box' + * (包括不会过时的 '-moz'). + */ + + input[type="search"] { + -webkit-appearance: textfield; /* 1 */ + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; /* 2 */ + box-sizing: content-box; + } + + /** + * Remove inner padding and search cancel button in Safari 5 and Chrome + * on OS X. + * + * 删除 Safari 5 和 OS X 上的 Chrome 中的输入框上的内边距和搜索取消按钮。 + */ + + input[type="search"]::-webkit-search-cancel-button, + input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; + } + + /** + * Remove inner padding and border in Firefox 4+. + * + * 删除 Firefox 4+ button 与 input 上的内边距。 + */ + + button::-moz-focus-inner, + input::-moz-focus-inner { + border: 0; + padding: 0; + } + + /** + * 1. Remove default vertical scrollbar in IE 8/9. + * 2. Improve readability and alignment in all browsers. + * + * 1. 删除 IE8/9 中默认的垂直滚动条。 + * 2. 改善所有浏览器中的可读性并使文本垂直对齐。 + */ + + textarea { + overflow: auto; /* 1 */ + vertical-align: top; /* 2 */ + } + + /* ========================================================================== + Tables + + 表格 + ========================================================================== */ + + /** + * Remove most spacing between table cells. + * + * 删除表格里单元格间的间距。 + */ + + table { + border-collapse: collapse; + border-spacing: 0; + } + \ No newline at end of file diff --git a/src/styles/sidebar.scss b/src/styles/sidebar.scss new file mode 100644 index 0000000..96edd24 --- /dev/null +++ b/src/styles/sidebar.scss @@ -0,0 +1,90 @@ + + +.el-menu--popup{ + .el-menu-item{ + background-color: #20222a; + i{ + margin-right: 5px; + } + i,span{ + color:hsla(0,0%,100%,.7); + } + &:hover{ + i,span{ + color:#fff; + } + } + &.is-active { + background-color: rgba(0,0,0,.8); + &:before { + content: ''; + top: 0; + left: 0; + bottom: 0; + width: 4px; + background: #409eff; + position: absolute; + } + i,span{ + color:#fff; + } + } + } + +} +.avue-sidebar { + user-select: none; + position: relative; + padding-top: 60px; + height: 100%; + position: relative; + background-color: #20222a; + transition: width .2s; + box-sizing: border-box; + box-shadow: 2px 0 6px rgba(0,21,41,.35); + &--tip{ + width:90%; + height: 140px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 5px; + position: absolute; + top:5px; + left:5%; + color:#ccc; + z-index: 2; + text-align: center; + font-size: 14px; + background-color: rgba(0,0,0,.4); + } + .el-menu-item,.el-submenu__title{ + i{ + margin-right: 5px; + } + i,span{ + color:hsla(0,0%,100%,.7); + } + &:hover{ + background: transparent; + i,span{ + color:#fff; + } + } + &.is-active { + &:before { + content: ''; + top: 0; + left: 0; + bottom: 0; + width: 4px; + background: #409eff; + position: absolute; + } + background-color: rgba(0,0,0,.8); + i,span{ + color:#fff; + } + } + } +} \ No newline at end of file diff --git a/src/styles/tags.scss b/src/styles/tags.scss new file mode 100644 index 0000000..283be5e --- /dev/null +++ b/src/styles/tags.scss @@ -0,0 +1,92 @@ + + +.avue-tags { + user-select: none; + position: relative; + padding: 0 10px; + margin-bottom: 10px; + box-sizing: border-box; + overflow: hidden; + border-top: 1px solid #f6f6f6; + background-color: #fff; + box-shadow: 0 1px 2px 0 rgba(0, 0, 0, .05); + .el-tabs--card>.el-tabs__header { + margin: 0; + } + .el-tabs--card>.el-tabs__header .el-tabs__nav, + .el-tabs--card>.el-tabs__header .el-tabs__item, + .el-tabs--card>.el-tabs__header { + border: none; + } + .el-tabs--card>.el-tabs__header .el-tabs__item:first-child { + border-left-width: 1px + } + .el-tabs--card>.el-tabs__header .el-tabs__item { + margin: 0 3px; + height: 40px; + line-height:40px; + font-size: 13px; + font-weight: normal; + color: #ccc; + &.is-active { + color: #409EFF; + border-bottom: 3px solid #409EFF; + } + } + .el-tabs__nav-prev, + .el-tabs__nav-next { + width: 20px; + line-height: 34px; + font-size: 18x; + text-align: center; + } + &__box { + position: relative; + box-sizing: border-box; + padding-right: 106px; + width: 100%; + &--close { + .el-tabs__item { + &:first-child { + padding: 0 20px !important; + .el-icon-close { + display: none; + } + } + } + } + } + &__contentmenu{ + position: fixed; + width:120px; + background-color: #fff; + z-index:1024; + border-radius: 5px; + box-shadow: 1px 2px 10px #ccc; + .item{ + cursor: pointer; + font-size: 14px; + padding: 8px 20px 8px 15px; + color: #606266; + &:first-child{ + border-top-left-radius: 5px; + border-top-right-radius: 5px; + } + &:last-child{ + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; + } + &:hover{ + background-color: #409EFF; + color:#fff; + } + } + } + &__menu { + position: absolute !important; + top: 3px; + right: 0; + padding: 1px 0 0 15px; + box-sizing: border-box; + } +} \ No newline at end of file diff --git a/src/styles/theme/d2.scss b/src/styles/theme/d2.scss new file mode 100644 index 0000000..479fc0f --- /dev/null +++ b/src/styles/theme/d2.scss @@ -0,0 +1,57 @@ +.theme-d2 { + .avue-logo{ + color: #409EFF; + background-color: #ebf1f6; + box-shadow: none; + .avue-logo_title{ + font-size: 22px; + font-weight: 400; + } + } + .avue-top{ + background-color: #ebf1f6; + box-shadow: none; + } + .avue-main{ + padding: 0 5px; + } + .avue-tags{ + margin-left: 6px; + padding: 0; + border: 1px solid #e4e7ed; + border-radius: 3px; + background-color: #ebf1f6; + box-shadow: none; + .el-tabs__item{ + border-left: 1px solid #cfd7e5 !important; + margin: 0 !important; + background-color: rgba(0,0,0,.03) !important; + color: #606266 !important; + font-size: 14px !important; + font-weight: 500 !important; + &:first-child{ + border-left: none !important; + } + } + .is-active{ + border-bottom:1px solid #fff !important; + background-color: #fff !important; + color: #409EFF !important; + } + } + .avue-sidebar{ + background-color: #ebf1f6; + box-shadow: none; + .el-menu-item,.el-submenu__title{ + i,span{ + color:#606266 + } + &:hover,&.is-active{ + background: hsla(0,0%,100%,.5); + i,span{ + color: #409EFF; + } + } + } + } +} \ No newline at end of file diff --git a/src/styles/theme/hey.scss b/src/styles/theme/hey.scss new file mode 100644 index 0000000..cc4a4fe --- /dev/null +++ b/src/styles/theme/hey.scss @@ -0,0 +1,45 @@ +.theme-hey{ + .avue-sidebar{ + background-color: #fff; + box-shadow: 0 1px 4px rgba(0,21,41,.08); + .el-menu-item,.el-submenu__title{ + i,span{ + color: rgba(49,58,70,.8); + } + &:hover{ + background: transparent; + i,span{ + color:#409eff; + } + } + &.is-active { + &:before { + left:auto; + right: 0 ; + } + background-color: #f0f6ff; + i,span{ + color:#409eff; + } + } + } + } + .avue-logo{ + background-color: #fff; + box-shadow: none; + .avue-logo_title{ + color:#409eff; + font-size: 24px; + } + } + .avue-tags{ + background: #f3f6f8; + .el-tabs__item{ + color: rgba(0,0,0,.65) !important; + } + .is-active{ + background-color: #fff; + border-bottom: none !important; + } + } +} \ No newline at end of file diff --git a/src/styles/theme/index.scss b/src/styles/theme/index.scss new file mode 100644 index 0000000..4356e78 --- /dev/null +++ b/src/styles/theme/index.scss @@ -0,0 +1,15 @@ +// 白色主题 +@import './white.scss'; + +// 炫酷主题 +@import './star.scss'; + + +// d2主题 +@import './d2.scss'; + +//iview +@import './iview.scss'; + +//heyui +@import './hey.scss'; diff --git a/src/styles/theme/iview.scss b/src/styles/theme/iview.scss new file mode 100644 index 0000000..1c6a844 --- /dev/null +++ b/src/styles/theme/iview.scss @@ -0,0 +1,79 @@ +.theme-iview { + .avue-logo{ + background: #001529; + box-shadow: none; + text-align: center; + .avue-logo_title{ + div{ + border-top-left-radius: 5px; + border-top-right-radius: 5px; + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; + font-size: 22px; + color:#fff; + font-weight: 500; + margin: 10px auto; + width: 180px; + height: 45px; + background-color: #409EFF; + } + } + } + .avue-tags{ + padding: 3px 5px 5px 0; + background: #f0f0f0; + box-shadow: inset 0 0 3px 2px hsla(0,0%,39.2%,.1); + .is-active{ + &:before{ + background: #409EFF !important; + } + } + .el-tabs__item{ + padding: 0 15px !important; + position: relative; + height: 32px !important; + line-height:32px !important; + border: 1px solid #e8eaec!important; + color: #515a6e!important; + background: #fff!important; + border-radius: 3px; + &:before{ + content:''; + display: inline-block; + width: 12px; + height: 12px; + margin-right:10px; + border-radius: 50%; + background: #e8eaec; + } + } + } + + .avue-sidebar{ + background: #001529; + .el-menu-item{ + &.is-active { + background-color: #000c17; + &:before { + display: none; + } + i,span{ + color:#409EFF; + } + } + } + .el-submenu{ + .el-menu-item{ + &.is-active { + background-color: #409EFF; + &:before { + display: none; + } + i,span{ + color:#fff; + } + } + } + } + } +} \ No newline at end of file diff --git a/src/styles/theme/star.scss b/src/styles/theme/star.scss new file mode 100644 index 0000000..b593fb2 --- /dev/null +++ b/src/styles/theme/star.scss @@ -0,0 +1,92 @@ +.theme-star { + .avue-contail { + background-image: url("/img/bg/star-squashed.jpg"); + background-size: 100% 100%; + } + .avue-logo{ + color: #fff; + } + .avue-header, + .avue-logo, + .tags-container { + background-color: transparent; + } + .el-card,.error-page { + opacity: .9; + } + .avue-tabs { + padding: 0 20px ; + } + .avue-tags{ + background-color: transparent; + border-top: none; + } + .avue-top{ + .avue-breadcrumb{ + color:#fff; + } + .el-menu-item{ + i,span{ + color:#fff; + } + &.is-active{ + background-color: rgba(0,0,0,.4) + } + } + .el-dropdown{ + color:#fff; + } + } + .avue-sidebar{ + box-shadow: 2px 0 6px rgba(0, 21, 41, 0.15); + background-color:transparent; + .el-menu-item,.el-submenu__title{ + i,span{ + color:#fff + } + &:hover{ + background: transparent; + i,span{ + color:#409EFF; + } + } + &.is-active { + background-color: rgba(0,0,0,.4); + i,span{ + color:#fff; + } + } + } + } + + .top-search { + .el-input__inner{ + color: #333; + } + input::-webkit-input-placeholder, + textarea::-webkit-input-placeholder { + /* WebKit browsers */ + color: #fff; + } + input:-moz-placeholder, + textarea:-moz-placeholder { + /* Mozilla Firefox 4 to 18 */ + color: #fff; + } + input::-moz-placeholder, + textarea::-moz-placeholder { + /* Mozilla Firefox 19+ */ + color: #fff; + } + input:-ms-input-placeholder, + textarea:-ms-input-placeholder { + /* Internet Explorer 10+ */ + color: #fff; + } + } + .top-bar__item { + i { + color: #fff; + } + } +} \ No newline at end of file diff --git a/src/styles/theme/white.scss b/src/styles/theme/white.scss new file mode 100644 index 0000000..ed81bc2 --- /dev/null +++ b/src/styles/theme/white.scss @@ -0,0 +1,120 @@ +.theme-white { + .el-menu--popup{ + .el-menu-item{ + background-color: #fff; + i,span{ + color:#666; + } + &:hover{ + i,span{ + color:#333; + } + } + &.is-active { + background-color: #409EFF; + &:before { + content: ''; + top: 0; + left: 0; + bottom: 0; + width: 4px; + background: #409eff; + position: absolute; + } + i,span{ + color:#fff; + } + } + } + } + .avue-header, + .avue-logo, + .tags-container { + background-color: #409EFF; + } + .avue-sidebar--tip{ + background-color:transparent; + color:#333; + } + .el-dropdown{ + color:#fff; + } + .avue-logo_title{ + font-weight: 400; + color:#fff; + } + .logo_title, + .avue-breadcrumb + { + color: #fff ; + i { + color: #fff; + } + } + .avue-top{ + .el-menu-item { + i, + span { + color: #fff ; + } + &:hover { + i, + span { + color: #fff ; + } + } + } + } + .avue-sidebar{ + box-shadow: 2px 0 6px rgba(0, 21, 41, 0.15); + background-color: #fff; + padding-top: 70px; + .el-menu-item,.el-submenu__title{ + i,span{ + color:#666 + } + &:hover{ + background: transparent; + i,span{ + color:#333; + } + } + &.is-active { + background-color: #409EFF; + i,span{ + color:#fff; + } + } + } + } + .top-search { + .el-input__inner{ + color: #333; + } + input::-webkit-input-placeholder, + textarea::-webkit-input-placeholder { + /* WebKit browsers */ + color: #fff; + } + input:-moz-placeholder, + textarea:-moz-placeholder { + /* Mozilla Firefox 4 to 18 */ + color: #fff; + } + input::-moz-placeholder, + textarea::-moz-placeholder { + /* Mozilla Firefox 19+ */ + color: #fff; + } + input:-ms-input-placeholder, + textarea:-ms-input-placeholder { + /* Internet Explorer 10+ */ + color: #fff; + } + } + .top-bar__item { + i { + color: #fff; + } + } +} \ No newline at end of file diff --git a/src/styles/top.scss b/src/styles/top.scss new file mode 100644 index 0000000..a39bb81 --- /dev/null +++ b/src/styles/top.scss @@ -0,0 +1,102 @@ +.avue-top { + padding: 0 20px; + position: relative; + box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.15); + color: rgba(0, 0, 0, .65); + font-size: 28px; + height: 64px; + box-sizing: border-box; + white-space: nowrap; + .el-menu-item{ + i,span{ + font-size: 13px; + } + } +} +.avue-breadcrumb { + height: 100%; + i{ + font-size: 30px !important; + } + &--active { + transform:rotate(90deg); + } +} + +.top-menu { + box-sizing: border-box; + .el-menu-item { + padding: 0 10px; + border:none !important; + } +} + +.top-search { + line-height: 64px; + position: absolute !important; + left: 20px; + top:0; + width: 400px !important; + .el-input__inner { + font-size: 13px; + border: none; + background-color: transparent; + } +} + +.top-bar__img { + margin: 0 8px 0 5px; + padding: 2px; + width: 30px; + height: 30px; + border-radius: 100%; + box-sizing: border-box; + border: 1px solid #eee; + vertical-align: middle; +} + +.top-bar__left, +.top-bar__right { + height: 64px; + position: absolute; + top: 0; + i{ + line-height: 64px; + } +} + +.top-bar__left { + left: 20px; +} + +.top-bar__right { + right: 20px; + display: flex; + align-items: center; +} + +.top-bar__item { + position: relative; + display: inline-block; + height: 64px; + margin:0 10px; + font-size: 16px; + &--show { + display: inline-block !important; + } + .el-badge__content.is-fixed{ + top:12px; + right: 5px; + } +} + +.top-bar__title { + height: 100%; + padding:0 40px; + box-sizing: border-box; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-size: inherit; + font-weight: 400; +} diff --git a/src/styles/variables.scss b/src/styles/variables.scss new file mode 100644 index 0000000..219e4a7 --- /dev/null +++ b/src/styles/variables.scss @@ -0,0 +1,2 @@ +//main +$mainBg: #409eff; diff --git a/src/util/auth.js b/src/util/auth.js new file mode 100644 index 0000000..598499f --- /dev/null +++ b/src/util/auth.js @@ -0,0 +1,15 @@ +import Cookies from 'js-cookie' +const TokenKey = 'x-access-token' +const inFifteenMinutes = new Date(new Date().getTime() + 120 * 60 * 1000); + +export function getToken() { + return Cookies.get(TokenKey) +} + +export function setToken(token) { + return Cookies.set(TokenKey, token, { expires: inFifteenMinutes }) +} + +export function removeToken() { + return Cookies.remove(TokenKey) +} \ No newline at end of file diff --git a/src/util/date.js b/src/util/date.js new file mode 100644 index 0000000..80ff1a1 --- /dev/null +++ b/src/util/date.js @@ -0,0 +1,50 @@ +export const calcDate = (date1, date2) => { + var date3 = date2 - date1; + + var days = Math.floor(date3 / (24 * 3600 * 1000)) + + var leave1 = date3 % (24 * 3600 * 1000) //计算天数后剩余的毫秒数 + var hours = Math.floor(leave1 / (3600 * 1000)) + + var leave2 = leave1 % (3600 * 1000) //计算小时数后剩余的毫秒数 + var minutes = Math.floor(leave2 / (60 * 1000)) + + var leave3 = leave2 % (60 * 1000) //计算分钟数后剩余的毫秒数 + var seconds = Math.round(date3 / 1000) + return { + leave1, + leave2, + leave3, + days: days, + hours: hours, + minutes: minutes, + seconds: seconds, + } +} +/** + * 日期格式化 + */ +export function dateFormat(date) { + let format = 'yyyy-MM-dd hh:mm:ss'; + if (date != 'Invalid Date') { + var o = { + "M+": date.getMonth() + 1, //month + "d+": date.getDate(), //day + "h+": date.getHours(), //hour + "m+": date.getMinutes(), //minute + "s+": date.getSeconds(), //second + "q+": Math.floor((date.getMonth() + 3) / 3), //quarter + "S": date.getMilliseconds() //millisecond + } + if (/(y+)/.test(format)) format = format.replace(RegExp.$1, + (date.getFullYear() + "").substr(4 - RegExp.$1.length)); + for (var k in o) + if (new RegExp("(" + k + ")").test(format)) + format = format.replace(RegExp.$1, + RegExp.$1.length == 1 ? o[k] : + ("00" + o[k]).substr(("" + o[k]).length)); + return format; + } + return ''; + +} \ No newline at end of file diff --git a/src/util/store.js b/src/util/store.js new file mode 100644 index 0000000..6388ec2 --- /dev/null +++ b/src/util/store.js @@ -0,0 +1,121 @@ +import { + validatenull +} from '@/util/validate'; +import website from '@/config/website' + +const keyName = website.key + '-'; +/** + * 存储localStorage + */ +export const setStore = (params = {}) => { + let { + name, + content, + type, + } = params; + name = keyName + name + let obj = { + dataType: typeof (content), + content: content, + type: type, + datetime: new Date().getTime() + } + if (type) window.sessionStorage.setItem(name, JSON.stringify(obj)); + else window.localStorage.setItem(name, JSON.stringify(obj)); +} +/** + * 获取localStorage + */ + +export const getStore = (params = {}) => { + let { + name, + debug + } = params; + name = keyName + name + let obj = {}, + content; + obj = window.sessionStorage.getItem(name); + if (validatenull(obj)) obj = window.localStorage.getItem(name); + if (validatenull(obj)) return; + try { + obj = JSON.parse(obj); + } catch{ + return obj; + } + if (debug) { + return obj; + } + if (obj.dataType == 'string') { + content = obj.content; + } else if (obj.dataType == 'number') { + content = Number(obj.content); + } else if (obj.dataType == 'boolean') { + content = eval(obj.content); + } else if (obj.dataType == 'object') { + content = obj.content; + } + return content; +} +/** + * 删除localStorage + */ +export const removeStore = (params = {}) => { + let { + name, + type + } = params; + name = keyName + name + if (type) { + window.sessionStorage.removeItem(name); + } else { + window.localStorage.removeItem(name); + } + +} + +/** + * 获取全部localStorage + */ +export const getAllStore = (params = {}) => { + let list = []; + let { + type + } = params; + if (type) { + for (let i = 0; i <= window.sessionStorage.length; i++) { + list.push({ + name: window.sessionStorage.key(i), + content: getStore({ + name: window.sessionStorage.key(i), + type: 'session' + }) + }) + } + } else { + for (let i = 0; i <= window.localStorage.length; i++) { + list.push({ + name: window.localStorage.key(i), + content: getStore({ + name: window.localStorage.key(i), + }) + }) + + } + } + return list; + +} + +/** + * 清空全部localStorage + */ +export const clearStore = (params = {}) => { + let { type } = params; + if (type) { + window.sessionStorage.clear(); + } else { + window.localStorage.clear() + } + +} \ No newline at end of file diff --git a/src/util/util.js b/src/util/util.js new file mode 100644 index 0000000..3bb9172 --- /dev/null +++ b/src/util/util.js @@ -0,0 +1,288 @@ +import { validatenull } from './validate' +//表单序列化 +export const serialize = data => { + let list = []; + Object.keys(data).forEach(ele => { + list.push(`${ele}=${data[ele]}`) + }) + return list.join('&'); +}; +export const getObjType = obj => { + var toString = Object.prototype.toString; + var map = { + '[object Boolean]': 'boolean', + '[object Number]': 'number', + '[object String]': 'string', + '[object Function]': 'function', + '[object Array]': 'array', + '[object Date]': 'date', + '[object RegExp]': 'regExp', + '[object Undefined]': 'undefined', + '[object Null]': 'null', + '[object Object]': 'object' + }; + if (obj instanceof Element) { + return 'element'; + } + return map[toString.call(obj)]; +}; +/** + * 对象深拷贝 + */ +export const deepClone = data => { + var type = getObjType(data); + var obj; + if (type === 'array') { + obj = []; + } else if (type === 'object') { + obj = {}; + } else { + //不再具有下一层次 + return data; + } + if (type === 'array') { + for (var i = 0, len = data.length; i < len; i++) { + obj.push(deepClone(data[i])); + } + } else if (type === 'object') { + for (var key in data) { + obj[key] = deepClone(data[key]); + } + } + return obj; +}; +/** + * 设置灰度模式 + */ +export const toggleGrayMode = (status) => { + if (status) { + document.body.className = document.body.className + ' grayMode'; + } else { + document.body.className = document.body.className.replace(' grayMode', ''); + } +}; +/** + * 设置主题 + */ +export const setTheme = (name) => { + document.body.className = name; +} + +/** + * 加密处理 + */ +export const encryption = (params) => { + let { + data, + type, + param, + key + } = params; + let result = JSON.parse(JSON.stringify(data)); + if (type == 'Base64') { + param.forEach(ele => { + result[ele] = btoa(result[ele]); + }) + } else if (type == 'Aes') { + param.forEach(ele => { + result[ele] = window.CryptoJS.AES.encrypt(result[ele], key).toString(); + }) + + } + return result; +}; + + +/** + * 浏览器判断是否全屏 + */ +export const fullscreenToggel = () => { + if (fullscreenEnable()) { + exitFullScreen(); + } else { + reqFullScreen(); + } +}; +/** + * esc监听全屏 + */ +export const listenfullscreen = (callback) => { + function listen() { + callback() + } + document.addEventListener("fullscreenchange", function () { + listen(); + }); + document.addEventListener("mozfullscreenchange", function () { + listen(); + }); + document.addEventListener("webkitfullscreenchange", function () { + listen(); + }); + document.addEventListener("msfullscreenchange", function () { + listen(); + }); +}; +/** + * 浏览器判断是否全屏 + */ +export const fullscreenEnable = () => { + var isFullscreen = document.isFullScreen || document.mozIsFullScreen || document.webkitIsFullScreen + return isFullscreen; +} + +/** + * 浏览器全屏 + */ +export const reqFullScreen = () => { + if (document.documentElement.requestFullScreen) { + document.documentElement.requestFullScreen(); + } else if (document.documentElement.webkitRequestFullScreen) { + document.documentElement.webkitRequestFullScreen(); + } else if (document.documentElement.mozRequestFullScreen) { + document.documentElement.mozRequestFullScreen(); + } +}; +/** + * 浏览器退出全屏 + */ +export const exitFullScreen = () => { + if (document.documentElement.requestFullScreen) { + document.exitFullScreen(); + } else if (document.documentElement.webkitRequestFullScreen) { + document.webkitCancelFullScreen(); + } else if (document.documentElement.mozRequestFullScreen) { + document.mozCancelFullScreen(); + } +}; +/** + * 递归寻找子类的父类 + */ + +export const findParent = (menu, id) => { + for (let i = 0; i < menu.length; i++) { + if (menu[i].children.length != 0) { + for (let j = 0; j < menu[i].children.length; j++) { + if (menu[i].children[j].id == id) { + return menu[i]; + } else { + if (menu[i].children[j].children.length != 0) { + return findParent(menu[i].children[j].children, id); + } + } + } + } + } +}; +/** + * 判断2个对象属性和值是否相等 + */ + +/** + * 动态插入css + */ + +export const loadStyle = url => { + const link = document.createElement('link'); + link.type = 'text/css'; + link.rel = 'stylesheet'; + link.href = url; + const head = document.getElementsByTagName('head')[0]; + head.appendChild(link); +}; +/** + * 判断路由是否相等 + */ +export const diff = (obj1, obj2) => { + delete obj1.close; + var o1 = obj1 instanceof Object; + var o2 = obj2 instanceof Object; + if (!o1 || !o2) { /* 判断不是对象 */ + return obj1 === obj2; + } + + if (Object.keys(obj1).length !== Object.keys(obj2).length) { + return false; + //Object.keys() 返回一个由对象的自身可枚举属性(key值)组成的数组,例如:数组返回下表:let arr = ["a", "b", "c"];console.log(Object.keys(arr))->0,1,2; + } + + for (var attr in obj1) { + var t1 = obj1[attr] instanceof Object; + var t2 = obj2[attr] instanceof Object; + if (t1 && t2) { + return diff(obj1[attr], obj2[attr]); + } else if (obj1[attr] !== obj2[attr]) { + return false; + } + } + return true; +} +/** + * 根据字典的value显示label + */ +export const findByvalue = (dic, value) => { + let result = ''; + if (validatenull(dic)) return value; + if (typeof (value) == 'string' || typeof (value) == 'number' || typeof (value) == 'boolean') { + let index = 0; + index = findArray(dic, value); + if (index != -1) { + result = dic[index].label; + } else { + result = value; + } + } else if (value instanceof Array) { + result = []; + let index = 0; + value.forEach(ele => { + index = findArray(dic, ele); + if (index != -1) { + result.push(dic[index].label); + } else { + result.push(value); + } + }); + result = result.toString(); + } + return result; +}; +/** + * 根据字典的value查找对应的index + */ +export const findArray = (dic, value) => { + for (let i = 0; i < dic.length; i++) { + if (dic[i].value == value) { + return i; + } + } + return -1; +}; +/** + * 生成随机len位数字 + */ +export const randomLenNum = (len, date) => { + let random = ''; + random = Math.ceil(Math.random() * 100000000000000).toString().substr(0, len ? len : 4); + if (date) random = random + Date.now(); + return random; +}; +/** + * 打开小窗口 + */ +export const openWindow = (url, title, w, h) => { + // Fixes dual-screen position Most browsers Firefox + const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left + const dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top + + const width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width + const height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height + + const left = ((width / 2) - (w / 2)) + dualScreenLeft + const top = ((height / 2) - (h / 2)) + dualScreenTop + const newWindow = window.open(url, title, 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=yes, copyhistory=no, width=' + w + ', height=' + h + ', top=' + top + ', left=' + left) + + // Puts focus on the newWindow + if (window.focus) { + newWindow.focus() + } +} \ No newline at end of file diff --git a/src/util/validate.js b/src/util/validate.js new file mode 100644 index 0000000..a774710 --- /dev/null +++ b/src/util/validate.js @@ -0,0 +1,253 @@ +/** + * Created by jiachenpan on 16/11/18. + */ + +export function isvalidUsername(str) { + const valid_map = ['admin', 'editor'] + return valid_map.indexOf(str.trim()) >= 0 +} + +/* 合法uri*/ +export function validateURL(textval) { + const urlregex = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/ + return urlregex.test(textval) +} +/** + * 邮箱 + * @param {*} s + */ +export function isEmail(s) { + return /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((.[a-zA-Z0-9_-]{2,3}){1,2})$/.test(s) +} + +/** + * 手机号码 + * @param {*} s + */ +export function isMobile(s) { + return /^1[0-9]{10}$/.test(s) +} + +/** + * 电话号码 + * @param {*} s + */ +export function isPhone(s) { + return /^([0-9]{3,4}-)?[0-9]{7,8}$/.test(s) +} + +/** + * URL地址 + * @param {*} s + */ +export function isURL(s) { + return /^http[s]?:\/\/.*/.test(s) +} + +/* 小写字母*/ +export function validateLowerCase(str) { + const reg = /^[a-z]+$/ + return reg.test(str) +} + +/* 大写字母*/ +export function validateUpperCase(str) { + const reg = /^[A-Z]+$/ + return reg.test(str) +} + +/* 大小写字母*/ +export function validatAlphabets(str) { + const reg = /^[A-Za-z]+$/ + return reg.test(str) +} +/*验证pad还是pc*/ +export const vaildatePc = function() { + const userAgentInfo = navigator.userAgent; + const Agents = ["Android", "iPhone", + "SymbianOS", "Windows Phone", + "iPad", "iPod" + ]; + let flag = true; + for (var v = 0; v < Agents.length; v++) { + if (userAgentInfo.indexOf(Agents[v]) > 0) { + flag = false; + break; + } + } + return flag; + } + /** + * validate email + * @param email + * @returns {boolean} + */ +export function validateEmail(email) { + const re = /^(([^<>()\\[\]\\.,;:\s@"]+(\.[^<>()\\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ + return re.test(email) +} + +/** + * 判断身份证号码 + */ +export function cardid(code) { + let list = []; + let result = true; + let msg = ''; + var city = { + 11: "北京", + 12: "天津", + 13: "河北", + 14: "山西", + 15: "内蒙古", + 21: "辽宁", + 22: "吉林", + 23: "黑龙江 ", + 31: "上海", + 32: "江苏", + 33: "浙江", + 34: "安徽", + 35: "福建", + 36: "江西", + 37: "山东", + 41: "河南", + 42: "湖北 ", + 43: "湖南", + 44: "广东", + 45: "广西", + 46: "海南", + 50: "重庆", + 51: "四川", + 52: "贵州", + 53: "云南", + 54: "西藏 ", + 61: "陕西", + 62: "甘肃", + 63: "青海", + 64: "宁夏", + 65: "新疆", + 71: "台湾", + 81: "香港", + 82: "澳门", + 91: "国外 " + }; + if (!validatenull(code)) { + if (code.length == 18) { + if (!code || !/(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(code)) { + msg = "证件号码格式错误"; + } else if (!city[code.substr(0, 2)]) { + msg = "地址编码错误"; + } else { + //18位身份证需要验证最后一位校验位 + code = code.split(''); + //∑(ai×Wi)(mod 11) + //加权因子 + var factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]; + //校验位 + var parity = [1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2, 'x']; + var sum = 0; + var ai = 0; + var wi = 0; + for (var i = 0; i < 17; i++) { + ai = code[i]; + wi = factor[i]; + sum += ai * wi; + } + if (parity[sum % 11] != code[17]) { + msg = "证件号码校验位错误"; + } else { + result = false; + } + + } + } else { + msg = "证件号码长度不为18位"; + } + + } else { + msg = "证件号码不能为空"; + } + list.push(result); + list.push(msg); + return list; +} +/** + * 判断手机号码是否正确 + */ +export function isvalidatemobile(phone) { + let list = []; + let result = true; + let msg = ''; + var isPhone = /^0\d{2,3}-?\d{7,8}$/; + //增加134 减少|1349[0-9]{7},增加181,增加145,增加17[678] + if (!validatenull(phone)) { + if (phone.length == 11) { + if (isPhone.test(phone)) { + msg = '手机号码格式不正确'; + } else { + result = false; + } + } else { + msg = '手机号码长度不为11位'; + } + } else { + msg = '手机号码不能为空'; + } + list.push(result); + list.push(msg); + return list; +} +/** + * 判断姓名是否正确 + */ +export function validatename(name) { + var regName = /^[\u4e00-\u9fa5]{2,4}$/; + if (!regName.test(name)) return false; + return true; +} +/** + * 判断是否为整数 + */ +export function validatenum(num, type) { + let regName = /[^\d.]/g; + if (type == 1) { + if (!regName.test(num)) return false; + } else if (type == 2) { + regName = /[^\d]/g; + if (!regName.test(num)) return false; + } + return true; +} +/** + * 判断是否为小数 + */ +export function validatenumord(num, type) { + let regName = /[^\d.]/g; + if (type == 1) { + if (!regName.test(num)) return false; + } else if (type == 2) { + regName = /[^\d.]/g; + if (!regName.test(num)) return false; + } + return true; +} +/** + * 判断是否为空 + */ +export function validatenull(val) { + if (typeof val == 'boolean') { + return false; + } + if (typeof val == 'number') { + return false; + } + if (val instanceof Array) { + if (val.length == 0) return true; + } else if (val instanceof Object) { + if (JSON.stringify(val) === '{}') return true; + } else { + if (val == 'null' || val == null || val == 'undefined' || val == undefined || val == '') return true; + return false; + } + return false; +} \ No newline at end of file