Former-commit-id: f4d2097b236a5c20e84ff57c2d4e9e62a3f0fefb
This commit is contained in:
liyang
2018-09-20 14:33:38 +08:00
parent e0ce56c7e9
commit 9839f47d20
170 changed files with 36620 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
> 1%
last 2 versions
not ie <= 8
+7
View File
@@ -0,0 +1,7 @@
# 所有环境默认
# 页面 title 前缀
VUE_APP_TITLE=D2Admin
# 网络请求公用地址
VUE_APP_API=/api/
+4
View File
@@ -0,0 +1,4 @@
# 开发环境
# 页面 title 前缀
VUE_APP_TITLE=D2Admin Dev
+10
View File
@@ -0,0 +1,10 @@
# travis
# 页面 title 前缀
VUE_APP_TITLE=D2Admin Preview
# 页面 指定使用的模式
NODE_ENV=production
# 标记当前编译版本
VUE_APP_TRAVIS=TRUE
+11
View File
@@ -0,0 +1,11 @@
# 忽略目录
build/
tests/
node_modules/
# node 覆盖率文件
coverage/
# 忽略文件
**/*-min.js
**/*.min.js
+17
View File
@@ -0,0 +1,17 @@
module.exports = {
root: true,
env: {
node: true
},
'extends': [
'plugin:vue/essential',
'@vue/standard'
],
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
},
parserOptions: {
parser: 'babel-eslint'
}
}
+17
View File
@@ -0,0 +1,17 @@
.DS_Store
node_modules
/dist
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw*
+5
View File
@@ -0,0 +1,5 @@
module.exports = {
plugins: {
autoprefixer: {}
}
}
+21
View File
@@ -0,0 +1,21 @@
language: node_js
node_js: stable
cache:
directories:
- "node_modules"
branches:
only:
- master
script:
- npm run build:travis
deploy:
provider: pages
local-dir: dist
skip-cleanup: true
github-token: $GITHUB_TOKEN
keep-history: true
on:
branch: master
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 李杨
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+5
View File
@@ -0,0 +1,5 @@
[![Build Status](https://www.travis-ci.org/d2-projects/d2-admin-start-kit.svg?branch=master)](https://www.travis-ci.org/d2-projects/d2-admin-start-kit)
[D2Admin](https://github.com/d2-projects/d2-admin) 简化版起始模板,删除所有完整版中的示例代码,保留所有核心功能。
[码云镜像](https://gitee.com/fairyever/d2-admin-start-kit)
+5
View File
@@ -0,0 +1,5 @@
module.exports = {
presets: [
'@vue/app'
]
}
+23
View File
@@ -0,0 +1,23 @@
module.exports = {
moduleFileExtensions: [
'js',
'jsx',
'json',
'vue'
],
transform: {
'^.+\\.vue$': 'vue-jest',
'.+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub',
'^.+\\.jsx?$': 'babel-jest'
},
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1'
},
snapshotSerializers: [
'jest-serializer-vue'
],
testMatch: [
'**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
],
testURL: 'http://localhost/'
}
+17419
View File
File diff suppressed because it is too large Load Diff
+67
View File
@@ -0,0 +1,67 @@
{
"name": "d2-admin",
"version": "1.4.8",
"private": true,
"scripts": {
"serve": "vue-cli-service serve --open",
"start": "vue-cli-service serve --open",
"dev": "vue-cli-service serve --open",
"build": "vue-cli-service build",
"build:travis": "vue-cli-service build --mode travis",
"lint": "vue-cli-service lint --fix",
"test:unit": "vue-cli-service test:unit"
},
"dependencies": {
"@d2-projects/d2-crud": "^1.2.0",
"axios": "^0.17.1",
"babel-polyfill": "^6.26.0",
"better-scroll": "^1.12.1",
"dayjs": "^1.6.7",
"element-ui": "^2.4.4",
"flex.css": "^1.1.7",
"fuse.js": "^3.2.1",
"hotkeys-js": "^3.3.6",
"js-cookie": "^2.2.0",
"lodash": "^4.17.10",
"lowdb": "^1.0.0",
"mockjs": "^1.0.1-beta3",
"nprogress": "^0.2.0",
"particles.js": "^2.0.0",
"screenfull": "^3.3.2",
"ua-parser-js": "^0.7.18",
"vue": "^2.5.17",
"vue-i18n": "^7.4.2",
"vue-router": "^3.0.1",
"vuex": "^3.0.1"
},
"devDependencies": {
"@kazupon/vue-i18n-loader": "^0.3.0",
"@vue/cli-plugin-babel": "^3.0.0",
"@vue/cli-plugin-eslint": "^3.0.0",
"@vue/cli-plugin-unit-jest": "^3.0.0",
"@vue/cli-service": "^3.0.0",
"@vue/eslint-config-standard": "^3.0.0",
"@vue/test-utils": "^1.0.0-beta.20",
"babel-core": "7.0.0-bridge.0",
"babel-jest": "^23.0.1",
"lint-staged": "^7.2.0",
"node-sass": "^4.9.0",
"sass-loader": "^7.0.1",
"svg-sprite-loader": "^3.8.0",
"text-loader": "0.0.1",
"vue-template-compiler": "^2.5.17"
},
"gitHooks": {
"pre-commit": "lint-staged"
},
"lint-staged": {
"*.js": [
"vue-cli-service lint",
"git add"
],
"*.vue": [
"vue-cli-service lint",
"git add"
]
}
}
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 359 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

+181
View File
@@ -0,0 +1,181 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>icon.ico">
<title><%= VUE_APP_TITLE %></title>
<style>
html, body, #app {
height: 100%;
margin: 0px;
padding: 0px;
}
.d2-app-loading-group {
height: 100%;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
background: linear-gradient(to bottom, rgba(255,255,255,0.15) 0%, rgba(0,0,0,0.15) 100%), radial-gradient(at top center, rgba(255,255,255,0.40) 0%, rgba(0,0,0,0.40) 120%) #989898;
background-blend-mode: multiply,multiply;
}
.d2-app-loading-title {
color: #FFF;
font-weight: bold;
font-size: 14px;
margin-top: 40px;
margin-bottom: 10px;
letter-spacing: 0.2em;
}
.d2-app-loading-sub-title {
color: #FFF;
font-size: 10px;
margin-bottom: 10px;
}
.d2-app-loading-sub-info {
color: #FFF;
font-size: 10px;
opacity: .8;
margin-bottom: 4px;
}
.d2-app-loading-btn {
text-decoration: none;
display: inline-block;
line-height: 1;
white-space: nowrap;
cursor: pointer;
background: #fff;
border: 1px solid #dcdfe6;
border-color: #dcdfe6;
color: #606266;
-webkit-appearance: none;
text-align: center;
box-sizing: border-box;
outline: none;
margin: 0;
transition: .1s;
font-weight: 500;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
padding: 12px 20px;
font-size: 14px;
border-radius: 4px;
/* 圆角 */
padding: 7px 15px;
border-radius: 20px;
font-size: 12px;
}
.d2-app-loading-grid {
width: 30px;
height: 30px;
}
.d2-app-loading-grid .d2-app-loading {
width: 10px;
height: 10px;
background-color: #FFF;
float: left;
-webkit-animation: d2-app-loading-grid-scale-delay 1.3s infinite ease-in-out;
animation: d2-app-loading-grid-scale-delay 1.3s infinite ease-in-out;
}
.d2-app-loading-grid .d2-app-loading1 {
border-top-left-radius: 4px;
-webkit-animation-delay: 0.2s;
animation-delay: 0.2s; }
.d2-app-loading-grid .d2-app-loading2 {
-webkit-animation-delay: 0.3s;
animation-delay: 0.3s; }
.d2-app-loading-grid .d2-app-loading3 {
border-top-right-radius: 4px;
-webkit-animation-delay: 0.4s;
animation-delay: 0.4s; }
.d2-app-loading-grid .d2-app-loading4 {
-webkit-animation-delay: 0.1s;
animation-delay: 0.1s; }
.d2-app-loading-grid .d2-app-loading5 {
-webkit-animation-delay: 0.2s;
animation-delay: 0.2s; }
.d2-app-loading-grid .d2-app-loading6 {
-webkit-animation-delay: 0.3s;
animation-delay: 0.3s; }
.d2-app-loading-grid .d2-app-loading7 {
border-bottom-left-radius: 4px;
-webkit-animation-delay: 0s;
animation-delay: 0s; }
.d2-app-loading-grid .d2-app-loading8 {
-webkit-animation-delay: 0.1s;
animation-delay: 0.1s; }
.d2-app-loading-grid .d2-app-loading9 {
border-bottom-right-radius: 4px;
-webkit-animation-delay: 0.2s;
animation-delay: 0.2s; }
@-webkit-keyframes d2-app-loading-grid-scale-delay {
0%, 70%, 100% {
-webkit-transform: scale3D(1, 1, 1);
transform: scale3D(1, 1, 1);
} 35% {
-webkit-transform: scale3D(0, 0, 1);
transform: scale3D(0, 0, 1);
}
}
@keyframes d2-app-loading-grid-scale-delay {
0%, 70%, 100% {
-webkit-transform: scale3D(1, 1, 1);
transform: scale3D(1, 1, 1);
} 35% {
-webkit-transform: scale3D(0, 0, 1);
transform: scale3D(0, 0, 1);
}
}
</style>
<script>
// 感谢您使用 D2Admin
// D2Admin 完全开源免费,并且长期更新维护
// 下面的百度统计代码不会拖慢您的应用速度也不会占用多少网络带宽,我们只是想统计一下我们的用户量
// 所以希望您不要删除我们的统计代码,让我们知道有更多人的在使用,给我们继续开发的动力
var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?de358376fd85791edd2acd3049956aa3";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
<!-- ua -->
<script src="<%= BASE_URL %>script/ua-parser.min.js"></script>
<script src="<%= BASE_URL %>script/ua.js"></script>
</head>
<body>
<noscript>
<strong>We're sorry but d2-admin doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app">
<div class="d2-app-loading-group">
<div class="d2-app-loading-grid">
<div class="d2-app-loading d2-app-loading1"></div>
<div class="d2-app-loading d2-app-loading2"></div>
<div class="d2-app-loading d2-app-loading3"></div>
<div class="d2-app-loading d2-app-loading4"></div>
<div class="d2-app-loading d2-app-loading5"></div>
<div class="d2-app-loading d2-app-loading6"></div>
<div class="d2-app-loading d2-app-loading7"></div>
<div class="d2-app-loading d2-app-loading8"></div>
<div class="d2-app-loading d2-app-loading9"></div>
</div>
<div class="d2-app-loading-title">加载中</div>
<div class="d2-app-loading-sub-title">欢迎使用 D2Admin。初次加载较慢,请耐心等待</div>
<div class="d2-app-loading-sub-info">如果很久很久都没有加载成功,请清空缓存重新加载页面</div>
<div style="margin-top: 10px;">
<a class="d2-app-loading-btn" href="https://github.com/d2-projects/d2-admin" target="blank">Github仓库</a>
<a class="d2-app-loading-btn" href="https://d2-projects.github.io/d2-admin-doc/zh/" target="blank">中文文档</a>
</div>
</div>
</div>
<!-- built files will be auto injected -->
</body>
</html>
+13
View File
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>提示信息</title>
</head>
<body>
<h1>请不要使用手机浏览</h1>
<!-- 请自行完善此页面 -->
</body>
</html>
File diff suppressed because one or more lines are too long
+9
View File
@@ -0,0 +1,9 @@
/* eslint-disable */
var parser = new UAParser()
var uaResult = parser.getResult()
if (uaResult.device.type === 'mobile') {
window.location.href = './is-mobile.html'
}
+15
View File
@@ -0,0 +1,15 @@
<template>
<div id="app">
<router-view/>
</div>
</template>
<script>
export default {
name: 'app'
}
</script>
<style lang="scss">
@import '~@/assets/style/public-class.scss';
</style>
+17
View File
@@ -0,0 +1,17 @@
import request from '@/plugin/axios'
export function httpGet (url, params = {}) {
return request({
url,
method: 'get',
params
})
}
export function httpPost (url, data = {}) {
return request({
url,
method: 'post',
data
})
}
+9
View File
@@ -0,0 +1,9 @@
import request from '@/plugin/axios'
export function AccountLogin (data) {
return request({
url: '/login',
method: 'post',
data
})
}
@@ -0,0 +1,27 @@
// 过渡动画 横向渐变
.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);
}
+13
View File
@@ -0,0 +1,13 @@
// 优化显示
html, body {
margin: 0px;
height: 100%;
font-family: "Arial", "Microsoft YaHei", "黑体", "宋体", sans-serif;
#app {
@extend %full;
a {
text-decoration: none;
}
}
}
+20
View File
@@ -0,0 +1,20 @@
// element 样式补丁
.el-card {
&.is-always-shadow {
box-shadow: 0 0 8px 0 rgba(232,237,250,.6), 0 2px 4px 0 rgba(232,237,250,.5);
}
&.is-hover-shadow {
&:hover {
box-shadow: 0 0 8px 0 rgba(232,237,250,.6), 0 2px 4px 0 rgba(232,237,250,.5);
}
}
}
.el-menu--horizontal {
border-bottom: none !important;
}
.el-tabs__item:focus.is-active.is-focus:not(:active) {
box-shadow: none !important;
}
+8
View File
@@ -0,0 +1,8 @@
#nprogress {
.bar {
background: $color-primary !important;
}
.peg {
box-shadow: 0 0 10px $color-primary, 0 0 5px $color-primary !important;
}
}
+67
View File
@@ -0,0 +1,67 @@
@import 'public';
// 补丁 base
@import '~@/assets/style/fixed/base.scss';
// 补丁 element
@import '~@/assets/style/fixed/element.scss';
// 补丁 n-progress
@import '~@/assets/style/fixed/n-progress.scss';
// 动画
@import '~@/assets/style/animate/vue-transition.scss';
// 在这里写公用的class
// 注意 这个文件里只写class
// mixin等内容请在 public.scss 里书写
// 文字相关
.#{$prefix}-text-center {
text-align: center;
}
// 浮动相关
.#{$prefix}-fl {
float: left;
}
.#{$prefix}-fr {
float: right;
}
.#{$prefix}-clearfix:before,
.#{$prefix}-clearfix:after {
display: table;
content: "";
}
.#{$prefix}-clearfix:after {
clear: both
}
// 边距相关
$sizes: (0, 5, 10, 15, 20);
@for $index from 1 to 6 {
.#{$prefix}-m-#{nth($sizes, $index)} { margin: #{nth($sizes, $index)}px !important; }
.#{$prefix}-mt-#{nth($sizes, $index)} { margin-top: #{nth($sizes, $index)}px !important; }
.#{$prefix}-mr-#{nth($sizes, $index)} { margin-right: #{nth($sizes, $index)}px !important; }
.#{$prefix}-mb-#{nth($sizes, $index)} { margin-bottom: #{nth($sizes, $index)}px !important; }
.#{$prefix}-ml-#{nth($sizes, $index)} { margin-left: #{nth($sizes, $index)}px !important; }
.#{$prefix}-p-#{nth($sizes, $index)} { padding: #{nth($sizes, $index)}px !important; }
.#{$prefix}-pt-#{nth($sizes, $index)} { padding-top: #{nth($sizes, $index)}px !important; }
.#{$prefix}-pr-#{nth($sizes, $index)} { padding-right: #{nth($sizes, $index)}px !important; }
.#{$prefix}-pb-#{nth($sizes, $index)} { padding-bottom: #{nth($sizes, $index)}px !important; }
.#{$prefix}-pl-#{nth($sizes, $index)} { padding-left: #{nth($sizes, $index)}px !important; }
}
// 快速使用
.#{$prefix}-m { margin: 20px !important; }
.#{$prefix}-mt { margin-top: 20px !important; }
.#{$prefix}-mr { margin-right: 20px !important; }
.#{$prefix}-mb { margin-bottom: 20px !important; }
.#{$prefix}-ml { margin-left: 20px !important; }
.#{$prefix}-p { padding: 20px !important; }
.#{$prefix}-pt { padding-top: 20px !important; }
.#{$prefix}-pr { padding-right: 20px !important; }
.#{$prefix}-pb { padding-bottom: 20px !important; }
.#{$prefix}-pl { padding-left: 20px !important; }
+44
View File
@@ -0,0 +1,44 @@
@import '~@/assets/style/unit/color.scss';
// 工具类名统一前缀
$prefix: d2;
// 禁止用户选中 鼠标变为手形
%unable-select {
user-select: none;
cursor: pointer;
}
// 填满父元素
// 组要父元素 position: relative | absolute;
%full {
position: absolute;
top: 0px;
right: 0px;
bottom: 0px;
left: 0px;
}
// flex 垂直水平居中
%flex-center-row {
display: flex;
justify-content: center;
align-items: center;
flex-direction: row;
}
%flex-center-col {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
// 将元素模拟成卡片外观
%card {
border: 1px solid #dddee1;
border-color: #e9eaec;
background: #fff;
border-radius: 4px;
font-size: 14px;
position: relative;
}
+2
View File
@@ -0,0 +1,2 @@
@import './setting.scss';
@import '../theme.scss';
+59
View File
@@ -0,0 +1,59 @@
// 主题名称
$theme-name: 'd2';
// 主题背景颜色
$theme-bg-color: #ebf1f6;
// 主题背景图片遮罩
$theme-bg-mask: rgba(#000, 0);
// container组件
$theme-container-background-color: rgba(#FFF, 1);
$theme-container-header-footer-background-color: #FFF;
$theme-container-border-inner: 1px solid #cfd7e5;
$theme-container-border-outer: 1px solid #cfd7e5;
$theme-multiple-page-control-color: $color-text-normal;
$theme-multiple-page-control-color-active: #2f74ff;
$theme-multiple-page-control-nav-prev-color: #cfd7e5;
$theme-multiple-page-control-nav-next-color: #cfd7e5;
$theme-multiple-page-control-border-color: #cfd7e5;
$theme-multiple-page-control-border-color-active: #FFF;
$theme-multiple-page-control-background-color: rgba(#000, .03);
$theme-multiple-page-control-background-color-active: #FFF;
// 顶栏和侧边栏中展开的菜单 hover 状态下
$theme-menu-item-color-hover: #293849;
$theme-menu-item-background-color-hover: #ecf5ff;
// 顶栏上的文字颜色
$theme-header-item-color: $color-text-normal;
$theme-header-item-background-color: transparent;
// 顶栏上的项目在 hover 时
$theme-header-item-color-hover: #2f74ff;
$theme-header-item-background-color-hover: rgba(#FFF, .5);
// 顶栏上的项目在 focus 时
$theme-header-item-color-focus: #2f74ff;
$theme-header-item-background-color-focus: rgba(#FFF, .5);
// 顶栏上的项目在 active 时
$theme-header-item-color-active: #2f74ff;
$theme-header-item-background-color-active: rgba(#FFF, .5);
// 侧边栏上的文字颜色
$theme-aside-item-color: $color-text-normal;
$theme-aside-item-background-color: transparent;
// 侧边栏上的项目在 hover 时
$theme-aside-item-color-hover: #2f74ff;
$theme-aside-item-background-color-hover: rgba(#FFF, .5);
// 侧边栏上的项目在 focus 时
$theme-aside-item-color-focus: #2f74ff;
$theme-aside-item-background-color-focus: rgba(#FFF, .5);
// 侧边栏上的项目在 active 时
$theme-aside-item-color-active: #2f74ff;
$theme-aside-item-background-color-active: rgba(#FFF, .5);
// 侧边栏菜单为空的时候显示的元素
$theme-aside-menu-empty-icon-color: $color-text-normal;
$theme-aside-menu-empty-text-color: $color-text-normal;
$theme-aside-menu-empty-background-color: rgba(#000, .03);
$theme-aside-menu-empty-icon-color-hover: $color-text-main;
$theme-aside-menu-empty-text-color-hover: $color-text-main;
$theme-aside-menu-empty-background-color-hover: rgba(#000, .05);
+2
View File
@@ -0,0 +1,2 @@
@import './setting.scss';
@import '../theme.scss';
+59
View File
@@ -0,0 +1,59 @@
// 主题名称
$theme-name: 'line';
// 主题背景颜色
$theme-bg-color: #f8f8f9;
// 主题背景图片遮罩
$theme-bg-mask: rgba(#000, 0);
// container组件
$theme-container-background-color: rgba(#FFF, .8);
$theme-container-header-footer-background-color: #FFF;
$theme-container-border-inner: 1px solid $color-border-2;
$theme-container-border-outer: 1px solid #cfd7e5;
$theme-multiple-page-control-color: #FFF;
$theme-multiple-page-control-color-active: $color-text-normal;
$theme-multiple-page-control-nav-prev-color: #cfd7e5;
$theme-multiple-page-control-nav-next-color: #cfd7e5;
$theme-multiple-page-control-border-color: #cfd7e5;
$theme-multiple-page-control-border-color-active: #FFF;
$theme-multiple-page-control-background-color: #cfd7e5;
$theme-multiple-page-control-background-color-active: #FFF;
// 顶栏和侧边栏中展开的菜单 hover 状态下
$theme-menu-item-color-hover: #293849;
$theme-menu-item-background-color-hover: #EFEFEF;
// 顶栏上的文字颜色
$theme-header-item-color: $color-text-normal;
$theme-header-item-background-color: transparent;
// 顶栏上的项目在 hover 时
$theme-header-item-color-hover: $color-text-main;
$theme-header-item-background-color-hover: rgba(#000, .02);
// 顶栏上的项目在 focus 时
$theme-header-item-color-focus: $color-text-main;
$theme-header-item-background-color-focus: rgba(#000, .02);
// 顶栏上的项目在 active 时
$theme-header-item-color-active: $color-text-main;
$theme-header-item-background-color-active: rgba(#000, .03);
// 侧边栏上的文字颜色
$theme-aside-item-color: $color-text-normal;
$theme-aside-item-background-color: transparent;
// 侧边栏上的项目在 hover 时
$theme-aside-item-color-hover: $color-text-main;
$theme-aside-item-background-color-hover: rgba(#000, .02);
// 侧边栏上的项目在 focus 时
$theme-aside-item-color-focus: $color-text-main;
$theme-aside-item-background-color-focus: rgba(#000, .02);
// 侧边栏上的项目在 active 时
$theme-aside-item-color-active: $color-text-main;
$theme-aside-item-background-color-active: rgba(#000, .03);
// 侧边栏菜单为空的时候显示的元素
$theme-aside-menu-empty-icon-color: $color-text-normal;
$theme-aside-menu-empty-text-color: $color-text-normal;
$theme-aside-menu-empty-background-color: rgba(#000, .03);
$theme-aside-menu-empty-icon-color-hover: $color-text-main;
$theme-aside-menu-empty-text-color-hover: $color-text-main;
$theme-aside-menu-empty-background-color-hover: rgba(#000, .05);
+8
View File
@@ -0,0 +1,8 @@
@import '~@/assets/style/public.scss';
@import '~@/assets/style/theme/theme-base.scss';
@import '~@/assets/style/theme/d2/index.scss';
@import '~@/assets/style/theme/line/index.scss';
@import '~@/assets/style/theme/star/index.scss';
@import '~@/assets/style/theme/tomorrow-night-blue/index.scss';
@import '~@/assets/style/theme/violet/index.scss';
+2
View File
@@ -0,0 +1,2 @@
@import './setting.scss';
@import '../theme.scss';
+59
View File
@@ -0,0 +1,59 @@
// 主题名称
$theme-name: 'star';
// 主题背景颜色
$theme-bg-color: #EFF4F8;
// 主题背景图片遮罩
$theme-bg-mask: rgba(#000, .3);
// container组件
$theme-container-background-color: rgba(#FFF, .9);
$theme-container-header-footer-background-color: #FFF;
$theme-container-border-inner: 1px solid $color-border-1;
$theme-container-border-outer: 1px solid #114450;
$theme-multiple-page-control-color: #FFF;
$theme-multiple-page-control-color-active: $color-text-normal;
$theme-multiple-page-control-nav-prev-color: #FFF;
$theme-multiple-page-control-nav-next-color: #FFF;
$theme-multiple-page-control-border-color: #114450;
$theme-multiple-page-control-border-color-active: #FFF;
$theme-multiple-page-control-background-color: rgba(#FFF, .5);
$theme-multiple-page-control-background-color-active: #FFF;
// 顶栏和侧边栏中展开的菜单 hover 状态下
$theme-menu-item-color-hover: #293849;
$theme-menu-item-background-color-hover: #ecf5ff;
// 顶栏上的文字颜色
$theme-header-item-color: #FFF;
$theme-header-item-background-color: transparent;
// 顶栏上的项目在 hover 时
$theme-header-item-color-hover: #FFF;
$theme-header-item-background-color-hover: rgba(#000, .2);
// 顶栏上的项目在 focus 时
$theme-header-item-color-focus: #FFF;
$theme-header-item-background-color-focus: rgba(#000, .2);
// 顶栏上的项目在 active 时
$theme-header-item-color-active: #FFF;
$theme-header-item-background-color-active: rgba(#000, .3);
// 侧边栏上的文字颜色
$theme-aside-item-color: #FFF;
$theme-aside-item-background-color: transparent;
// 侧边栏上的项目在 hover 时
$theme-aside-item-color-hover: #FFF;
$theme-aside-item-background-color-hover: rgba(#000, .2);
// 侧边栏上的项目在 focus 时
$theme-aside-item-color-focus: #FFF;
$theme-aside-item-background-color-focus: rgba(#000, .2);
// 侧边栏上的项目在 active 时
$theme-aside-item-color-active: #FFF;
$theme-aside-item-background-color-active: rgba(#000, .3);
// 侧边栏菜单为空的时候显示的元素
$theme-aside-menu-empty-icon-color: #FFF;
$theme-aside-menu-empty-text-color: #FFF;
$theme-aside-menu-empty-background-color: rgba(#FFF, .2);
$theme-aside-menu-empty-icon-color-hover: #FFF;
$theme-aside-menu-empty-text-color-hover: #FFF;
$theme-aside-menu-empty-background-color-hover: rgba(#FFF, .3);
+445
View File
@@ -0,0 +1,445 @@
// 减小弹出菜单的项目高度
.el-menu--popup {
.el-menu-item {
height: 36px;
line-height: 36px;
}
.el-submenu__title {
height: 36px;
line-height: 36px;
}
}
// 整体框架结构
.d2-layout-header-aside-group {
height: 100%;
width: 100%;
min-width: 900px;
background-size: cover;
background-position: center;
overflow: hidden;
position: relative;
// 背景上面的半透明遮罩
.d2-layout-header-aside-mask {
@extend %full;
}
// 内容层
.d2-layout-header-aside-content {
@extend %full;
.d2-theme-header {
height: 60px;
.d2-theme-header-menu {
overflow: hidden;
&.is-scrollable {
position: relative;
padding: 0 20px;
.d2-theme-header-menu__prev, .d2-theme-header-menu__next {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
}
}
.d2-theme-header-menu__content {
overflow: hidden;
.d2-theme-header-menu__scroll {
white-space: nowrap;
position: relative;
-webkit-transition: -webkit-transform .3s;
transition: -webkit-transform .3s;
transition: transform .3s;
transition: transform .3s, -webkit-transform .3s;
transition: transform .3s,-webkit-transform .3s;
float: left;
}
}
.d2-theme-header-menu__prev, .d2-theme-header-menu__next {
height: 60px;
position: absolute;
top: 0;
font-size: 20px;
cursor: pointer;
display: none;
}
.d2-theme-header-menu__prev {
left: 0;
border-top-left-radius: 2px;
border-bottom-left-radius: 2px;
}
.d2-theme-header-menu__next {
right: 0;
border-top-right-radius: 2px;
border-bottom-right-radius: 2px;
}
}
}
.d2-theme-container {
.d2-theme-container-aside {
transition: width .3s;
position: relative;
.d2-layout-header-aside-menu-side {
@extend %full;
overflow: hidden;
}
}
.d2-theme-container-main {
padding: 0px;
position: relative;
overflow: hidden;
.d2-theme-container-main-layer {
position: absolute;
top: 0px;
bottom: 0px;
left: 0px;
right: 0px;
}
.d2-theme-container-main-body {
position: relative;
}
}
}
}
}
// 主题公用
.d2-layout-header-aside-group {
&.grayMode {
-webkit-filter: grayscale(100%);
-moz-filter: grayscale(100%);
-ms-filter: grayscale(100%);
-o-filter: grayscale(100%);
filter: grayscale(100%);
filter: gray;
}
// 主体
.d2-layout-header-aside-content {
// [布局] 顶栏
.d2-theme-header {
// logo区域
.logo-group {
transition: width .3s;
float: left;
text-align: center;
img {
height: 60px;
}
}
// 折叠侧边栏切换按钮
.toggle-aside-btn {
float: left;
height: 60px;
width: 60px;
display: flex;
justify-content: center;
align-items: center;
@extend %unable-select;
i {
font-size: 20px;
margin-top: 4px;
}
}
// [菜单] 顶栏
.el-menu {
float: left;
border-bottom: none;
background-color: transparent;
%header-menu-item {
@extend %unable-select;
i.fa {
font-size: 16px;
margin-right: 4px;
}
}
.el-menu-item {
@extend %header-menu-item;
border-bottom: none;
}
.el-submenu {
@extend %header-menu-item;
.el-submenu__title {
border-bottom: none;
}
}
}
// 顶栏右侧的按钮
.d2-header-right {
float: right;
height: 60px;
display: flex;
align-items: center;
.btn-text {
padding: 14px 12px;
border-radius: 4px;
margin: 0px !important;
}
.el-dropdown {
@extend %unable-select;
}
}
}
// [布局] 顶栏下面
.d2-theme-container {
// 侧边栏
.d2-theme-container-aside {
%d2-theme-container-aside-menu-icon {
width: 20px;
text-align: center;
font-size: 16px;
}
// [菜单] 正常状态
.el-menu {
@extend %unable-select;
background-color: transparent;
border-right: none;
.el-menu-item {
i {
@extend %d2-theme-container-aside-menu-icon;
}
}
}
.el-submenu {
@extend %unable-select;
.el-submenu__title {
i {
@extend %d2-theme-container-aside-menu-icon;
}
.el-submenu__icon-arrow {
margin-top: -10px;
}
}
}
// 菜单为空的时候显示的信息
.d2-layout-header-aside-menu-empty {
height: 160px;
margin: 10px;
margin-top: 0px;
border-radius: 4px;
@extend %unable-select;
i {
font-size: 30px;
margin-bottom: 10px;
}
span {
font-size: 14px;
}
}
// [菜单] 折叠状态
.el-menu--collapse {
background-color: transparent;
.el-submenu__title {
text-align: center;
}
}
}
// 右下 主体
.d2-theme-container-main {
// 主体部分分为多页面控制器 和主体
.d2-theme-container-main-header {
// 多页面控制器
.d2-multiple-page-control-group {
padding-right: 20px;
.d2-multiple-page-control-content {
overflow: auto;
position: relative;
.d2-multiple-page-control-content-inner {
.d2-multiple-page-control {
.el-tabs__header.is-top {
margin: 0px;
}
.el-tabs__nav {
overflow: hidden;
}
}
}
}
.d2-multiple-page-control-btn {
position: relative;
bottom: -1px;
.el-dropdown {
.el-button-group {
.el-button:first-child {
border-bottom-left-radius: 0px;
}
.el-button:last-child {
border-bottom-right-radius: 0px;
}
}
}
}
}
}
// 主体
.d2-theme-container-main-body {
// 布局组件
.container-component {
@extend %full;
overflow: hidden;
// 填充式布局组件
.d2-container-full {
position: absolute;
top: 0px;
right: 20px;
bottom: 0px;
left: 0px;
display: flex;
flex-direction: column;
overflow: hidden;
.d2-container-full__header {
padding: 20px;
}
.d2-container-full__body {
flex-grow: 1;
padding: 20px 20px;
overflow: auto;
position: relative;
}
.d2-container-full__footer {
padding: 20px;
}
}
// 填充式布局组件 - 滚动优化
.d2-container-full-bs {
position: absolute;
top: 0px;
right: 20px;
bottom: 0px;
left: 0px;
display: flex;
flex-direction: column;
overflow: hidden;
.d2-container-full-bs__header {
padding: 20px;
}
.d2-container-full-bs__body {
flex-grow: 1;
overflow: hidden;
position: relative;
.d2-container-full-bs__body-wrapper-inner {
padding: 20px;
position: relative;
}
}
.d2-container-full-bs__footer {
padding: 20px;
}
}
// 隐形布局组件
.d2-container-ghost {
position: absolute;
top: 0px;
right: 20px;
bottom: 0px;
left: 0px;
display: flex;
flex-direction: column;
overflow: hidden;
.d2-container-ghost__header {
padding: 20px;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
}
.d2-container-ghost__body {
flex-grow: 1;
overflow: auto;
position: relative;
}
.d2-container-ghost__footer {
padding: 20px;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
}
// 隐形布局组件 - 滚动优化
.d2-container-ghost-bs {
position: absolute;
top: 0px;
right: 20px;
bottom: 0px;
left: 0px;
display: flex;
flex-direction: column;
overflow: hidden;
.d2-container-ghost-bs__header {
padding: 20px;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
}
.d2-container-ghost-bs__body {
flex-grow: 1;
overflow: hidden;
position: relative;
}
.d2-container-ghost-bs__footer {
padding: 20px;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
}
// 卡片式布局组件
.d2-container-card {
position: absolute;
top: 0px;
right: 20px;
bottom: 0px;
left: 0px;
display: flex;
flex-direction: column;
overflow: hidden;
.d2-container-card__header {
padding: 20px;
}
.d2-container-card__body {
flex-grow: 1;
overflow: auto;
.d2-container-card__body-card {
position: relative;
margin-bottom: 20px;
padding: 20px;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
}
}
.d2-container-card__footer {
padding: 20px;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
}
// 卡片式布局组件 - 滚动优化
.d2-container-card-bs {
position: absolute;
top: 0px;
right: 20px;
bottom: 0px;
left: 0px;
display: flex;
flex-direction: column;
overflow: hidden;
.d2-container-card-bs__header {
padding: 20px;
}
.d2-container-card-bs__body {
position: relative;
flex-grow: 1;
overflow: hidden;
.d2-container-card-bs__body-wrapper-inner {
padding-bottom: 20px;
}
.d2-container-card-bs__body-card {
position: relative;
padding: 20px;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
}
}
.d2-container-card-bs__footer {
padding: 20px;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
}
}
}
}
}
}
}
+413
View File
@@ -0,0 +1,413 @@
// 每个主题特有的设置
.theme-#{$theme-name} {
.el-card {
&.d2-card {
border: $theme-container-border-outer;
.el-card__header {
border-bottom: $theme-container-border-outer;
}
}
}
// 背景图片和遮罩
.d2-layout-header-aside-group {
background-color: $theme-bg-color;
.d2-layout-header-aside-mask {
background: $theme-bg-mask;
}
}
// 菜单项目
@mixin theme-menu-hover-style {
color: $theme-menu-item-color-hover;
i.fa {
color: $theme-menu-item-color-hover;
}
background: $theme-menu-item-background-color-hover;
}
%el-menu-icon {
i {
display: inline-block;
width: 14px;
text-align: center;
margin-right: 5px;
}
svg {
margin: 0px;
height: 14px;
width: 14px;
margin-right: 5px;
}
}
.el-submenu__title {
@extend %unable-select;
@extend %el-menu-icon;
}
.el-menu-item {
@extend %unable-select;
@extend %el-menu-icon;
}
.el-submenu__title:hover {
@include theme-menu-hover-style;
}
.el-menu-item:hover {
@include theme-menu-hover-style;
}
.el-menu--horizontal .el-menu-item:not(.is-disabled):hover {
@include theme-menu-hover-style;
}
.el-menu--horizontal .el-menu .el-submenu__title:hover {
@include theme-menu-hover-style;
}
// 顶栏
.d2-theme-header {
// 顶栏菜单空间不足时显示的滚动控件
.d2-theme-header-menu {
.d2-theme-header-menu__prev, .d2-theme-header-menu__next {
color: $theme-header-item-color;
background: $theme-header-item-background-color;
&:hover {
color: $theme-header-item-color-hover;
background: $theme-header-item-background-color-hover;
}
}
}
// 切换按钮
.toggle-aside-btn {
i {
color: $theme-header-item-color;
background: $theme-header-item-background-color;
&:hover {
color: $theme-header-item-color-hover;
}
}
}
// 顶栏菜单
.el-menu {
.el-menu-item {
transition: border-top-color 0s;
color: $theme-header-item-color;
background: $theme-header-item-background-color;
i.fa { color: inherit; }
&:hover {
color: $theme-header-item-color-hover;
background: $theme-header-item-background-color-hover;
i.fa { color: inherit; }
}
&:focus {
color: $theme-header-item-color-focus;
background: $theme-header-item-background-color-focus;
i.fa { color: inherit; }
}
&.is-active {
color: $theme-header-item-color-active;
background: $theme-header-item-background-color-active;
i.fa { color: inherit; }
}
}
.el-submenu {
&.is-active {
.el-submenu__title {
color: $theme-header-item-color-active;
background: $theme-header-item-background-color-active;
i.fa { color: inherit; }
}
}
.el-submenu__title {
transition: border-top-color 0s;
color: $theme-header-item-color;
background: $theme-header-item-background-color;
i.fa { color: inherit; }
.el-submenu__icon-arrow {
color: $theme-header-item-color;
}
&:hover {
color: $theme-header-item-color-hover;
background: $theme-header-item-background-color-hover;
i.fa { color: inherit; }
.el-submenu__icon-arrow {
color: $theme-header-item-color-hover;
}
}
&:focus {
color: $theme-header-item-color-focus;
background: $theme-header-item-background-color-focus;
i.fa { color: inherit; }
.el-submenu__icon-arrow {
color: $theme-header-item-color-focus;
}
}
}
}
}
// 顶栏右侧
.d2-header-right {
.btn-text {
color: $theme-header-item-color;
&.can-hover {
&:hover {
color: $theme-header-item-color-hover;
background: $theme-header-item-background-color-hover;
}
}
}
}
}
// [布局] 顶栏下面
.d2-theme-container {
// 侧边栏
.d2-theme-container-aside {
// 菜单为空的时候显示的信息
.d2-layout-header-aside-menu-empty {
background: $theme-aside-menu-empty-background-color;
i {
color: $theme-aside-menu-empty-icon-color;
}
span {
color: $theme-aside-menu-empty-text-color;
}
&:hover {
background: $theme-aside-menu-empty-background-color-hover;
i {
color: $theme-aside-menu-empty-icon-color-hover;
}
span {
color: $theme-aside-menu-empty-text-color-hover;
}
}
}
// [菜单] 正常状态
.el-menu {
.el-menu-item {
color: $theme-aside-item-color;
background: $theme-aside-item-background-color;
i {
color: $theme-aside-item-color;
}
&:hover {
color: $theme-aside-item-color-hover;
background: $theme-aside-item-background-color-hover;
i {
color: $theme-aside-item-color-hover;
}
}
&:focus {
color: $theme-aside-item-color-focus;
background: $theme-aside-item-background-color-focus;
i {
color: $theme-aside-item-color-focus;
}
}
&.is-active {
color: $theme-aside-item-color-active;
background: $theme-aside-item-background-color-active;
i {
color: $theme-aside-item-color-active;
}
}
}
}
.el-submenu {
.el-submenu__title {
color: $theme-aside-item-color;
background: $theme-aside-item-background-color;
i {
color: $theme-aside-item-color;
}
.el-submenu__icon-arrow {
color: $theme-aside-item-color;
}
&:hover {
color: $theme-aside-item-color-hover;
background: $theme-aside-item-background-color-hover;
i {
color: $theme-aside-item-color-hover;
}
.el-submenu__icon-arrow {
color: $theme-aside-item-color-hover;
}
}
}
}
}
.d2-theme-container-main {
// 主体部分分为多页面控制器 和主体
.d2-theme-container-main-header {
// 多页面控制器
.d2-multiple-page-control {
.el-tabs__header.is-top {
border-bottom-color: $theme-multiple-page-control-border-color;
}
.el-tabs__nav {
border-color: $theme-multiple-page-control-border-color;
.el-tabs__item {
@extend %unable-select;
color: $theme-multiple-page-control-color;
background-color: $theme-multiple-page-control-background-color;
border-left-color: $theme-multiple-page-control-border-color;
&:first-child {
border-left: none;
&:hover {
padding: 0px 20px;
}
.el-icon-close {
display: none;
}
}
}
.el-tabs__item.is-active {
color: $theme-multiple-page-control-color-active;
background-color: $theme-multiple-page-control-background-color-active;
border-bottom-color: $theme-multiple-page-control-border-color-active;
}
}
%el-tabs__nav {
font-size: 20px;
}
.el-tabs__nav-prev {
@extend %el-tabs__nav;
color: $theme-multiple-page-control-nav-prev-color;
}
.el-tabs__nav-next {
@extend %el-tabs__nav;
color: $theme-multiple-page-control-nav-next-color;
}
}
// 多页控制器的关闭控制
.d2-multiple-page-control-btn {
.el-dropdown {
.el-button-group {
.el-button {
border-color: $theme-multiple-page-control-border-color;
}
}
}
}
}
// 主体
.d2-theme-container-main-body {
// 布局组件
.container-component {
// [组件]
// d2-container-full 填充型
.d2-container-full {
border: $theme-container-border-outer;
border-top: none;
border-bottom: none;
.d2-container-full__header {
border-bottom: $theme-container-border-inner;
background: $theme-container-header-footer-background-color;
}
.d2-container-full__body {
background: $theme-container-background-color;
}
.d2-container-full__footer {
border-top: $theme-container-border-inner;
background: $theme-container-header-footer-background-color;
}
}
// [组件]
// d2-container-full-bs 填充型 滚动优化
.d2-container-full-bs {
border: $theme-container-border-outer;
border-top: none;
border-bottom: none;
.d2-container-full-bs__header {
border-bottom: $theme-container-border-inner;
background: $theme-container-header-footer-background-color;
}
.d2-container-full-bs__body {
background: $theme-container-background-color;
}
.d2-container-full-bs__footer {
border-top: $theme-container-border-inner;
background: $theme-container-header-footer-background-color;
}
}
// [组件]
// d2-container-ghost 隐形布局组件
.d2-container-ghost {
.d2-container-ghost__header {
border-bottom: $theme-container-border-outer;
border-left: $theme-container-border-outer;
border-right: $theme-container-border-outer;
background: $theme-container-header-footer-background-color;
}
.d2-container-ghost__footer {
border-top: $theme-container-border-outer;
border-left: $theme-container-border-outer;
border-right: $theme-container-border-outer;
background: $theme-container-header-footer-background-color;
}
}
// [组件]
// d2-container-ghost-bs 隐形布局组件 滚动优化
.d2-container-ghost-bs {
.d2-container-ghost-bs__header {
border-bottom: $theme-container-border-outer;
border-left: $theme-container-border-outer;
border-right: $theme-container-border-outer;
background: $theme-container-header-footer-background-color;
}
.d2-container-ghost-bs__footer {
border-top: $theme-container-border-outer;
border-left: $theme-container-border-outer;
border-right: $theme-container-border-outer;
background: $theme-container-header-footer-background-color;
}
}
// [组件]
// d2-container-card 卡片型
.d2-container-card {
.d2-container-card__header {
border-bottom: $theme-container-border-inner;
border-left: $theme-container-border-outer;
border-right: $theme-container-border-outer;
background: $theme-container-header-footer-background-color;
}
.d2-container-card__body {
.d2-container-card__body-card {
background: $theme-container-background-color;
border-left: $theme-container-border-outer;
border-right: $theme-container-border-outer;
border-bottom: $theme-container-border-outer;
}
}
.d2-container-card__footer {
border-top: $theme-container-border-outer;
border-left: $theme-container-border-outer;
border-right: $theme-container-border-outer;
background: $theme-container-header-footer-background-color;
}
}
// [组件]
// d2-container-card-bs 卡片型 滚动优化
.d2-container-card-bs {
.d2-container-card-bs__header {
border-bottom: $theme-container-border-inner;
border-left: $theme-container-border-outer;
border-right: $theme-container-border-outer;
background: $theme-container-header-footer-background-color;
}
.d2-container-card-bs__body {
.d2-container-card-bs__body-card {
background: $theme-container-background-color;
border-left: $theme-container-border-outer;
border-right: $theme-container-border-outer;
border-bottom: $theme-container-border-outer;
}
}
.d2-container-card-bs__footer {
border-top: $theme-container-border-outer;
border-left: $theme-container-border-outer;
border-right: $theme-container-border-outer;
background: $theme-container-header-footer-background-color;
}
}
}
}
}
}
}
@@ -0,0 +1,2 @@
@import './setting.scss';
@import '../theme.scss';
@@ -0,0 +1,59 @@
// 主题名称
$theme-name: 'tomorrow-night-blue';
// 主题背景颜色
$theme-bg-color: #002253;
// 主题背景图片遮罩
$theme-bg-mask: rgba(#000, 0);
// container组件
$theme-container-background-color: rgba(#FFF, 1);
$theme-container-header-footer-background-color: #FFF;
$theme-container-border-inner: 1px solid $color-border-1;
$theme-container-border-outer: 1px solid #002253;
$theme-multiple-page-control-color: #FFF;
$theme-multiple-page-control-color-active: $color-text-normal;
$theme-multiple-page-control-nav-prev-color: #FFF;
$theme-multiple-page-control-nav-next-color: #FFF;
$theme-multiple-page-control-border-color: #002253;
$theme-multiple-page-control-border-color-active: #FFF;
$theme-multiple-page-control-background-color: rgba(#FFF, .2);
$theme-multiple-page-control-background-color-active: #FFF;
// 顶栏和侧边栏中展开的菜单 hover 状态下
$theme-menu-item-color-hover: #293849;
$theme-menu-item-background-color-hover: #ecf5ff;
// 顶栏上的文字颜色
$theme-header-item-color: #FF929A;
$theme-header-item-background-color: transparent;
// 顶栏上的项目在 hover 时
$theme-header-item-color-hover: #FFEBA4;
$theme-header-item-background-color-hover: rgba(#FFF, .05);
// 顶栏上的项目在 focus 时
$theme-header-item-color-focus: #FFB870;
$theme-header-item-background-color-focus: rgba(#FFF, .05);
// 顶栏上的项目在 active 时
$theme-header-item-color-active: #FFB870;
$theme-header-item-background-color-active: rgba(#FFF, .05);
// 侧边栏上的文字颜色
$theme-aside-item-color: #FF929A;
$theme-aside-item-background-color: transparent;
// 侧边栏上的项目在 hover 时
$theme-aside-item-color-hover: #FFEBA4;
$theme-aside-item-background-color-hover: rgba(#FFF, .05);
// 侧边栏上的项目在 focus 时
$theme-aside-item-color-focus: #FFB870;
$theme-aside-item-background-color-focus: rgba(#FFF, .05);
// 侧边栏上的项目在 active 时
$theme-aside-item-color-active: #FFB870;
$theme-aside-item-background-color-active: rgba(#FFF, .05);
// 侧边栏菜单为空的时候显示的元素
$theme-aside-menu-empty-icon-color: #FFB870;
$theme-aside-menu-empty-text-color: #FFB870;
$theme-aside-menu-empty-background-color: rgba(#FFF, .1);
$theme-aside-menu-empty-icon-color-hover: #FFEBA4;
$theme-aside-menu-empty-text-color-hover: #FFEBA4;
$theme-aside-menu-empty-background-color-hover: rgba(#FFF, .2);
+9
View File
@@ -0,0 +1,9 @@
@import './setting.scss';
@import '../theme.scss';
.theme-#{$theme-name} {
.d2-layout-header-aside-group {
background: #bc00e3;
background: linear-gradient(120deg, #bc00e3 0%, #4EFFFB 100%);
}
}
@@ -0,0 +1,59 @@
// 主题名称
$theme-name: 'violet';
// 主题背景颜色
$theme-bg-color: #000;
// 主题背景图片遮罩
$theme-bg-mask: rgba(#000, 0);
// container组件
$theme-container-background-color: #FFF;
$theme-container-header-footer-background-color: #FFF;
$theme-container-border-inner: 1px solid $color-border-2;
$theme-container-border-outer: 1px solid #8C40E2;
$theme-multiple-page-control-color: #FFF;
$theme-multiple-page-control-color-active: $color-text-normal;
$theme-multiple-page-control-nav-prev-color: #FFF;
$theme-multiple-page-control-nav-next-color: #FFF;
$theme-multiple-page-control-border-color: #8C40E2;
$theme-multiple-page-control-border-color-active: #FFF;
$theme-multiple-page-control-background-color: rgba(#FFF, .3);
$theme-multiple-page-control-background-color-active: #FFF;
// 顶栏和侧边栏中展开的菜单 hover 状态下
$theme-menu-item-color-hover: #293849;
$theme-menu-item-background-color-hover: #ecf5ff;
// 顶栏上的文字颜色
$theme-header-item-color: #FFF;
$theme-header-item-background-color: transparent;
// 顶栏上的项目在 hover 时
$theme-header-item-color-hover: #FFF;
$theme-header-item-background-color-hover: linear-gradient(-180deg, rgba(255,255,255,0.18) 0%, rgba(255,255,255,0.12) 100%);
// 顶栏上的项目在 focus 时
$theme-header-item-color-focus: #FFF;
$theme-header-item-background-color-focus: linear-gradient(-180deg, rgba(255,255,255,0.18) 0%, rgba(255,255,255,0.12) 100%);
// 顶栏上的项目在 active 时
$theme-header-item-color-active: #FFF;
$theme-header-item-background-color-active: linear-gradient(-180deg, rgba(255,255,255,0.18) 0%, rgba(255,255,255,0.12) 100%);
// 侧边栏上的文字颜色
$theme-aside-item-color: #FFF;
$theme-aside-item-background-color: transparent;
// 侧边栏上的项目在 hover 时
$theme-aside-item-color-hover: #FFF;
$theme-aside-item-background-color-hover: linear-gradient(90deg, rgba(255,255,255,0.28) 0%, rgba(255,255,255,0.00) 100%);
// 侧边栏上的项目在 focus 时
$theme-aside-item-color-focus: #FFF;
$theme-aside-item-background-color-focus: linear-gradient(90deg, rgba(255,255,255,0.28) 0%, rgba(255,255,255,0.00) 100%);
// 侧边栏上的项目在 active 时
$theme-aside-item-color-active: #FFF;
$theme-aside-item-background-color-active: linear-gradient(90deg, rgba(255,255,255,0.28) 0%, rgba(255,255,255,0.00) 100%);
// 侧边栏菜单为空的时候显示的元素
$theme-aside-menu-empty-icon-color: #FFF;
$theme-aside-menu-empty-text-color: #FFF;
$theme-aside-menu-empty-background-color: rgba(#000, .1);
$theme-aside-menu-empty-icon-color-hover: #FFF;
$theme-aside-menu-empty-text-color-hover: #FFF;
$theme-aside-menu-empty-background-color-hover: rgba(#000, .15);
+23
View File
@@ -0,0 +1,23 @@
// 主色
$color-primary: #409EFF;
// 辅助色
$color-info: #909399;
$color-success: #67C23A;
$color-warning: #E6A23C;
$color-danger: #F56C6C;
// 文字
$color-text-main: #303133;
$color-text-normal: #606266;
$color-text-sub: #909399;
$color-text-placehoder: #C0C4CC;
// 边框
$color-border-1: #DCDFE6;
$color-border-2: #E4E7ED;
$color-border-3: #EBEEF5;
$color-border-4: #F2F6FC;
// 背景
$color-bg: #f8f8f9;
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.8 KiB

+13
View File
@@ -0,0 +1,13 @@
<svg viewBox="0 0 60 54" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<desc>D2Admin</desc>
<defs></defs>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="logo-no-shadow" transform="translate(-3.000000, -3.000000)">
<path d="M44.2833805,33.4299717 L6.05798302,56.3652102 C4.16366196,57.5018028 1.70662094,56.8875426 0.570028297,54.9932215 C0.197031333,54.3715599 8.87839274e-17,53.6602143 0,52.9352385 L-4.4408921e-16,7.06476152 C-7.1463071e-16,4.85562252 1.790861,3.06476152 4,3.06476152 C4.72497578,3.06476152 5.43632142,3.26179285 6.05798302,3.63478981 L44.2833805,26.5700283 C46.1777016,27.7066209 46.7919618,30.163662 45.6553692,32.057983 C45.3175701,32.6209814 44.8463789,33.0921727 44.2833805,33.4299717 Z" id="Triangle-Copy" fill="#35495E" transform="translate(25.000000, 30.000000) rotate(-180.000000) translate(-25.000000, -30.000000) "></path>
<path d="M60.2833805,33.4299717 L22.057983,56.3652102 C20.163662,57.5018028 17.7066209,56.8875426 16.5700283,54.9932215 C16.1970313,54.3715599 16,53.6602143 16,52.9352385 L16,7.06476152 C16,4.85562252 17.790861,3.06476152 20,3.06476152 C20.7249758,3.06476152 21.4363214,3.26179285 22.057983,3.63478981 L60.2833805,26.5700283 C62.1777016,27.7066209 62.7919618,30.163662 61.6553692,32.057983 C61.3175701,32.6209814 60.8463789,33.0921727 60.2833805,33.4299717 Z" id="Triangle" fill="#409EFF"></path>
<path d="M42.4688663,31.7973091 L24.0289915,42.8612339 C23.081831,43.4295303 21.8533105,43.1224001 21.2850141,42.1752396 C21.0985157,41.8644088 21,41.508736 21,41.1462481 L21,19.0183984 C21,17.9138289 21.8954305,17.0183984 23,17.0183984 C23.3624879,17.0183984 23.7181607,17.116914 24.0289915,17.3034125 L42.4688663,28.3673374 C43.4160268,28.9356337 43.7231569,30.1641542 43.1548606,31.1113147 C42.9859611,31.3928139 42.7503655,31.6284096 42.4688663,31.7973091 Z" id="Triangle-Copy" fill="#FFFFFF" transform="translate(31.000000, 30.082670) rotate(-180.000000) translate(-31.000000, -30.082670) "></path>
<path d="M37.5708451,30.8574929 L30.5144958,35.0913025 C30.0409155,35.3754507 29.4266552,35.2218856 29.1425071,34.7483054 C29.0492578,34.59289 29,34.4150536 29,34.2338096 L29,25.7661904 C29,25.2139056 29.4477153,24.7661904 30,24.7661904 C30.1812439,24.7661904 30.3590804,24.8154482 30.5144958,24.9086975 L37.5708451,29.1425071 C38.0444254,29.4266552 38.1979905,30.0409155 37.9138423,30.5144958 C37.8293925,30.6552454 37.7115947,30.7730432 37.5708451,30.8574929 Z" id="Triangle" fill="#409EFF"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

+7
View File
@@ -0,0 +1,7 @@
import Vue from 'vue'
const requireAll = requireContext => requireContext.keys().map(requireContext)
const req = require.context('./icons', false, /\.svg$/)
const iconMap = requireAll(req)
Vue.prototype.$IconSvg = iconMap.map(e => e.default.id.slice(3))
@@ -0,0 +1,27 @@
<template>
<div class="d2-container-card-bs">
<div v-if="$slots.header" class="d2-container-card-bs__header" ref="header">
<slot name="header"/>
</div>
<div class="d2-container-card-bs__body" ref="wrapper">
<div class="d2-container-card-bs__body-wrapper-inner">
<div class="d2-container-card-bs__body-card">
<slot/>
</div>
</div>
</div>
<div v-if="$slots.footer" class="d2-container-card-bs__footer" ref="footer">
<slot name="footer"/>
</div>
</div>
</template>
<script>
import bs from './mixins/bs'
export default {
name: 'd2-container-card-bs',
mixins: [
bs
]
}
</script>
@@ -0,0 +1,21 @@
<template>
<div class="d2-container-card">
<div v-if="$slots.header" class="d2-container-card__header" ref="header">
<slot name="header"/>
</div>
<div class="d2-container-card__body">
<div class="d2-container-card__body-card">
<slot/>
</div>
</div>
<div v-if="$slots.footer" class="d2-container-card__footer" ref="footer">
<slot name="footer"/>
</div>
</div>
</template>
<script>
export default {
name: 'd2-container-card'
}
</script>
@@ -0,0 +1,25 @@
<template>
<div class="d2-container-full-bs">
<div v-if="$slots.header" class="d2-container-full-bs__header" ref="header">
<slot name="header"/>
</div>
<div class="d2-container-full-bs__body" ref="wrapper">
<div class="d2-container-full-bs__body-wrapper-inner">
<slot/>
</div>
</div>
<div v-if="$slots.footer" class="d2-container-full-bs__footer" ref="footer">
<slot name="footer"/>
</div>
</div>
</template>
<script>
import bs from './mixins/bs'
export default {
name: 'd2-container-card-bs',
mixins: [
bs
]
}
</script>
@@ -0,0 +1,19 @@
<template>
<div class="d2-container-full">
<div v-if="$slots.header" class="d2-container-full__header" ref="header">
<slot name="header"/>
</div>
<div class="d2-container-full__body">
<slot/>
</div>
<div v-if="$slots.footer" class="d2-container-full__footer" ref="footer">
<slot name="footer"/>
</div>
</div>
</template>
<script>
export default {
name: 'd2-container-full'
}
</script>
@@ -0,0 +1,23 @@
<template>
<div class="d2-container-ghost-bs">
<div v-if="$slots.header" class="d2-container-ghost-bs__header" ref="header">
<slot name="header"/>
</div>
<div class="d2-container-ghost-bs__body" ref="wrapper">
<slot/>
</div>
<div v-if="$slots.footer" class="d2-container-ghost-bs__footer" ref="footer">
<slot name="footer"/>
</div>
</div>
</template>
<script>
import bs from './mixins/bs'
export default {
name: 'd2-container-card-bs',
mixins: [
bs
]
}
</script>
@@ -0,0 +1,13 @@
<template>
<div class="d2-container-ghost">
<div v-if="$slots.header" class="d2-container-ghost__header" ref="header">
<slot name="header"/>
</div>
<div class="d2-container-ghost__body">
<slot/>
</div>
<div v-if="$slots.footer" class="d2-container-ghost__footer" ref="footer">
<slot name="footer"/>
</div>
</div>
</template>
@@ -0,0 +1,41 @@
import BScroll from 'better-scroll'
export default {
props: {
betterScrollOptions: {
type: Object,
required: false,
default: () => ({})
}
},
data () {
return {
BS: null
}
},
mounted () {
this.scrollInit()
},
beforeDestroy () {
this.scrollDestroy()
},
methods: {
scrollInit () {
this.BS = new BScroll(this.$refs.wrapper, Object.assign({
mouseWheel: true,
scrollbar: {
fade: true,
interactive: false
}
}, this.betterScrollOptions))
},
scrollDestroy () {
// https://github.com/d2-projects/d2-admin/issues/75
try {
this.BS.destroy()
} catch (e) {
delete this.BS
this.BS = null
}
}
}
}
+75
View File
@@ -0,0 +1,75 @@
<template>
<div class="container-component" ref="container">
<!-- [card] 卡片容器 -->
<d2-container-card v-if="type === 'card' && !betterScroll">
<slot v-if="$slots.header" name="header" slot="header"/>
<slot/>
<slot v-if="$slots.footer" name="footer" slot="footer"/>
</d2-container-card>
<!-- [card] 卡片容器 滚动优化 -->
<d2-container-card-bs v-bind="$attrs" v-if="type === 'card' && betterScroll">
<slot v-if="$slots.header" name="header" slot="header"/>
<slot/>
<slot v-if="$slots.footer" name="footer" slot="footer"/>
</d2-container-card-bs>
<!-- [ghost] 隐形容器 -->
<d2-container-ghost v-if="type === 'ghost' && !betterScroll">
<slot v-if="$slots.header" name="header" slot="header"/>
<slot/>
<slot v-if="$slots.footer" name="footer" slot="footer"/>
</d2-container-ghost>
<!-- [ghost] 隐形容器 滚动优化 -->
<d2-container-ghost-bs v-bind="$attrs" v-if="type === 'ghost' && betterScroll">
<slot v-if="$slots.header" name="header" slot="header"/>
<slot/>
<slot v-if="$slots.footer" name="footer" slot="footer"/>
</d2-container-ghost-bs>
<!-- [container-full] 填充 -->
<d2-container-full v-if="type === 'full' && !betterScroll">
<slot v-if="$slots.header" name="header" slot="header"/>
<slot/>
<slot v-if="$slots.footer" name="footer" slot="footer"/>
</d2-container-full>
<!-- [container-full-bs] 填充 滚动优化 -->
<d2-container-full-bs v-bind="$attrs" v-if="type === 'full' && betterScroll">
<slot v-if="$slots.header" name="header" slot="header"/>
<slot/>
<slot v-if="$slots.footer" name="footer" slot="footer"/>
</d2-container-full-bs>
</div>
</template>
<script>
// 组件
import d2ContainerFull from './components/d2-container-full.vue'
import d2ContainerFullBs from './components/d2-container-full-bs.vue'
import d2ContainerGhost from './components/d2-container-ghost.vue'
import d2ContainerGhostBs from './components/d2-container-ghost-bs.vue'
import d2ContainerCard from './components/d2-container-card.vue'
import d2ContainerCardBs from './components/d2-container-card-bs.vue'
export default {
name: 'd2-container',
components: {
'd2-container-full': d2ContainerFull,
'd2-container-full-bs': d2ContainerFullBs,
'd2-container-ghost': d2ContainerGhost,
'd2-container-ghost-bs': d2ContainerGhostBs,
'd2-container-card': d2ContainerCard,
'd2-container-card-bs': d2ContainerCardBs
},
props: {
// 容器样式
type: {
type: String,
required: false,
default: 'full'
},
// 滚动优化
betterScroll: {
type: Boolean,
required: false,
default: false
}
}
}
</script>
+22
View File
@@ -0,0 +1,22 @@
<template>
<svg aria-hidden="true">
<use :xlink:href="icon"></use>
</svg>
</template>
<script>
export default {
name: 'd2-icon-svg',
props: {
name: {
type: String,
required: true
}
},
computed: {
icon () {
return `#d2-${this.name}`
}
}
}
</script>
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 434 KiB

+17
View File
@@ -0,0 +1,17 @@
<template>
<i class="fa" :class="`fa-${name}`" aria-hidden="true"></i>
</template>
<script>
import './font-awesome-4.7.0/css/font-awesome.min.css'
export default {
name: 'd2-icon',
props: {
name: {
type: String,
required: false,
default: 'font-awesome'
}
}
}
</script>
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

+56
View File
@@ -0,0 +1,56 @@
<template>
<div class="d2-page-cover">
<div class="d2-page-cover__logo">
<slot/>
</div>
<p class="d2-page-cover__title">{{title}}</p>
<p class="d2-page-cover__sub-title d2-mt-0">{{subTitle}}</p>
<slot name="footer"/>
<a target="blank" href="https://github.com/d2-projects/d2-admin">
<img
style="position: absolute; top: 0; right: 0; border: 0; width: 150px;"
src="./image/darkblue@2x.png"
alt="Fork me on GitHub">
</a>
</div>
</template>
<script>
export default {
props: {
title: {
type: String,
required: false,
default: 'Title'
},
subTitle: {
type: String,
required: false,
default: 'subTitle'
}
}
}
</script>
<style lang="scss" scoped>
@import '~@/assets/style/public.scss';
.d2-page-cover {
@extend %full;
@extend %unable-select;
display: flex;
flex-flow: column nowrap;
justify-content: center;
align-items: center;
.d2-page-cover__logo {
img {
width: 200px;
}
}
.d2-page-cover__title {
color: $color-text-main;
}
.d2-page-cover__sub-title {
color: $color-text-sub;
}
}
</style>
+9
View File
@@ -0,0 +1,9 @@
import Vue from 'vue'
import d2Container from './d2-container'
// 注意 有些组件使用异步加载会有影响
Vue.component('d2-container', d2Container)
Vue.component('d2-page-cover', () => import('./d2-page-cover'))
Vue.component('d2-icon', () => import('./d2-icon'))
Vue.component('d2-icon-svg', () => import('./d2-icon-svg/index.vue'))
+17
View File
@@ -0,0 +1,17 @@
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import cn from './lang/cn'
import ja from './lang/ja'
import en from './lang/en'
Vue.use(VueI18n)
export default new VueI18n({
locale: 'cn',
messages: {
cn,
ja,
en
}
})
+7
View File
@@ -0,0 +1,7 @@
export default {
pub: {
pageHeader: {
demo: '示例'
}
}
}
+7
View File
@@ -0,0 +1,7 @@
export default {
pub: {
pageHeader: {
demo: 'Demo'
}
}
}
+7
View File
@@ -0,0 +1,7 @@
export default {
pub: {
pageHeader: {
demo: 'サンプル'
}
}
}
@@ -0,0 +1,27 @@
<template>
<el-menu-item :index="menu.path || uniqueId">
<i v-if="menu.icon" :class="`fa fa-${menu.icon}`"></i>
<d2-icon-svg v-else-if="menu.iconSvg" :name="menu.iconSvg"/>
<i v-else class="fa fa-file-o"></i>
<span slot="title">{{menu.title || '未命名菜单'}}</span>
</el-menu-item>
</template>
<script>
import { uniqueId } from 'lodash'
export default {
name: 'd2-layout-header-aside-menu-item',
props: {
menu: {
type: Object,
required: false,
default: () => {}
}
},
data () {
return {
uniqueId: uniqueId('d2-menu-empty-')
}
}
}
</script>
@@ -0,0 +1,39 @@
<template>
<el-submenu :index="menu.path || uniqueId">
<template slot="title">
<i v-if="menu.icon" :class="`fa fa-${menu.icon}`"></i>
<d2-icon-svg v-else-if="menu.iconSvg" :name="menu.iconSvg"/>
<i v-else class="fa fa-folder-o"></i>
<span slot="title">{{menu.title}}</span>
</template>
<template v-for="(child, childIndex) in menu.children">
<d2-layout-header-aside-menu-item v-if="child.children === undefined" :menu="child" :key="childIndex"/>
<d2-layout-header-aside-menu-sub v-else :menu="child" :key="childIndex"/>
</template>
</el-submenu>
</template>
<script>
import { uniqueId } from 'lodash'
// 组件
import d2LayoutMainMenuItem from '../menu-item'
export default {
name: 'd2-layout-header-aside-menu-sub',
components: {
'd2-layout-header-aside-menu-item': d2LayoutMainMenuItem
},
props: {
menu: {
type: Object,
required: false,
default: () => {}
}
},
data () {
return {
uniqueId: uniqueId('d2-menu-empty-')
}
}
}
</script>
@@ -0,0 +1,61 @@
<template>
<div
class="d2-contentmenu-list"
@click="rowClick">
<div
v-for="item in menulist"
:key="item.value"
:data-value="item.value"
class="d2-contentmenu-item"
flex="cross:center main:center">
<d2-icon
v-if="item.icon"
:name="item.icon"/>
<div
class="d2-contentmenu-item-title"
flex-box="1">
{{item.title}}
</div>
</div>
</div>
</template>
<script>
export default {
name: 'd2-contextmenu-list',
props: {
menulist: {
type: Array,
default: () => []
}
},
methods: {
rowClick (event) {
let target = event.target
while (!target.dataset.value) {
target = target.parentNode
}
this.$emit('rowClick', target.dataset.value)
}
}
}
</script>
<style lang="scss">
.d2-contentmenu-list {
.d2-contentmenu-item {
padding: 8px 20px 8px 15px;
margin: 0;
font-size: 14px;
color: #606266;
cursor: pointer;
&:hover {
background: #ecf5ff;
color: #66b1ff;
}
.d2-contentmenu-item-title {
margin-left: 10px;
}
}
}
</style>
@@ -0,0 +1,71 @@
<template>
<div
class="d2-contextmenu"
v-show="flag"
:style="style">
<slot/>
</div>
</template>
<script>
export default {
name: 'd2-contextmenu',
props: {
visible: {
type: Boolean,
default: false
},
x: {
type: Number,
default: 0
},
y: {
type: Number,
default: 0
}
},
computed: {
flag: {
get () {
if (this.visible) {
// 注册全局监听事件 [ 目前只考虑鼠标解除触发 ]
window.addEventListener('mousedown', this.watchContextmenu)
}
return this.visible
},
set (newVal) {
this.$emit('update:visible', newVal)
}
},
style () {
return {
left: this.x + 'px',
top: this.y + 'px',
display: this.visible ? 'block' : 'none '
}
}
},
methods: {
watchContextmenu (event) {
if (!this.$el.contains(event.target) || event.button !== 0) this.flag = false
window.removeEventListener('mousedown', this.watchContextmenu)
}
},
mounted () {
// 将菜单放置到body下
document.querySelector('body').appendChild(this.$el)
}
}
</script>
<style>
.d2-contextmenu {
position: absolute;
padding: 5px 0;
z-index: 2018;
background: #FFF;
border: 1px solid #cfd7e5;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
}
</style>
@@ -0,0 +1,30 @@
<template>
<div
class="d2-error-log-list__expand"
:class="className">
<p class="d2-error-log-list__expand-title">{{title}}</p>
<p class="d2-error-log-list__expand-value">{{value === '' ? '无数据' : value}}</p>
<slot/>
</div>
</template>
<script>
export default {
props: {
type: {
default: 'log'
},
title: {
default: ''
},
value: {
default: ''
}
},
computed: {
className () {
return this.type === 'log' ? 'd2-error-log-list__expand--log' : 'd2-error-log-list__expand--error'
}
}
}
</script>
@@ -0,0 +1,195 @@
<template>
<el-table
:data="logReverse"
border
stripe
style="width: 100%"
size="mini">
<el-table-column type="expand">
<div slot-scope="props" class="d2-error-log-list__expand-group">
<expand-item
:type="props.row.type"
title="类型"
:value="props.row.type === 'log' ? '日志' : '异常'"/>
<expand-item
:type="props.row.type"
title="内容"
:value="props.row.info"/>
<expand-item
v-if="props.row.type === 'error'"
type="error"
title="报错组件"
:value="get(props.row.vm, '$vnode.tag', '')"/>
<expand-item
v-if="props.row.type === 'error'"
type="error"
title="错误名称"
:value="get(props.row.err, 'name', '')"/>
<expand-item
v-if="props.row.type === 'error'"
type="error"
title="错误信息"
:value="get(props.row.err, 'message', '')"/>
<expand-item
v-if="props.row.type === 'error'"
type="error"
title="错误堆栈"
value="见下">
<div style="overflow: auto;">
<pre>{{stackBeautify(props.row.err)}}</pre>
</div>
</expand-item>
<expand-item
:type="props.row.type"
title="用户名"
:value="get(props.row.user, 'name', '')"/>
<expand-item
:type="props.row.type"
title="uuid"
:value="props.row.uuid"/>
<expand-item
:type="props.row.type"
title="token"
:value="props.row.token"/>
<expand-item
:type="props.row.type"
title="页面地址"
:value="props.row.url"/>
<expand-item
:type="props.row.type"
title="时间"
:value="props.row.time"/>
</div>
</el-table-column>
<el-table-column
prop="type"
label="类型"
width="80px"
align="center"
:filters="[
{ text: '日志', value: 'log' },
{ text: '异常', value: 'error' }
]"
:filter-multiple="false"
:filter-method="filterType"
filter-placement="bottom">
<template slot-scope="scope">
<el-tag
v-if="scope.row.type === 'error'"
size="mini"
type="danger">
<d2-icon name="bug"/> Bug
</el-tag>
<el-tag
v-else
size="mini"
type="info">
<d2-icon name="dot-circle-o"/> Log
</el-tag>
</template>
</el-table-column>
<el-table-column
label="地址"
prop="url"
width="140px"
:show-overflow-tooltip="true">
</el-table-column>
<el-table-column
label="内容"
prop="info"
:show-overflow-tooltip="true">
</el-table-column>
<el-table-column
label="错误类型"
width="140px"
:show-overflow-tooltip="true">
<template
slot-scope="scope">
{{get(scope.row.err, 'name', '')}}
</template>
</el-table-column>
<el-table-column
label="错误信息"
width="300px">
<template
slot-scope="scope">
{{get(scope.row.err, 'message', '')}}
</template>
</el-table-column>
</el-table>
</template>
<script>
import { mapState } from 'vuex'
import { get } from 'lodash'
import ExpandItem from './components/ExpandItem'
export default {
name: 'd2-error-log-list',
components: {
ExpandItem
},
computed: {
...mapState('d2admin', {
logList: state => state.log.list
}),
logReverse () {
// 直接 reverse 的话有点问题
const res = []
const loglength = this.logList.length
this.logList.forEach((log, index) => {
res.push(this.logList[loglength - 1 - index])
})
return res
}
},
methods: {
get,
filterType (value, row) {
return row.type === value
},
stackBeautify (err) {
if (!err) {
return ''
}
return err.stack
}
}
}
</script>
<style lang="scss">
@import '~@/assets/style/public.scss';
.d2-error-log-list__expand-group {
.d2-error-log-list__expand {
padding-left: 20px;
margin-bottom: 10px;
&:last-child {
margin-bottom: 0px;
}
.d2-error-log-list__expand-title {
font-size: 16px;
font-weight: bold;
margin-top: 0px;
margin-bottom: 10px;
}
.d2-error-log-list__expand-value {
font-size: 12px;
margin-top: 0px;
margin-bottom: 0px;
}
}
.d2-error-log-list__expand--log {
border-left: 4px solid $color-info;
}
.d2-error-log-list__expand--error {
border-left: 4px solid $color-danger;
}
}
</style>
@@ -0,0 +1,82 @@
<template>
<div>
<el-tooltip
effect="dark"
:content="tooltipContent"
placement="bottom">
<el-button
class="d2-ml-0 d2-mr btn-text can-hover"
type="text"
@click="handleClick">
<el-badge
v-if="logLength > 0"
:max="99"
:value="logLengthError"
:is-dot="logLengthError === 0">
<d2-icon
:name="logLengthError === 0 ? 'dot-circle-o' : 'bug'"
style="font-size: 20px"/>
</el-badge>
<d2-icon
v-else
name="dot-circle-o"
style="font-size: 20px"/>
</el-button>
</el-tooltip>
<el-dialog
:title="tooltipContent"
:fullscreen="true"
:visible.sync="dialogVisible"
:append-to-body="true">
<div class="d2-mb-10">
<el-button type="danger" size="mini" @click="handleLogClean">
<d2-icon name="trash-o"/>
清空
</el-button>
</div>
<d2-error-log-list/>
</el-dialog>
</div>
</template>
<script>
import { mapGetters, mapMutations } from 'vuex'
import D2ErrorLogList from './components/list'
export default {
components: {
D2ErrorLogList
},
data () {
return {
dialogVisible: false
}
},
computed: {
...mapGetters('d2admin', {
logLength: 'log/length',
logLengthError: 'log/lengthError'
}),
tooltipContent () {
return this.logLength === 0
? '没有日志或异常'
: `${this.logLength} 条日志${this.logLengthError > 0
? ` | 包含 ${this.logLengthError} 个异常`
: ''}`
}
},
methods: {
...mapMutations('d2admin/log', [
'clean'
]),
handleClick () {
if (this.logLength > 0) {
this.dialogVisible = true
}
},
handleLogClean () {
this.dialogVisible = false
this.clean()
}
}
}
</script>
@@ -0,0 +1,27 @@
<template>
<el-tooltip
effect="dark"
:content="active ? '退出全屏' : '全屏'"
placement="bottom">
<el-button class="d2-mr btn-text can-hover" type="text" @click="toggle">
<d2-icon v-if="active" name="compress"/>
<d2-icon v-else name="arrows-alt" style="font-size: 16px"/>
</el-button>
</el-tooltip>
</template>
<script>
import { mapState, mapActions } from 'vuex'
export default {
computed: {
...mapState('d2admin/fullscreen', [
'active'
])
},
methods: {
...mapActions('d2admin/fullscreen', [
'toggle'
])
}
}
</script>
@@ -0,0 +1,15 @@
<template>
<el-button class="d2-mr btn-text can-hover" type="text" @click="handleClick">
<d2-icon name="search" style="font-size: 18px;"/>
</el-button>
</template>
<script>
export default {
methods: {
handleClick () {
this.$emit('click')
}
}
}
</script>
@@ -0,0 +1,67 @@
<template>
<el-dropdown placement="bottom" size="small" @command="handleChange">
<el-button class="d2-mr btn-text can-hover" type="text">
<d2-icon name="font" style="font-size: 16px;"/>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="default">
<d2-icon :name="iconName('default')" class="d2-mr-5"/>默认
</el-dropdown-item>
<el-dropdown-item command="medium">
<d2-icon :name="iconName('medium')" class="d2-mr-5"/>中
</el-dropdown-item>
<el-dropdown-item command="small">
<d2-icon :name="iconName('small')" class="d2-mr-5"/>小
</el-dropdown-item>
<el-dropdown-item command="mini">
<d2-icon :name="iconName('mini')" class="d2-mr-5"/>最小
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex'
export default {
name: 'd2-header-size',
computed: {
...mapState('d2admin/size', [
'value'
])
},
watch: {
// 注意 这里是关键
// 因为需要访问 this.$ELEMENT 所以只能在这里使用这种方式
value: {
handler (val) {
if (this.$ELEMENT.size !== val) {
// 设置 element 全局尺寸
this.$ELEMENT.size = val
// 清空缓存设置
this.pageKeepAliveClean()
// 刷新此页面
const { path, query } = this.$route
this.$router.replace({
path: '/redirect/' + JSON.stringify({ path, query })
})
}
},
immediate: true
}
},
methods: {
...mapMutations({
pageKeepAliveClean: 'd2admin/page/keepAliveClean'
}),
...mapActions({
sizeSet: 'd2admin/size/set'
}),
handleChange (value) {
this.sizeSet(value)
},
iconName (name) {
return name === this.value ? 'dot-circle-o' : 'circle-o'
}
}
}
</script>
@@ -0,0 +1,58 @@
<template>
<el-table :data="list" v-bind="table">
<el-table-column prop="title" align="center" width="160"/>
<el-table-column label="预览" width="120">
<div
slot-scope="scope"
class="theme-preview"
:style="{'backgroundImage': `url(${$baseUrl}${scope.row.preview})`}">
</div>
</el-table-column>
<el-table-column prop="address" align="center">
<template slot-scope="scope">
<el-button v-if="activeName === scope.row.name" type="success" icon="el-icon-check" round>已激活</el-button>
<el-button v-else round @click="handleSelectTheme(scope.row.name)">使用</el-button>
</template>
</el-table-column>
</el-table>
</template>
<script>
import { mapState, mapActions } from 'vuex'
export default {
name: 'd2-theme-list',
data () {
return {
table: {
showHeader: false,
border: true
}
}
},
computed: {
...mapState('d2admin/theme', [
'list',
'activeName'
])
},
methods: {
...mapActions('d2admin/theme', [
'set'
]),
handleSelectTheme (name) {
this.set(name)
}
}
}
</script>
<style lang="scss" scoped>
@import '~@/assets/style/public.scss';
.theme-preview {
height: 50px;
width: 100px;
border-radius: 4px;
background-size: cover;
border: 1px solid $color-border-1;
}
</style>
@@ -0,0 +1,26 @@
<template>
<div>
<el-tooltip effect="dark" content="主题" placement="bottom">
<el-button class="d2-ml-0 d2-mr btn-text can-hover" type="text" @click="dialogVisible = true">
<d2-icon name="diamond" style="font-size: 16px"/>
</el-button>
</el-tooltip>
<el-dialog title="主题" width="600px" :visible.sync="dialogVisible" :append-to-body="true">
<d2-theme-list style="margin-top: -25px;"/>
</el-dialog>
</div>
</template>
<script>
import themeList from './components/d2-theme-list'
export default {
components: {
'd2-theme-list': themeList
},
data () {
return {
dialogVisible: false
}
}
}
</script>
@@ -0,0 +1,36 @@
<template>
<el-dropdown size="small" class="d2-mr">
<span class="btn-text">你好 {{info.name}}</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item @click.native="logOff">
<d2-icon name="power-off" class="d2-mr-5"/>
注销
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
<script>
import { mapState, mapActions } from 'vuex'
export default {
computed: {
...mapState('d2admin/user', [
'info'
])
},
methods: {
...mapActions('d2admin/account', [
'logout'
]),
/**
* @description 登出
*/
logOff () {
this.logout({
vm: this,
confirm: true
})
}
}
}
</script>

Some files were not shown because too many files have changed in this diff Show More