upload web
|
@ -10,8 +10,9 @@
|
|||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
*.iml
|
||||
.idea
|
||||
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
||||
*.iml
|
||||
.idea
|
||||
/web/node_modules
|
|
@ -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.
|
|
@ -0,0 +1,24 @@
|
|||
[D2Admin](https://github.com/d2-projects/d2-admin) is a fully open source and free enterprise back-end product front-end integration solution, using the latest front-end technology stack, javascript files loading of local first screen less than 60kb, has prepared most of the project preparations, and with a lot of sample code to help the management system agile development.
|
||||
|
||||
[中文](https://github.com/d2-projects/d2-admin-start-kit/blob/master/README.zh.md) | **English**
|
||||
|
||||
## Preview
|
||||
|
||||
![Deploy preview](https://github.com/d2-projects/d2-admin-start-kit/workflows/Deploy%20preview/badge.svg)
|
||||
[![Netlify Status](https://api.netlify.com/api/v1/badges/08ff8c93-f0a8-497a-a081-440b31fb3aa4/deploy-status)](https://app.netlify.com/sites/d2-admin-start-kit/deploys)
|
||||
|
||||
The following access addresses are built and deployed by the latest master branch code at the same time. The access effect is completely consistent. Please select the appropriate access link according to your own network situation.
|
||||
|
||||
| server | link | server |
|
||||
| --- | --- | --- |
|
||||
| d2.pub | [d2.pub/d2-admin-start-kit/preview](https://d2.pub/d2-admin-start-kit/preview) | China server |
|
||||
| cdn.d2.pub | [cdn.d2.pub/d2-admin-start-kit/preview](https://cdn.d2.pub/d2-admin-start-kit/preview) | qiniu CDN |
|
||||
| github | [d2-projects.github.io/d2-admin-start-kit](https://d2-projects.github.io/d2-admin-start-kit) | GitHub pages |
|
||||
| netlify | [d2-admin-start-kit.netlify.com](https://d2-admin-start-kit.netlify.com) | Netlify CDN |
|
||||
|
||||
## Other synchronous repositories
|
||||
|
||||
| type | link |
|
||||
| --- | --- |
|
||||
| gitee | [https://gitee.com/d2-projects/d2-admin](https://gitee.com/d2-projects/d2-admin) |
|
||||
| coding | [https://d2-projects.coding.net/p/d2-projects/d/d2-admin/git](https://d2-projects.coding.net/p/d2-projects/d/d2-admin/git) |
|
|
@ -0,0 +1,89 @@
|
|||
[D2Admin](https://github.com/d2-projects/d2-admin) 是一个完全 **开源免费** 的企业中后台产品前端集成方案,使用最新的前端技术栈,小于 60kb 的本地首屏 js 加载,已经做好大部分项目前期准备工作,并且带有大量示例代码,助力管理系统敏捷开发。
|
||||
|
||||
**中文** | [English](https://github.com/d2-projects/d2-admin-start-kit)
|
||||
|
||||
## 预览
|
||||
|
||||
![Deploy preview](https://github.com/d2-projects/d2-admin-start-kit/workflows/Deploy%20preview/badge.svg)
|
||||
[![Netlify Status](https://api.netlify.com/api/v1/badges/08ff8c93-f0a8-497a-a081-440b31fb3aa4/deploy-status)](https://app.netlify.com/sites/d2-admin-start-kit/deploys)
|
||||
|
||||
下列访问地址均由最新的 master 分支代码同时构建部署,访问效果完全一致,请根据自身网络情况选择合适的访问链接。
|
||||
|
||||
| 位置 | 链接 | 部署位置 |
|
||||
| --- | --- | --- |
|
||||
| d2.pub | [preview](https://d2.pub/d2-admin-start-kit/preview) | 中国服务器 |
|
||||
| cdn.d2.pub | [preview](https://cdn.d2.pub/d2-admin-start-kit/preview) | 七牛云 CDN |
|
||||
| github | [preview](https://d2-projects.github.io/d2-admin-start-kit) | GitHub pages |
|
||||
| netlify | [preview](https://d2-admin-start-kit.netlify.com) | Netlify CDN |
|
||||
|
||||
## 其它同步仓库
|
||||
|
||||
| 位置 | 链接 |
|
||||
| --- | --- |
|
||||
| 码云 | [https://gitee.com/d2-projects/d2-admin-start-kit](https://gitee.com/d2-projects/d2-admin-start-kit) |
|
||||
| coding | [https://d2-projects.coding.net/p/d2-projects/d/d2-admin-start-kit/git](https://d2-projects.coding.net/p/d2-projects/d/d2-admin-start-kit/git) |
|
||||
|
||||
# 以下内容为开发实践
|
||||
## node && npm version
|
||||
nodejs: v16.18.0
|
||||
npm: 8.19.2
|
||||
|
||||
## install package
|
||||
npm config set registry https://registry.npmmirror.com
|
||||
sudo npm install yarn -g
|
||||
yarn install
|
||||
|
||||
## 文档地址
|
||||
https://d2.pub/doc/d2-admin/
|
||||
|
||||
### vue-cli-service serve和npm run serve的区别
|
||||
```text
|
||||
在原package.json中:
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve --open",
|
||||
"dev": "npm run serve",
|
||||
"build": "vue-cli-service build",
|
||||
"build:preview": "NODE_OPTIONS=--max_old_space_size=4096 vue-cli-service build --mode preview",
|
||||
"lint": "vue-cli-service lint --fix",
|
||||
"test:unit": "vue-cli-service test:unit"
|
||||
}
|
||||
vue-cli-service serve和npm run serve在功能上没有区别。
|
||||
vue-cli-service serve是直接调用Vue CLI服务工具来启动本地开发服务器,它会监听源码变化并自动热更新浏览器内容,通常用于开发环境
|
||||
npm run serve是npm包管理器提供的命令,用来执行package.json中指定的脚本,当执行npm run serve时,npm会查找并运行scripts部分定义的"serve"命令,
|
||||
因此实际上它也是调用vue-cli-service命令。
|
||||
```
|
||||
|
||||
### vue-cli-service不同环境配置
|
||||
```text
|
||||
在 Vue CLI 项目中,环境变量配置是通过不同的 .env 文件实现的。这些文件允许你在不同环境下设置不同的变量值,例如开发环境、测试环境和生产环境。
|
||||
Vue CLI 使用 dotenv-webpack 插件处理环境变量,其中以 VUE_APP_ 开头的变量会被 webpack 的 DefinePlugin 静态嵌入到客户端侧的包中,这样你就可以在代码中直接使用它们,并且在构建时会根据当前环境替换为对应的值。
|
||||
以下是如何配置不同环境变量的基本结构:
|
||||
默认环境:所有环境都可读取的基础变量可以放在 .env 文件中。
|
||||
开发环境:针对开发环境(npm run dev)的变量,放在 .env.development 文件中。
|
||||
生产环境:针对生产环境(npm run build)的变量,放在 .env.production 文件中。
|
||||
|
||||
当你执行 vue-cli-service build 时,默认会使用生产模式(.env.production),如果你需要构建特定模式下的项目,可以通过 --mode 参数指定:
|
||||
vue-cli-service build --mode staging
|
||||
在这种情况下,你需要有一个名为 .env.staging 的文件来提供相应环境的变量配置。
|
||||
```
|
||||
|
||||
### 在vuex中,mapActions的作用
|
||||
```text
|
||||
在 Vuex 中,mapActions 是一个辅助函数,它来自于 vuex 组件绑定插件(VueX 提供的)。这个函数的作用是将 Vuex store 中定义的 actions 映射为
|
||||
Vue 组件的本地方法,使得在组件内部可以更方便地调用这些 action,而无需直接通过 this.$store.dispatch()。
|
||||
例如,在 Vuex store 中有以下 actions 定义:
|
||||
|
||||
具体参考'src/views/system/login/page.vue'中的:
|
||||
import { mapActions } from 'vuex'
|
||||
|
||||
// 使用 mapActions 将 store 的 actions 映射为本组件的方法
|
||||
...mapActions('d2admin/account', [
|
||||
'login'
|
||||
])
|
||||
|
||||
// 现在可以在组件内像调用普通方法一样调用它们
|
||||
// 相当于 this.$store.dispatch('login')
|
||||
this.login()
|
||||
```
|
||||
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
module.exports = {
|
||||
presets: [
|
||||
'@vue/cli-plugin-babel/preset'
|
||||
],
|
||||
// 允许两种编码引入方式共存,也就是 common 规范与 es6 规范的共存处理
|
||||
sourceType: 'unambiguous'
|
||||
}
|
|
@ -0,0 +1,165 @@
|
|||
<babeledit_project version="1.2">
|
||||
<!--
|
||||
|
||||
BabelEdit project file
|
||||
https://www.codeandweb.com/babeledit
|
||||
|
||||
This file contains meta data for all translations, but not the translation texts itself.
|
||||
They are stored in framework-specific message files (.json / .vue / .yaml / .properties)
|
||||
|
||||
-->
|
||||
<preset_collections/>
|
||||
<framework>vue-json</framework>
|
||||
<filename>d2-admin.babel</filename>
|
||||
<source_root_dir></source_root_dir>
|
||||
<folder_node>
|
||||
<name></name>
|
||||
<children>
|
||||
<concept_node>
|
||||
<name>_element</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
<description></description>
|
||||
<comment></comment>
|
||||
<default_text></default_text>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>ja-JP</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>zh-CHS</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>zh-CHT</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>_name</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
<description></description>
|
||||
<comment></comment>
|
||||
<default_text></default_text>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>ja-JP</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>zh-CHS</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>zh-CHT</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<folder_node>
|
||||
<name>page</name>
|
||||
<children>
|
||||
<folder_node>
|
||||
<name>demo</name>
|
||||
<children>
|
||||
<folder_node>
|
||||
<name>playground</name>
|
||||
<children>
|
||||
<folder_node>
|
||||
<name>locales</name>
|
||||
<children>
|
||||
<concept_node>
|
||||
<name>text</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
<description></description>
|
||||
<comment></comment>
|
||||
<default_text></default_text>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>ja-JP</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>zh-CHS</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>zh-CHT</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
</children>
|
||||
</folder_node>
|
||||
</children>
|
||||
</folder_node>
|
||||
</children>
|
||||
</folder_node>
|
||||
</children>
|
||||
</folder_node>
|
||||
</children>
|
||||
</folder_node>
|
||||
<isTemplateProject>false</isTemplateProject>
|
||||
<languages>
|
||||
<language>
|
||||
<code>en-US</code>
|
||||
<source_id></source_id>
|
||||
<source_file>src/locales/en.json</source_file>
|
||||
</language>
|
||||
<language>
|
||||
<code>ja-JP</code>
|
||||
<source_id></source_id>
|
||||
<source_file>src/locales/ja.json</source_file>
|
||||
</language>
|
||||
<language>
|
||||
<code>zh-CHS</code>
|
||||
<source_id></source_id>
|
||||
<source_file>src/locales/zh-chs.json</source_file>
|
||||
</language>
|
||||
<language>
|
||||
<code>zh-CHT</code>
|
||||
<source_id></source_id>
|
||||
<source_file>src/locales/zh-cht.json</source_file>
|
||||
</language>
|
||||
</languages>
|
||||
<translation_files>
|
||||
<translation_file>
|
||||
<file>src/locales/en.json</file>
|
||||
</translation_file>
|
||||
<translation_file>
|
||||
<file>src/locales/ja.json</file>
|
||||
</translation_file>
|
||||
<translation_file>
|
||||
<file>src/locales/zh-chs.json</file>
|
||||
</translation_file>
|
||||
<translation_file>
|
||||
<file>src/locales/zh-cht.json</file>
|
||||
</translation_file>
|
||||
</translation_files>
|
||||
<editor_configuration>
|
||||
<save_empty_translations>true</save_empty_translations>
|
||||
<copy_templates>
|
||||
<copy_template>$t('%1')</copy_template>
|
||||
<copy_template>{{ $t('%1') }}</copy_template>
|
||||
<copy_template>this.$t('%1')</copy_template>
|
||||
</copy_templates>
|
||||
</editor_configuration>
|
||||
<primary_language>zh-CHS</primary_language>
|
||||
<configuration>
|
||||
<indent>tab</indent>
|
||||
<format>namespaced-json</format>
|
||||
</configuration>
|
||||
</babeledit_project>
|
|
@ -0,0 +1,24 @@
|
|||
// If you want to re enable these configurations, please make sure that the version number of each package is the latest
|
||||
|
||||
module.exports = [
|
||||
// { name: 'vue', library: 'Vue', js: 'https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.min.js', css: '' },
|
||||
// { name: 'vue-i18n', library: 'VueI18n', js: 'https://cdn.jsdelivr.net/npm/vue-i18n@8.15.1/dist/vue-i18n.min.js', css: '' },
|
||||
// { name: 'vue-router', library: 'VueRouter', js: 'https://cdn.jsdelivr.net/npm/vue-router@3.1.3/dist/vue-router.min.js', css: '' },
|
||||
// { name: 'vuex', library: 'Vuex', js: 'https://cdn.jsdelivr.net/npm/vuex@3.1.2/dist/vuex.min.js', css: '' },
|
||||
// { name: 'axios', library: 'axios', js: 'https://cdn.jsdelivr.net/npm/axios@0.19.0/dist/axios.min.js', css: '' },
|
||||
// { name: 'better-scroll', library: 'BScroll', js: 'https://cdn.jsdelivr.net/npm/better-scroll@1.15.2/dist/bscroll.min.js', css: '' },
|
||||
// { name: 'axios-mock-adapter', library: 'AxiosMockAdapter', js: 'https://cdn.jsdelivr.net/npm/axios-mock-adapter@1.18.1/dist/axios-mock-adapter.min.js', css: '' },
|
||||
// { name: 'element-ui', library: 'ELEMENT', js: 'https://cdn.jsdelivr.net/npm/element-ui@2.15.6/lib/index.js', css: 'https://cdn.jsdelivr.net/npm/element-ui@2.15.6/lib/theme-chalk/index.css' },
|
||||
// { name: 'lodash', library: '_', js: 'https://cdn.jsdelivr.net/npm/lodash@4.17.15/lodash.min.js', css: '' },
|
||||
// { name: 'ua-parser-js', library: 'UAParser', js: 'https://cdn.jsdelivr.net/npm/ua-parser-js@0.7.20/dist/ua-parser.min.js', css: '' },
|
||||
// { name: 'js-cookie', library: 'Cookies', js: 'https://cdn.jsdelivr.net/npm/js-cookie@2.2.1/src/js.cookie.min.js', css: '' },
|
||||
// { name: 'nprogress', library: 'NProgress', js: 'https://cdn.jsdelivr.net/npm/nprogress@0.2.0/nprogress.min.js', css: 'https://cdn.jsdelivr.net/npm/nprogress@0.2.0/nprogress.css' },
|
||||
// { name: 'dayjs', library: 'dayjs', js: 'https://cdn.jsdelivr.net/npm/dayjs@1.8.17/dayjs.min.js', css: '' },
|
||||
// { name: 'fuse.js', library: 'Fuse', js: 'https://cdn.jsdelivr.net/npm/fuse.js@5.2.3/dist/fuse.min.js', css: '' },
|
||||
// { name: 'hotkeys-js', library: 'hotkeys', js: 'https://cdn.jsdelivr.net/npm/hotkeys-js@3.7.3/dist/hotkeys.min.js', css: '' },
|
||||
// { name: 'qs', library: 'Qs', js: 'https://cdn.jsdelivr.net/npm/qs@6.9.1/dist/qs.js', css: '' },
|
||||
// { name: 'lowdb', library: 'low', js: 'https://cdn.jsdelivr.net/npm/lowdb@1.0.0/dist/low.min.js', css: '' },
|
||||
// { name: 'lowdb/adapters/LocalStorage', library: 'LocalStorage', js: 'https://cdn.jsdelivr.net/npm/lowdb@1.0.0/dist/LocalStorage.min.js', css: '' },
|
||||
// { name: 'screenfull', library: 'screenfull', js: 'https://cdn.jsdelivr.net/npm/screenfull@5.0.2/dist/screenfull.min.js', css: '' },
|
||||
// { name: 'sortablejs', library: 'Sortable', js: 'https://cdn.jsdelivr.net/npm/sortablejs@1.10.1/Sortable.min.js', css: '' }
|
||||
]
|
|
@ -0,0 +1,3 @@
|
|||
module.exports = {
|
||||
preset: '@vue/cli-plugin-unit-jest'
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2017",
|
||||
"allowSyntheticDefaultImports": false,
|
||||
"baseUrl": "./",
|
||||
"paths": {
|
||||
"@/*": ["src/*"]
|
||||
}
|
||||
},
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
{
|
||||
"name": "d2-admin",
|
||||
"version": "1.20.1",
|
||||
"scripts": {
|
||||
"dev": "vue-cli-service serve --open",
|
||||
"build:daily": "vue-cli-service build --mode daily",
|
||||
"build:stage": "vue-cli-service build --mode staging",
|
||||
"build:prod": "vue-cli-service build --mode production",
|
||||
"build:preview": "NODE_OPTIONS=--max_old_space_size=4096 vue-cli-service build --mode preview",
|
||||
"fix": "vue-cli-service lint --fix",
|
||||
"test:unit": "vue-cli-service test:unit"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^0.19.0",
|
||||
"axios-mock-adapter": "^1.18.1",
|
||||
"better-scroll": "^1.15.2",
|
||||
"core-js": "^3.4.3",
|
||||
"dayjs": "^1.8.17",
|
||||
"element-ui": "^2.15.6",
|
||||
"faker": "^4.1.0",
|
||||
"flex.css": "^1.1.7",
|
||||
"fuse.js": "^5.2.3",
|
||||
"hotkeys-js": "^3.7.3",
|
||||
"js-cookie": "^2.2.1",
|
||||
"lodash": "^4.17.19",
|
||||
"lowdb": "^1.0.0",
|
||||
"nprogress": "^0.2.0",
|
||||
"screenfull": "^5.0.2",
|
||||
"sortablejs": "^1.10.1",
|
||||
"ua-parser-js": "^0.7.20",
|
||||
"vue": "^2.6.11",
|
||||
"vue-i18n": "^8.15.1",
|
||||
"vue-router": "^3.1.3",
|
||||
"vuex": "^3.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@d2-projects/vue-filename-injector": "^1.1.0",
|
||||
"@kazupon/vue-i18n-loader": "^0.5.0",
|
||||
"@vue/cli-plugin-babel": "^4.1.0",
|
||||
"@vue/cli-plugin-eslint": "^4.1.0",
|
||||
"@vue/cli-plugin-router": "^4.1.0",
|
||||
"@vue/cli-plugin-unit-jest": "^4.1.0",
|
||||
"@vue/cli-plugin-vuex": "^4.1.0",
|
||||
"@vue/cli-service": "^4.1.0",
|
||||
"@vue/eslint-config-standard": "^5.1.2",
|
||||
"@vue/test-utils": "^1.0.2",
|
||||
"babel-eslint": "^10.0.3",
|
||||
"compression-webpack-plugin": "^3.0.1",
|
||||
"cz-conventional-changelog": "^3.2.0",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-plugin-import": "^2.20.2",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^4.2.1",
|
||||
"eslint-plugin-standard": "^4.0.1",
|
||||
"eslint-plugin-vue": "^6.2.2",
|
||||
"sass": "^1.23.7",
|
||||
"sass-loader": "^8.0.0",
|
||||
"svg-sprite-loader": "^4.1.6",
|
||||
"text-loader": "^0.0.1",
|
||||
"vue-cli-plugin-i18n": "^1.0.1",
|
||||
"vue-template-compiler": "^2.6.10",
|
||||
"webpack-bundle-analyzer": "^3.6.0",
|
||||
"webpack-theme-color-replacer": "^1.3.3"
|
||||
},
|
||||
"config": {
|
||||
"commitizen": {
|
||||
"path": "./node_modules/cz-conventional-changelog"
|
||||
}
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/d2-projects/d2-admin.git"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 66 KiB |
After Width: | Height: | Size: 6.3 KiB |
|
@ -0,0 +1,6 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="32" height="32" fill="white">
|
||||
<path opacity=".25" d="M16 0 A16 16 0 0 0 16 32 A16 16 0 0 0 16 0 M16 4 A12 12 0 0 1 16 28 A12 12 0 0 1 16 4"/>
|
||||
<path d="M16 0 A16 16 0 0 1 32 16 L28 16 A12 12 0 0 0 16 4z">
|
||||
<animateTransform attributeName="transform" type="rotate" from="0 16 16" to="360 16 16" dur="0.8s" repeatCount="indefinite" />
|
||||
</path>
|
||||
</svg>
|
After Width: | Height: | Size: 422 B |
After Width: | Height: | Size: 6.5 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 6.6 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 6.4 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 86 KiB |
After Width: | Height: | Size: 6.6 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 359 KiB |
After Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 48 KiB |
After Width: | Height: | Size: 6.2 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 20 KiB |
|
@ -0,0 +1,60 @@
|
|||
<!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">
|
||||
<!-- 使用 CDN 加速的 CSS 文件,配置在 vue.config.js 下 -->
|
||||
<% for (var i in htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.css) { %>
|
||||
<link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="preload" as="style">
|
||||
<link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet">
|
||||
<% } %>
|
||||
<!-- 使用 CDN 加速的 JS 文件,配置在 vue.config.js 下 -->
|
||||
<% for (var i in htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.js) { %>
|
||||
<link href="<%= htmlWebpackPlugin.options.cdn.js[i] %>" rel="preload" as="script">
|
||||
<% } %>
|
||||
<title><%= VUE_APP_TITLE %></title>
|
||||
<style>
|
||||
html, body, #app { height: 100%; margin: 0px; padding: 0px; width: 100%; }
|
||||
.d2-home { background-color: #303133; height: 100%; display: flex; flex-direction: column; }
|
||||
.d2-home__main { user-select: none; width: 100%; flex-grow: 1; display: flex; justify-content: center; align-items: center; flex-direction: column; }
|
||||
.d2-home__footer { width: 100%; flex-grow: 0; text-align: center; padding: 1em 0; }
|
||||
.d2-home__footer > a { font-size: 12px; color: #ABABAB; text-decoration: none; }
|
||||
.d2-home__loading { height: 32px; width: 32px; margin-bottom: 20px; }
|
||||
</style>
|
||||
<script>
|
||||
var _hmt = _hmt || [];
|
||||
var hmid = "bc38887aa5588add05a38704342ad7e8";
|
||||
(function() { var hm = document.createElement("script"); hm.src = "https://hm.baidu.com/hm.js?" + hmid; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s);})();
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<strong>
|
||||
Sorry, D2Admin will not work properly without JavaScript support. Enable JavaScript for browsers and continue.
|
||||
</strong>
|
||||
</noscript>
|
||||
<div id="app">
|
||||
<div class="d2-home">
|
||||
<div class="d2-home__main">
|
||||
<img
|
||||
class="d2-home__loading"
|
||||
src="./image/loading/loading-spin.svg"
|
||||
alt="loading">
|
||||
</div>
|
||||
<div class="d2-home__footer">
|
||||
<!-- <a-->
|
||||
<!-- href="https://github.com/d2-projects/d2-admin"-->
|
||||
<!-- target="_blank">-->
|
||||
<!-- https://github.com/d2-projects/d2-admin-->
|
||||
<!-- </a>-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 使用 CDN 加速的 JS 文件,配置在 vue.config.js 下 -->
|
||||
<% for (var i in htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.js) { %>
|
||||
<script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
|
||||
<% } %>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,28 @@
|
|||
<template>
|
||||
<div id="app">
|
||||
<router-view/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import util from '@/libs/util'
|
||||
export default {
|
||||
name: 'app',
|
||||
watch: {
|
||||
'$i18n.locale': 'i18nHandle'
|
||||
},
|
||||
created () {
|
||||
this.i18nHandle(this.$i18n.locale)
|
||||
},
|
||||
methods: {
|
||||
i18nHandle (val, oldVal) {
|
||||
util.cookies.set('lang', val)
|
||||
document.querySelector('html').setAttribute('lang', val)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '~@/assets/style/public-class.scss';
|
||||
</style>
|
|
@ -0,0 +1,17 @@
|
|||
import { assign, map } from 'lodash'
|
||||
import faker from 'faker/locale/zh_CN'
|
||||
import { service, request, serviceForMock, requestForMock, mock } from './service'
|
||||
import * as tools from './tools'
|
||||
|
||||
const files = require.context('./modules', true, /\.api\.js$/)
|
||||
const generators = files.keys().map(key => files(key).default)
|
||||
|
||||
export default assign({}, ...map(generators, generator => generator({
|
||||
service,
|
||||
request,
|
||||
serviceForMock,
|
||||
requestForMock,
|
||||
mock,
|
||||
faker,
|
||||
tools
|
||||
})))
|
|
@ -0,0 +1,31 @@
|
|||
import { find, assign } from 'lodash'
|
||||
|
||||
const users = [
|
||||
{ username: 'admin', password: 'admin', uuid: 'admin-uuid', name: 'Admin' },
|
||||
{ username: 'editor', password: 'editor', uuid: 'editor-uuid', name: 'Editor' },
|
||||
{ username: 'user1', password: 'user1', uuid: 'user1-uuid', name: 'User1' }
|
||||
]
|
||||
|
||||
export default ({ service, request, serviceForMock, requestForMock, mock, faker, tools }) => ({
|
||||
/**
|
||||
* @description 登录
|
||||
* @param {Object} data 登录携带的信息
|
||||
*/
|
||||
SYS_USER_LOGIN (data = {}) {
|
||||
// 模拟数据
|
||||
mock
|
||||
.onAny('/login')
|
||||
.reply(config => {
|
||||
const user = find(users, tools.parse(config.data))
|
||||
return user
|
||||
? tools.responseSuccess(assign({}, user, { token: faker.random.uuid() }))
|
||||
: tools.responseError({}, '账号或密码不正确')
|
||||
})
|
||||
// 接口请求
|
||||
return requestForMock({
|
||||
url: '/login',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
})
|
|
@ -0,0 +1,102 @@
|
|||
import axios from 'axios'
|
||||
import Adapter from 'axios-mock-adapter'
|
||||
import { get } from 'lodash'
|
||||
import util from '@/libs/util'
|
||||
import { errorLog, errorCreate } from './tools'
|
||||
|
||||
/**
|
||||
* @description 创建请求实例
|
||||
*/
|
||||
function createService () {
|
||||
// 创建一个 axios 实例
|
||||
const service = axios.create()
|
||||
// 请求拦截
|
||||
service.interceptors.request.use(
|
||||
config => config,
|
||||
error => {
|
||||
// 发送失败
|
||||
console.log(error)
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
// 响应拦截
|
||||
service.interceptors.response.use(
|
||||
response => {
|
||||
// dataAxios 是 axios 返回数据中的 data
|
||||
const dataAxios = response.data
|
||||
// 这个状态码是和后端约定的
|
||||
const { code } = dataAxios
|
||||
// 根据 code 进行判断
|
||||
if (code === undefined) {
|
||||
// 如果没有 code 代表这不是项目后端开发的接口 比如可能是 D2Admin 请求最新版本
|
||||
return dataAxios
|
||||
} else {
|
||||
// 有 code 代表这是一个后端接口 可以进行进一步的判断
|
||||
switch (code) {
|
||||
case 0:
|
||||
// [ 示例 ] code === 0 代表没有错误
|
||||
return dataAxios.data
|
||||
case 'xxx':
|
||||
// [ 示例 ] 其它和后台约定的 code
|
||||
errorCreate(`[ code: xxx ] ${dataAxios.msg}: ${response.config.url}`)
|
||||
break
|
||||
default:
|
||||
// 不是正确的 code
|
||||
errorCreate(`${dataAxios.msg}: ${response.config.url}`)
|
||||
break
|
||||
}
|
||||
}
|
||||
},
|
||||
error => {
|
||||
const status = get(error, 'response.status')
|
||||
switch (status) {
|
||||
case 400: error.message = '请求错误'; break
|
||||
case 401: error.message = '未授权,请登录'; break
|
||||
case 403: error.message = '拒绝访问'; break
|
||||
case 404: error.message = `请求地址出错: ${error.response.config.url}`; break
|
||||
case 408: error.message = '请求超时'; break
|
||||
case 500: error.message = '服务器内部错误'; break
|
||||
case 501: error.message = '服务未实现'; break
|
||||
case 502: error.message = '网关错误'; break
|
||||
case 503: error.message = '服务不可用'; break
|
||||
case 504: error.message = '网关超时'; break
|
||||
case 505: error.message = 'HTTP版本不受支持'; break
|
||||
default: break
|
||||
}
|
||||
errorLog(error)
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
return service
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 创建请求方法
|
||||
* @param {Object} service axios 实例
|
||||
*/
|
||||
function createRequestFunction (service) {
|
||||
return function (config) {
|
||||
const token = util.cookies.get('token')
|
||||
const configDefault = {
|
||||
headers: {
|
||||
Authorization: token,
|
||||
'Content-Type': get(config, 'headers.Content-Type', 'application/json')
|
||||
},
|
||||
timeout: 5000,
|
||||
baseURL: process.env.VUE_APP_API,
|
||||
data: {}
|
||||
}
|
||||
return service(Object.assign(configDefault, config))
|
||||
}
|
||||
}
|
||||
|
||||
// 用于真实网络请求的实例和请求方法
|
||||
export const service = createService()
|
||||
export const request = createRequestFunction(service)
|
||||
|
||||
// 用于模拟网络请求的实例和请求方法
|
||||
export const serviceForMock = createService()
|
||||
export const requestForMock = createRequestFunction(serviceForMock)
|
||||
|
||||
// 网络请求数据模拟工具
|
||||
export const mock = new Adapter(serviceForMock)
|
|
@ -0,0 +1,86 @@
|
|||
import { Message } from 'element-ui'
|
||||
import store from '@/store'
|
||||
import util from '@/libs/util'
|
||||
|
||||
/**
|
||||
* @description 安全地解析 json 字符串
|
||||
* @param {String} jsonString 需要解析的 json 字符串
|
||||
* @param {String} defaultValue 默认值
|
||||
*/
|
||||
export function parse (jsonString = '{}', defaultValue = {}) {
|
||||
let result = defaultValue
|
||||
try {
|
||||
result = JSON.parse(jsonString)
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 接口请求返回
|
||||
* @param {Any} data 返回值
|
||||
* @param {String} msg 状态信息
|
||||
* @param {Number} code 状态码
|
||||
*/
|
||||
export function response (data = {}, msg = '', code = 0) {
|
||||
return [
|
||||
200,
|
||||
{ code, msg, data }
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 接口请求返回 正确返回
|
||||
* @param {Any} data 返回值
|
||||
* @param {String} msg 状态信息
|
||||
*/
|
||||
export function responseSuccess (data = {}, msg = '成功') {
|
||||
return response(data, msg)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 接口请求返回 错误返回
|
||||
* @param {Any} data 返回值
|
||||
* @param {String} msg 状态信息
|
||||
* @param {Number} code 状态码
|
||||
*/
|
||||
export function responseError (data = {}, msg = '请求失败', code = 500) {
|
||||
return response(data, msg, code)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 记录和显示错误
|
||||
* @param {Error} error 错误对象
|
||||
*/
|
||||
export function errorLog (error) {
|
||||
// 添加到日志
|
||||
store.dispatch('d2admin/log/push', {
|
||||
message: '数据请求异常',
|
||||
type: 'danger',
|
||||
meta: {
|
||||
error
|
||||
}
|
||||
})
|
||||
// 打印到控制台
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
util.log.danger('>>>>>> Error >>>>>>')
|
||||
console.log(error)
|
||||
}
|
||||
// 显示提示
|
||||
Message({
|
||||
message: error.message,
|
||||
type: 'error',
|
||||
duration: 5 * 1000
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 创建一个错误
|
||||
* @param {String} msg 错误信息
|
||||
*/
|
||||
export function errorCreate (msg) {
|
||||
const error = new Error(msg)
|
||||
errorLog(error)
|
||||
throw error
|
||||
}
|
|
@ -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 .3s;
|
||||
}
|
||||
.fade-scale-enter {
|
||||
opacity: 0;
|
||||
transform: scale(1.2);
|
||||
}
|
||||
.fade-scale-leave-to {
|
||||
opacity: 0;
|
||||
transform: scale(0.8);
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
// 优化显示
|
||||
html, body {
|
||||
margin: 0px;
|
||||
height: 100%;
|
||||
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
|
||||
#app {
|
||||
@extend %full;
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
// 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;
|
||||
}
|
||||
|
||||
// 修复IE宽度不能撑满
|
||||
.el-table__body,
|
||||
.el-table__header {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
// Chrome下表格头部错位修复
|
||||
.el-table th.gutter,
|
||||
.el-table colgroup.gutter {
|
||||
display: table-cell !important;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
// markdown 样式补丁
|
||||
.markdown-body {
|
||||
ul {
|
||||
list-style: disc;
|
||||
}
|
||||
h1, h2 {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
#nprogress {
|
||||
.bar {
|
||||
background: $color-primary !important;
|
||||
}
|
||||
.peg {
|
||||
box-shadow: 0 0 10px $color-primary, 0 0 5px $color-primary !important;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
.tree-view-wrapper.tree-view-small {
|
||||
.tree-view-item {
|
||||
font-size: 10px;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
// vue-splitpane 样式补丁
|
||||
.vue-grid-item {
|
||||
&.vue-grid-placeholder {
|
||||
border: 1px solid $color-border-1;
|
||||
background-color: rgba(#FFF, .3);
|
||||
opacity: 1;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
// vue-splitpane 样式补丁
|
||||
.splitter-pane-resizer {
|
||||
background-color: $color-border-1 !important;
|
||||
opacity: 1 !important;
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
@import 'public';
|
||||
|
||||
// 补丁 base
|
||||
@import '~@/assets/style/fixed/base.scss';
|
||||
// 补丁 element
|
||||
@import '~@/assets/style/fixed/element.scss';
|
||||
// 补丁 markdown
|
||||
@import '~@/assets/style/fixed/markdown.scss';
|
||||
// 补丁 n-progress
|
||||
@import '~@/assets/style/fixed/n-progress.scss';
|
||||
// 补丁 vue-splitpane
|
||||
@import '~@/assets/style/fixed/vue-splitpane.scss';
|
||||
// 补丁 vue-grid-layout
|
||||
@import '~@/assets/style/fixed/vue-grid-layout.scss';
|
||||
// 补丁 tree-view
|
||||
@import '~@/assets/style/fixed/tree-view.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;
|
||||
}
|
||||
|
||||
// 边距相关
|
||||
$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; }
|
|
@ -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;
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
@import './setting.scss';
|
||||
@import '../theme.scss';
|
|
@ -0,0 +1,64 @@
|
|||
// 主题名称
|
||||
$theme-name: 'chester';
|
||||
// 主题背景颜色
|
||||
$theme-bg-color: #2C3643;
|
||||
// 主题背景图片遮罩
|
||||
$theme-bg-mask: rgba(#000, 0);
|
||||
|
||||
// 消息提示
|
||||
$theme-message-info-background-color: #FFFFFF;
|
||||
$theme-message-info-text-color: #222A34;
|
||||
$theme-message-info-border-color: #222A34;
|
||||
|
||||
// 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 #2A2D2E;
|
||||
|
||||
$theme-multiple-page-control-color: #CCCCCC;
|
||||
$theme-multiple-page-control-color-active: #242D38;
|
||||
$theme-multiple-page-control-nav-prev-color: #CCCCCC;
|
||||
$theme-multiple-page-control-nav-next-color: #CCCCCC;
|
||||
$theme-multiple-page-control-border-color: #2A2D2E;
|
||||
$theme-multiple-page-control-border-color-active: #FFFFFF;
|
||||
$theme-multiple-page-control-background-color: #242D38;
|
||||
$theme-multiple-page-control-background-color-active: #FFFFFF;
|
||||
|
||||
// 顶栏和侧边栏中展开的菜单 hover 状态下
|
||||
$theme-menu-item-color-hover: #CCCCCC;
|
||||
$theme-menu-item-background-color-hover: #2A2D2E;
|
||||
|
||||
// 顶栏上的文字颜色
|
||||
$theme-header-item-color: #CCCCCC;
|
||||
$theme-header-item-background-color: transparent;
|
||||
// 顶栏上的项目在 hover 时
|
||||
$theme-header-item-color-hover: #CCCCCC;
|
||||
$theme-header-item-background-color-hover: #2A2D2E;
|
||||
// 顶栏上的项目在 focus 时
|
||||
$theme-header-item-color-focus: #CCCCCC;
|
||||
$theme-header-item-background-color-focus: #222A34;
|
||||
// 顶栏上的项目在 active 时
|
||||
$theme-header-item-color-active: #FFFFFF;
|
||||
$theme-header-item-background-color-active: #222A34;
|
||||
|
||||
// 侧边栏上的文字颜色
|
||||
$theme-aside-item-color: #CCCCCC;
|
||||
$theme-aside-item-background-color: transparent;
|
||||
// 侧边栏上的项目在 hover 时
|
||||
$theme-aside-item-color-hover: #CCCCCC;
|
||||
$theme-aside-item-background-color-hover: #2A2D2E;
|
||||
// 侧边栏上的项目在 focus 时
|
||||
$theme-aside-item-color-focus: #CCCCCC;
|
||||
$theme-aside-item-background-color-focus: #222A34;
|
||||
// 侧边栏上的项目在 active 时
|
||||
$theme-aside-item-color-active: #FFFFFF;
|
||||
$theme-aside-item-background-color-active: #222A34;
|
||||
|
||||
// 侧边栏菜单为空的时候显示的元素
|
||||
$theme-aside-menu-empty-icon-color: #CCCCCC;
|
||||
$theme-aside-menu-empty-text-color: #CCCCCC;
|
||||
$theme-aside-menu-empty-background-color: #242D38;
|
||||
$theme-aside-menu-empty-icon-color-hover: #FFFFFF;
|
||||
$theme-aside-menu-empty-text-color-hover: #FFFFFF;
|
||||
$theme-aside-menu-empty-background-color-hover: #242D38;
|
|
@ -0,0 +1,2 @@
|
|||
@import './setting.scss';
|
||||
@import '../theme.scss';
|
|
@ -0,0 +1,64 @@
|
|||
// 主题名称
|
||||
$theme-name: 'd2';
|
||||
// 主题背景颜色
|
||||
$theme-bg-color: #ebf1f6;
|
||||
// 主题背景图片遮罩
|
||||
$theme-bg-mask: rgba(#000, 0);
|
||||
|
||||
// 消息提示
|
||||
$theme-message-info-background-color: $color-bg;
|
||||
$theme-message-info-text-color: $color-text-normal;
|
||||
$theme-message-info-border-color: $color-border-1;
|
||||
|
||||
// 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);
|
|
@ -0,0 +1,2 @@
|
|||
@import './setting.scss';
|
||||
@import '../theme.scss';
|
|
@ -0,0 +1,64 @@
|
|||
// 主题名称
|
||||
$theme-name: 'element';
|
||||
// 主题背景颜色
|
||||
$theme-bg-color: #314255;
|
||||
// 主题背景图片遮罩
|
||||
$theme-bg-mask: rgba(#000, 0);
|
||||
|
||||
// 消息提示
|
||||
$theme-message-info-background-color: #FFFFFF;
|
||||
$theme-message-info-text-color: #202D3D;
|
||||
$theme-message-info-border-color: #202D3D;
|
||||
|
||||
// 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 #011527;
|
||||
|
||||
$theme-multiple-page-control-color: #BFCBD9;
|
||||
$theme-multiple-page-control-color-active: #46A0FC;
|
||||
$theme-multiple-page-control-nav-prev-color: #BFCBD9;
|
||||
$theme-multiple-page-control-nav-next-color: #BFCBD9;
|
||||
$theme-multiple-page-control-border-color: #011527;
|
||||
$theme-multiple-page-control-border-color-active: #FFFFFF;
|
||||
$theme-multiple-page-control-background-color: #212D3D;
|
||||
$theme-multiple-page-control-background-color-active: #FFFFFF;
|
||||
|
||||
// 顶栏和侧边栏中展开的菜单 hover 状态下
|
||||
$theme-menu-item-color-hover: #BFCBD9;
|
||||
$theme-menu-item-background-color-hover: #011527;
|
||||
|
||||
// 顶栏上的文字颜色
|
||||
$theme-header-item-color: #BFCBD9;
|
||||
$theme-header-item-background-color: transparent;
|
||||
// 顶栏上的项目在 hover 时
|
||||
$theme-header-item-color-hover: #BFCBD9;
|
||||
$theme-header-item-background-color-hover: #011527;
|
||||
// 顶栏上的项目在 focus 时
|
||||
$theme-header-item-color-focus: #BFCBD9;
|
||||
$theme-header-item-background-color-focus: #202D3D;
|
||||
// 顶栏上的项目在 active 时
|
||||
$theme-header-item-color-active: #46A0FC;
|
||||
$theme-header-item-background-color-active: #202D3D;
|
||||
|
||||
// 侧边栏上的文字颜色
|
||||
$theme-aside-item-color: #BFCBD9;
|
||||
$theme-aside-item-background-color: transparent;
|
||||
// 侧边栏上的项目在 hover 时
|
||||
$theme-aside-item-color-hover: #BFCBD9;
|
||||
$theme-aside-item-background-color-hover: #011527;
|
||||
// 侧边栏上的项目在 focus 时
|
||||
$theme-aside-item-color-focus: #BFCBD9;
|
||||
$theme-aside-item-background-color-focus: #202D3D;
|
||||
// 侧边栏上的项目在 active 时
|
||||
$theme-aside-item-color-active: #46A0FC;
|
||||
$theme-aside-item-background-color-active: #202D3D;
|
||||
|
||||
// 侧边栏菜单为空的时候显示的元素
|
||||
$theme-aside-menu-empty-icon-color: #BFCBD9;
|
||||
$theme-aside-menu-empty-text-color: #BFCBD9;
|
||||
$theme-aside-menu-empty-background-color: #202D3D;
|
||||
$theme-aside-menu-empty-icon-color-hover: #46A0FC;
|
||||
$theme-aside-menu-empty-text-color-hover: #46A0FC;
|
||||
$theme-aside-menu-empty-background-color-hover: #202D3D;
|
|
@ -0,0 +1,2 @@
|
|||
@import './setting.scss';
|
||||
@import '../theme.scss';
|
|
@ -0,0 +1,64 @@
|
|||
// 主题名称
|
||||
$theme-name: 'line';
|
||||
// 主题背景颜色
|
||||
$theme-bg-color: #f8f8f9;
|
||||
// 主题背景图片遮罩
|
||||
$theme-bg-mask: rgba(#000, 0);
|
||||
|
||||
// 消息提示
|
||||
$theme-message-info-background-color: $color-bg;
|
||||
$theme-message-info-text-color: $color-text-normal;
|
||||
$theme-message-info-border-color: $color-border-1;
|
||||
|
||||
// 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);
|
|
@ -0,0 +1,9 @@
|
|||
@import '~@/assets/style/theme/theme-base.scss';
|
||||
|
||||
@import '~@/assets/style/theme/d2/index.scss';
|
||||
@import '~@/assets/style/theme/chester/index.scss';
|
||||
@import '~@/assets/style/theme/element/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';
|
|
@ -0,0 +1,2 @@
|
|||
@import './setting.scss';
|
||||
@import '../theme.scss';
|
|
@ -0,0 +1,64 @@
|
|||
// 主题名称
|
||||
$theme-name: 'star';
|
||||
// 主题背景颜色
|
||||
$theme-bg-color: #EFF4F8;
|
||||
// 主题背景图片遮罩
|
||||
$theme-bg-mask: rgba(#000, .3);
|
||||
|
||||
// 消息提示
|
||||
$theme-message-info-background-color: $color-bg;
|
||||
$theme-message-info-text-color: $color-text-normal;
|
||||
$theme-message-info-border-color: $color-border-1;
|
||||
|
||||
// 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);
|
|
@ -0,0 +1,454 @@
|
|||
// 减小弹出菜单的项目高度
|
||||
.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 {
|
||||
position: relative;
|
||||
.d2-layout-header-aside-menu-side {
|
||||
@extend %full;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
.d2-theme-container-transition {
|
||||
transition: width .3s;
|
||||
}
|
||||
.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 {
|
||||
float: left;
|
||||
text-align: center;
|
||||
img {
|
||||
height: 60px;
|
||||
}
|
||||
}
|
||||
.logo-transition {
|
||||
transition: width .3s;
|
||||
}
|
||||
// 折叠侧边栏切换按钮
|
||||
.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-color-picker.el-color-picker--mini {
|
||||
padding: 9px 6px;
|
||||
}
|
||||
}
|
||||
.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 {
|
||||
height: 41px;
|
||||
// 多页面控制器
|
||||
.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;
|
||||
height: 100%;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,421 @@
|
|||
// 每个主题特有的设置
|
||||
.theme-#{$theme-name} {
|
||||
|
||||
.el-message {
|
||||
&.el-message--info {
|
||||
background-color: $theme-message-info-background-color;
|
||||
color: $theme-message-info-text-color;
|
||||
border-color: $theme-message-info-border-color;
|
||||
}
|
||||
}
|
||||
|
||||
.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;
|
||||
fill: $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;
|
||||
fill: $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;
|
||||
fill: $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-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,64 @@
|
|||
// 主题名称
|
||||
$theme-name: 'tomorrow-night-blue';
|
||||
// 主题背景颜色
|
||||
$theme-bg-color: #002253;
|
||||
// 主题背景图片遮罩
|
||||
$theme-bg-mask: rgba(#000, 0);
|
||||
|
||||
// 消息提示
|
||||
$theme-message-info-background-color: $color-bg;
|
||||
$theme-message-info-text-color: $color-text-normal;
|
||||
$theme-message-info-border-color: $color-border-1;
|
||||
|
||||
// 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);
|
|
@ -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,64 @@
|
|||
// 主题名称
|
||||
$theme-name: 'violet';
|
||||
// 主题背景颜色
|
||||
$theme-bg-color: #000;
|
||||
// 主题背景图片遮罩
|
||||
$theme-bg-mask: rgba(#000, 0);
|
||||
|
||||
// 消息提示
|
||||
$theme-message-info-background-color: $color-bg;
|
||||
$theme-message-info-text-color: $color-text-normal;
|
||||
$theme-message-info-border-color: $color-border-1;
|
||||
|
||||
// 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);
|
|
@ -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;
|
After Width: | Height: | Size: 7.8 KiB |
|
@ -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 |
|
@ -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,33 @@
|
|||
<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" ref="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>
|
||||
import scroll from './mixins/normal'
|
||||
export default {
|
||||
name: 'd2-container-card',
|
||||
mixins: [
|
||||
scroll
|
||||
],
|
||||
mounted () {
|
||||
// 增加滚动事件监听
|
||||
this.addScrollListener()
|
||||
},
|
||||
beforeDestroy () {
|
||||
// 移除滚动事件监听
|
||||
this.removeScrollListener()
|
||||
}
|
||||
}
|
||||
</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,31 @@
|
|||
<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" ref="body">
|
||||
<slot/>
|
||||
</div>
|
||||
<div v-if="$slots.footer" class="d2-container-full__footer" ref="footer">
|
||||
<slot name="footer"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import scroll from './mixins/normal'
|
||||
export default {
|
||||
name: 'd2-container-full',
|
||||
mixins: [
|
||||
scroll
|
||||
],
|
||||
mounted () {
|
||||
// 增加滚动事件监听
|
||||
this.addScrollListener()
|
||||
},
|
||||
beforeDestroy () {
|
||||
// 移除滚动事件监听
|
||||
this.removeScrollListener()
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,26 @@
|
|||
<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">
|
||||
<!-- https://github.com/d2-projects/d2-admin/issues/181 -->
|
||||
<div>
|
||||
<slot/>
|
||||
</div>
|
||||
</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,31 @@
|
|||
<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" ref="body">
|
||||
<slot/>
|
||||
</div>
|
||||
<div v-if="$slots.footer" class="d2-container-ghost__footer" ref="footer">
|
||||
<slot name="footer"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import scroll from './mixins/normal'
|
||||
export default {
|
||||
name: 'd2-container-ghost',
|
||||
mixins: [
|
||||
scroll
|
||||
],
|
||||
mounted () {
|
||||
// 增加滚动事件监听
|
||||
this.addScrollListener()
|
||||
},
|
||||
beforeDestroy () {
|
||||
// 移除滚动事件监听
|
||||
this.removeScrollListener()
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,79 @@
|
|||
<template>
|
||||
<div
|
||||
v-if="show"
|
||||
class="d2-source"
|
||||
:class="{ 'd2-source--active': isActive }"
|
||||
@click="handleClick">
|
||||
<d2-icon name="code"/> 本页源码
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { last, get } from 'lodash'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
isActive: false,
|
||||
path: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
show () {
|
||||
return process.env.VUE_APP_SCOURCE_LINK === 'TRUE'
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
$route: {
|
||||
handler (to) {
|
||||
this.path = get(last(to.matched), 'components.default.__source')
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
// 一秒后显示按钮
|
||||
setTimeout(() => {
|
||||
this.isActive = true
|
||||
}, 500)
|
||||
},
|
||||
methods: {
|
||||
// 点击按钮的时候跳转到源代码
|
||||
handleClick () {
|
||||
this.$open(`${process.env.VUE_APP_REPO}/blob/master/${this.path}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.d2-source {
|
||||
$borderRadius: 4px;
|
||||
$paddingLR: 15px;
|
||||
$paddingTB: 7px;
|
||||
$fontSize: 12px;
|
||||
$rightOuter: $paddingLR / 2;
|
||||
opacity: 0;
|
||||
position: fixed;
|
||||
z-index: 9999;
|
||||
right: - $borderRadius - $rightOuter;
|
||||
bottom: 20px;
|
||||
font-size: $fontSize;
|
||||
line-height: $fontSize;
|
||||
font-weight: bold;
|
||||
border-radius: $borderRadius;
|
||||
padding: $paddingTB $paddingLR;
|
||||
padding-right: $borderRadius + $paddingLR;
|
||||
background-color: rgba(#000, .7);
|
||||
border: 1px solid #000;
|
||||
color: #FFF;
|
||||
transition: all .3s;
|
||||
@extend %unable-select;
|
||||
&.d2-source--active {
|
||||
opacity: 1;
|
||||
}
|
||||
&:hover {
|
||||
right: - $borderRadius;
|
||||
background-color: rgba(#000, .9);
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,62 @@
|
|||
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 () {
|
||||
// 初始化 bs
|
||||
this.BS = new BScroll(this.$refs.wrapper, Object.assign({
|
||||
mouseWheel: true,
|
||||
click: true,
|
||||
scrollbar: {
|
||||
fade: true,
|
||||
interactive: false
|
||||
}
|
||||
}, this.betterScrollOptions))
|
||||
// 滚动时发出事件 并且统一返回的数据格式
|
||||
this.BS.on('scroll', ({ x, y }) => this.$emit('scroll', {
|
||||
x: -x,
|
||||
y: -y
|
||||
}))
|
||||
},
|
||||
scrollDestroy () {
|
||||
// https://github.com/d2-projects/d2-admin/issues/75
|
||||
try {
|
||||
this.BS.destroy()
|
||||
} catch (e) {
|
||||
delete this.BS
|
||||
this.BS = null
|
||||
}
|
||||
},
|
||||
// 外部调用的方法 返回顶部
|
||||
scrollToTop () {
|
||||
if (this.BS) this.BS.scrollTo(0, 0, 300)
|
||||
},
|
||||
// 手动发出滚动事件
|
||||
scroll () {
|
||||
if (this.BS) {
|
||||
this.$emit('scroll', {
|
||||
x: -this.BS.x,
|
||||
y: -this.BS.y
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
// 提供滚动方面的功能
|
||||
// 非滚动优化模式通用
|
||||
|
||||
import { throttle } from 'lodash'
|
||||
|
||||
// 生成滚动事件的 handler
|
||||
function handleMaker (wait) {
|
||||
return throttle(e => {
|
||||
this.$emit('scroll', {
|
||||
x: e.target.scrollLeft,
|
||||
y: e.target.scrollTop
|
||||
})
|
||||
}, wait)
|
||||
}
|
||||
|
||||
export default {
|
||||
props: {
|
||||
// 滚动事件节流间隔
|
||||
scrollDelay: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 10
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
handleScroll: null
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
scrollDelay (val) {
|
||||
// 移除旧的监听
|
||||
this.removeScrollListener()
|
||||
// 生成新的 handle 方法
|
||||
this.handleScroll = handleMaker.call(this, val)
|
||||
// 添加新的监听
|
||||
this.addScrollListener()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 增加滚动事件监听
|
||||
addScrollListener () {
|
||||
if (typeof this.handleScroll !== 'function') {
|
||||
// mounted 生命周期内调用这个方法的时候会进入这里的判断
|
||||
this.handleScroll = handleMaker.call(this, this.scrollDelay)
|
||||
}
|
||||
// 添加监听
|
||||
this.$refs.body.addEventListener('scroll', this.handleScroll)
|
||||
},
|
||||
// 移除滚动事件监听
|
||||
removeScrollListener () {
|
||||
this.$refs.body.removeEventListener('scroll', this.handleScroll)
|
||||
},
|
||||
// 外部调用的方法 返回顶部
|
||||
scrollToTop () {
|
||||
const smoothscroll = () => {
|
||||
const body = this.$refs.body
|
||||
const currentScroll = body.scrollTop
|
||||
if (currentScroll > 0) {
|
||||
window.requestAnimationFrame(smoothscroll)
|
||||
body.scrollTo(0, currentScroll - (currentScroll / 5))
|
||||
}
|
||||
}
|
||||
smoothscroll()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
// 组件
|
||||
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'
|
||||
import d2Source from './components/d2-source.vue'
|
||||
|
||||
export default {
|
||||
name: 'd2-container',
|
||||
props: {
|
||||
// 容器样式
|
||||
type: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'full'
|
||||
},
|
||||
// 滚动优化
|
||||
betterScroll: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 始终返回渲染组件
|
||||
component () {
|
||||
if (this.type === 'card' && !this.betterScroll) return d2ContainerCard
|
||||
if (this.type === 'card' && this.betterScroll) return d2ContainerCardBs
|
||||
if (this.type === 'ghost' && !this.betterScroll) return d2ContainerGhost
|
||||
if (this.type === 'ghost' && this.betterScroll) return d2ContainerGhostBs
|
||||
if (this.type === 'full' && !this.betterScroll) return d2ContainerFull
|
||||
if (this.type === 'full' && this.betterScroll) return d2ContainerFullBs
|
||||
else {
|
||||
return 'div'
|
||||
}
|
||||
}
|
||||
},
|
||||
render (h) {
|
||||
const slots = [
|
||||
this.$slots.default,
|
||||
this.$slots.header ? <template slot="header">{ this.$slots.header }</template> : null,
|
||||
this.$slots.footer ? <template slot="footer">{ this.$slots.footer }</template> : null
|
||||
]
|
||||
return <div
|
||||
ref="container"
|
||||
class="container-component">
|
||||
<this.component
|
||||
ref="component"
|
||||
{ ...{ attrs: this.$attrs } }
|
||||
onScroll={ e => this.$emit('scroll', e) }>
|
||||
{ slots }
|
||||
</this.component>
|
||||
<d2Source/>
|
||||
</div>
|
||||
},
|
||||
methods: {
|
||||
// 返回顶部
|
||||
scrollToTop () {
|
||||
this.$refs.component.scrollToTop()
|
||||
// 如果开启了 better scroll 还需要手动触发一遍 scroll 事件
|
||||
const bs = this.$refs.component.BS
|
||||
if (bs) this.$refs.component.scroll()
|
||||
},
|
||||
// 用法同原生方法 scrollBy
|
||||
scrollBy (x = 0, y = 0, time = 300) {
|
||||
if (this.betterScroll) {
|
||||
const bs = this.$refs.component.BS
|
||||
if (bs) {
|
||||
bs.scrollBy(-x, -y, time)
|
||||
// 手动触发一遍 scroll 事件
|
||||
this.$refs.component.scroll()
|
||||
}
|
||||
} else {
|
||||
this.$refs.component.$refs.body.scrollBy(x, y)
|
||||
}
|
||||
},
|
||||
// 用法同原生方法 scrollTo
|
||||
scrollTo (x = 0, y = 0, time = 300) {
|
||||
if (this.betterScroll) {
|
||||
const bs = this.$refs.component.BS
|
||||
if (bs) {
|
||||
bs.scrollTo(-x, -y, time)
|
||||
// 手动触发一遍 scroll 事件
|
||||
this.$refs.component.scroll()
|
||||
}
|
||||
} else {
|
||||
this.$refs.component.$refs.body.scrollTo(x, y)
|
||||
}
|
||||
},
|
||||
// 用法同原生方法 scrollTop
|
||||
scrollTop (top = 0, time = 300) {
|
||||
if (this.betterScroll) {
|
||||
const bs = this.$refs.component.BS
|
||||
if (bs) {
|
||||
bs.scrollTo(bs.x, -top, time)
|
||||
// 手动触发一遍 scroll 事件
|
||||
this.$refs.component.scroll()
|
||||
}
|
||||
} else {
|
||||
this.$refs.component.$refs.body.scrollTop = top
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
After Width: | Height: | Size: 434 KiB |
|
@ -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>
|
|
@ -0,0 +1,8 @@
|
|||
import Vue from 'vue'
|
||||
|
||||
import d2Container from './d2-container'
|
||||
|
||||
// 注意 有些组件使用异步加载会有影响
|
||||
Vue.component('d2-container', d2Container)
|
||||
Vue.component('d2-icon', () => import('./d2-icon'))
|
||||
Vue.component('d2-icon-svg', () => import('./d2-icon-svg/index.vue'))
|
|
@ -0,0 +1,37 @@
|
|||
import Vue from 'vue'
|
||||
import VueI18n from 'vue-i18n'
|
||||
import util from '@/libs/util'
|
||||
|
||||
Vue.use(VueI18n)
|
||||
|
||||
function loadLocaleMessages () {
|
||||
const locales = require.context('./locales', true, /[A-Za-z0-9-_,\s]+\.json$/i)
|
||||
const messages = {}
|
||||
for (const key of locales.keys()) {
|
||||
const matched = key.match(/([A-Za-z0-9-_]+)\./i)
|
||||
if (matched && matched.length > 1) {
|
||||
const locale = matched[1]
|
||||
const localeElementUI = require(`element-ui/lib/locale/lang/${locales(key)._element}`)
|
||||
messages[locale] = {
|
||||
...locales(key),
|
||||
...localeElementUI ? localeElementUI.default : {}
|
||||
}
|
||||
}
|
||||
}
|
||||
return messages
|
||||
}
|
||||
|
||||
const messages = loadLocaleMessages()
|
||||
|
||||
Vue.prototype.$languages = Object.keys(messages).map(langlage => ({
|
||||
label: messages[langlage]._name,
|
||||
value: langlage
|
||||
}))
|
||||
|
||||
const i18n = new VueI18n({
|
||||
locale: util.cookies.get('lang') || process.env.VUE_APP_I18N_LOCALE,
|
||||
fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE,
|
||||
messages
|
||||
})
|
||||
|
||||
export default i18n
|
|
@ -0,0 +1,50 @@
|
|||
<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,68 @@
|
|||
<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,44 @@
|
|||
<template>
|
||||
<el-color-picker
|
||||
class="btn-text can-hover"
|
||||
:value="value"
|
||||
:predefine="predefine"
|
||||
size="mini"
|
||||
@change="set"/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState, mapActions } from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'd2-header-color',
|
||||
data () {
|
||||
return {
|
||||
predefine: [
|
||||
'#ff4500',
|
||||
'#ff8c00',
|
||||
'#ffd700',
|
||||
'#90ee90',
|
||||
'#00ced1',
|
||||
'#1e90ff',
|
||||
'#c71585'
|
||||
]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('d2admin/color', [
|
||||
'value'
|
||||
])
|
||||
},
|
||||
watch: {
|
||||
value (value) {
|
||||
this.set(value)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions('d2admin/color', [
|
||||
'set'
|
||||
])
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,24 @@
|
|||
<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,25 @@
|
|||
<template>
|
||||
<el-dropdown placement="bottom" size="small" @command="onChangeLocale">
|
||||
<el-button class="d2-mr btn-text can-hover" type="text">
|
||||
<d2-icon name="language" style="font-size: 16px;"/>
|
||||
</el-button>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item
|
||||
v-for="language in $languages"
|
||||
:key="language.value"
|
||||
:command="language.value">
|
||||
<d2-icon :name="$i18n.locale === language.value ? 'dot-circle-o' : 'circle-o'" class="d2-mr-5"/>
|
||||
{{ language.label }}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import localeMixin from '@/locales/mixin.js'
|
||||
export default {
|
||||
mixins: [
|
||||
localeMixin
|
||||
]
|
||||
}
|
||||
</script>
|