Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2c835ea42f | ||
|
|
666783e11e | ||
|
|
2894434ae8 | ||
|
|
2b28317a8f | ||
|
|
31ce6dca15 | ||
|
|
c9a5fee48a | ||
|
|
b31cd37109 | ||
|
|
8786e2b427 | ||
|
|
87cce788a5 | ||
|
|
8165c13128 | ||
|
|
b7f4d87236 | ||
|
|
91ffc11b90 | ||
|
|
e2ad3d1caf | ||
|
|
9bd725fc8e | ||
|
|
affd0d0325 | ||
|
|
b9402649c6 | ||
|
|
02298f9361 | ||
|
|
f698bdd6b0 | ||
|
|
ef85fda048 | ||
|
|
27816d9303 | ||
|
|
52189867ea | ||
|
|
c127440207 | ||
|
|
d856e81c5f | ||
|
|
36d4c81dd5 | ||
|
|
254bde20b9 | ||
|
|
153270fe9a | ||
|
|
9fa6462bcd | ||
|
|
bb16ed3b21 | ||
|
|
32c881a875 | ||
|
|
5859dd5113 | ||
|
|
214b34ed28 | ||
|
|
ab7c915140 | ||
|
|
0e8c223cfa | ||
|
|
e1838a5fac | ||
|
|
813e9c9ae3 | ||
|
|
7bddd1e1c8 | ||
|
|
392fd860f2 | ||
|
|
17a674d956 | ||
|
|
71bc7ebe8e | ||
|
|
18db3f5cae | ||
|
|
9901920bc7 | ||
|
|
0296d2f345 | ||
|
|
d880fc0487 | ||
|
|
058498093a | ||
|
|
2ac3e24e7a | ||
|
|
f7f0351505 | ||
|
|
8b9b6f6bd4 | ||
|
|
4bcc3555ca | ||
|
|
e003175a02 | ||
|
|
46db40780a | ||
|
|
5b5f0d05c4 | ||
|
|
93691bdb4f | ||
|
|
00429b1f73 | ||
|
|
b0029661e0 | ||
|
|
5325637deb | ||
|
|
aee4a75428 | ||
|
|
820801af20 | ||
|
|
e60cbd853f | ||
|
|
e61ff77284 | ||
|
|
4ec3c9f9ab | ||
|
|
202f6e54b7 | ||
|
|
c3c5adffd7 | ||
|
|
7ff2e70853 | ||
|
|
9981b2f56d | ||
|
|
cbc1cbe9f4 | ||
|
|
99eca5420e | ||
|
|
eb072dc5a9 | ||
|
|
14bf34fbc6 | ||
|
|
5d6d11aa7d | ||
|
|
ec90f66d94 | ||
|
|
7d8e245e14 | ||
|
|
65456dfccc | ||
|
|
7bfc98a0ff | ||
|
|
061ade451a | ||
|
|
85810b5767 | ||
|
|
7bb3d6fe3b | ||
|
|
3b7da44cc7 | ||
|
|
9d8d3d35da | ||
|
|
62466ff1d4 | ||
|
|
8e9ee8df71 | ||
|
|
08f5a9f186 | ||
|
|
49413436c1 | ||
|
|
6afbc93199 | ||
|
|
41b5b44403 | ||
|
|
b34f66ad8c | ||
|
|
1d8eb74ba7 | ||
|
|
0dc139c087 | ||
|
|
92eb82e207 | ||
|
|
2f76483d05 | ||
|
|
3ae906b07e | ||
|
|
e41ae5e5b5 | ||
|
|
43ab1290f5 | ||
|
|
13a3020633 | ||
|
|
9e505f2003 | ||
|
|
7803fd0dba | ||
|
|
7f9425fc61 | ||
|
|
dc377984ff | ||
|
|
057feb28e2 | ||
|
|
5681238cd0 | ||
|
|
43f3712f54 | ||
|
|
736d0120b7 | ||
|
|
5483b99376 | ||
|
|
f13543c54e | ||
|
|
00a9e71de9 | ||
|
|
f058642d69 | ||
|
|
7fd650024e | ||
|
|
edc6c9c562 | ||
|
|
65b8de8db0 | ||
|
|
eada6b5005 | ||
|
|
bb397d0639 | ||
|
|
86852f6714 | ||
|
|
7b1af51fe6 | ||
|
|
61746f5ebf | ||
|
|
231d89ae5c | ||
|
|
a1fb2f9ba5 | ||
|
|
9782fd929a | ||
|
|
d0dab0894c | ||
|
|
422f716d36 | ||
|
|
1fa200e0fd | ||
|
|
c83edd2209 | ||
|
|
328946944d | ||
|
|
700a2eff60 | ||
|
|
8871c7873d | ||
|
|
47faafa27d | ||
|
|
f0aac156a2 | ||
|
|
148a0052e3 | ||
|
|
68d6fa0176 | ||
|
|
cc8d2c8729 | ||
|
|
34ef6e4ec9 | ||
|
|
3c97f38c5e | ||
|
|
750478036c | ||
|
|
9a0f787484 | ||
|
|
9e99a5f30a | ||
|
|
f471691292 | ||
|
|
dd20af4c19 | ||
|
|
3902a657ee | ||
|
|
84cfc03d29 | ||
|
|
af41bbe7a3 | ||
|
|
ea4c9428a1 | ||
|
|
328bc4c712 | ||
|
|
17b4dbb191 | ||
|
|
7569ca9c87 | ||
|
|
754c86a7c5 | ||
|
|
023bb4a3a1 | ||
|
|
16adebaebf | ||
|
|
7ae8dd128f | ||
|
|
e9863403fe | ||
|
|
260462465e | ||
|
|
de63f1e3d4 | ||
|
|
33b48e0e2d | ||
|
|
d62192fa39 | ||
|
|
62c183470a | ||
|
|
3819c8e24e | ||
|
|
cca1a55647 | ||
|
|
a4ae20f458 | ||
|
|
7009d94648 | ||
|
|
d227d231db | ||
|
|
b8cd2e5d4d | ||
|
|
422b5bda20 | ||
|
|
5f0455c676 | ||
|
|
e4b9e58a41 | ||
|
|
8babfa9d67 | ||
|
|
30b2a5ba09 | ||
|
|
290eab243b | ||
|
|
9bab8765c4 | ||
|
|
e3d34dde82 | ||
|
|
3e9533a624 | ||
|
|
41df6e08ed | ||
|
|
3e0fe86a4b | ||
|
|
469d3d93f9 | ||
|
|
d07a7d229c | ||
|
|
2eddd832e8 | ||
|
|
c7ffa53463 | ||
|
|
be436f6679 | ||
|
|
8e17ad1c5f | ||
|
|
622b8129fb | ||
|
|
b8599d15d0 | ||
|
|
2fa3fca071 | ||
|
|
a67e0e1e23 | ||
|
|
67ace29f28 | ||
|
|
31011d65ed | ||
|
|
f9ed88b84f | ||
|
|
7bf0fc6c77 | ||
|
|
5b7d29de4d | ||
|
|
bc01b42182 | ||
|
|
9ca77eb501 | ||
|
|
36a890ceb4 | ||
|
|
232c63af60 | ||
|
|
686ff1dcde | ||
|
|
7bad1db7e6 | ||
|
|
3a2a5bab2a | ||
|
|
ddbc94e854 | ||
|
|
7332a1807d | ||
|
|
03bb3f4881 | ||
|
|
397cc7af58 | ||
|
|
2afa8c6f0f | ||
|
|
9894b3196f | ||
|
|
094d6961e2 | ||
|
|
4e5796159f | ||
|
|
2409817980 | ||
|
|
641830255f | ||
|
|
347598abac | ||
|
|
f010f8a709 | ||
|
|
26f6e00d15 | ||
|
|
8720c172b0 | ||
|
|
4922ba1082 | ||
|
|
24d91ae7cc | ||
|
|
3f6fcd408e | ||
|
|
643bd8ee80 | ||
|
|
d8195aede5 | ||
|
|
88a7f64510 | ||
|
|
4884b953ce | ||
|
|
d85dd443e0 | ||
|
|
76255dc098 | ||
|
|
aab1d1b48d | ||
|
|
a6b8643941 | ||
|
|
dd99108afd | ||
|
|
23f7c50106 | ||
|
|
55da380795 | ||
|
|
912536c620 | ||
|
|
73e4670f8b | ||
|
|
9e7c2cbf5a | ||
|
|
9dbb8d4001 | ||
|
|
56b39b698d | ||
|
|
2f545a343f | ||
|
|
28eb0a01bd | ||
|
|
ebe2651ce8 | ||
|
|
91eb8485f3 | ||
|
|
9fd02b75a8 | ||
|
|
b355245a9c | ||
|
|
a24c8f66a5 |
@@ -1,8 +0,0 @@
|
||||
/build/
|
||||
/config/
|
||||
/dist/
|
||||
/static/
|
||||
/*.js
|
||||
|
||||
src/common/fork/*
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
// https://eslint.org/docs/user-guide/configuring
|
||||
|
||||
module.exports = {
|
||||
root: true,
|
||||
parser: 'babel-eslint',
|
||||
parserOptions: {
|
||||
sourceType: 'module'
|
||||
},
|
||||
env: {
|
||||
browser: true,
|
||||
},
|
||||
// https://github.com/standard/standard/blob/master/docs/RULES-en.md
|
||||
extends: 'standard',
|
||||
// required to lint *.vue files
|
||||
plugins: [
|
||||
'html'
|
||||
],
|
||||
// add your custom rules here
|
||||
'rules': {
|
||||
// allow paren-less arrow functions
|
||||
'arrow-parens': 0,
|
||||
// allow async-await
|
||||
'generator-star-spacing': 0,
|
||||
// allow debugger during development
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
|
||||
|
||||
//ignore the paren check before function.
|
||||
'space-before-function-paren': [0, 'always'],
|
||||
//ignore the space before block.
|
||||
'space-before-blocks': [0, 'always'],
|
||||
//ignore the empty line check.
|
||||
'no-multiple-empty-lines': [0, {'max': 2}],
|
||||
//semicolon or no semicolon is ok.
|
||||
'semi': [0, 'always'],
|
||||
//ignore the space before or after =>
|
||||
'arrow-spacing': 0,
|
||||
//the type of quotes
|
||||
'quotes': [0, 'single'],
|
||||
//block can be padded by blank lines
|
||||
'padded-blocks': 0,
|
||||
//comma spacing before or after.
|
||||
'comma-spacing': 0,
|
||||
//key spacing.
|
||||
'key-spacing': [0, {'beforeColon': false, 'afterColon': true}],
|
||||
//trailing spaces
|
||||
'no-trailing-spaces': 0,
|
||||
//spaced comment
|
||||
'spaced-comment': 0,
|
||||
//keyword-spacing
|
||||
'keyword-spacing': 0,
|
||||
'space-in-parens': 0,
|
||||
'no-extend-native': 0,
|
||||
'no-useless-escape': 0,
|
||||
'no-unused-vars': 0,
|
||||
'no-undef': 0,
|
||||
'no-tabs': 0,
|
||||
'indent': 0,
|
||||
'no-multi-spaces': 0,
|
||||
'eol-last': 0,
|
||||
'no-template-curly-in-string': 0,
|
||||
'no-mixed-spaces-and-tabs': 0,
|
||||
'handle-callback-err': 0,
|
||||
"import/no-webpack-loader-syntax": "off",
|
||||
'object-curly-spacing': 0,
|
||||
'comma-dangle': 0
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,27 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
node_modules/
|
||||
/dist/
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
yarn.lock
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
@@ -12,3 +30,7 @@ yarn-error.log*
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
draft.html
|
||||
|
||||
report.*.json
|
||||
draft.txt
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
# 蓝眼云盘
|
||||
|
||||
2018-04-12
|
||||
tank-1.0.3
|
||||
1. 添加了多文件同时上传的功能.
|
||||
2. 开发情况下有可能上传的文件路径没有权限,添加了更多提示.
|
||||
|
||||
2018-01-19
|
||||
tank-1.0.2
|
||||
1. 修复了下载时无法估算文件大小的bug,header头重添加了Content-Type. [#2](https://github.com/eyebluecn/tank/issues/2)
|
||||
2. 修复了移动端样式混乱的问题.[#3](https://github.com/eyebluecn/tank/issues/3)
|
||||
3. 修复了文夹层数无上限的bug. [#4](https://github.com/eyebluecn/tank/issues/4)
|
||||
4. 修复了文件夹自己移动到自己后就全部消失的bug. [#8](https://github.com/eyebluecn/tank/issues/8)
|
||||
5. 统一不能删除用户,但是可以禁用或者启用用户. [#9](https://github.com/eyebluecn/tank/issues/9)
|
||||
|
||||
|
||||
2018-01-12
|
||||
tank-1.0.1
|
||||
1. 修复面包屑回退的bug [#1](https://github.com/eyebluecn/tank/issues/1)
|
||||
2. 修复移动文件时,可能移到其他人的文件夹下的bug
|
||||
3. 新增404页面
|
||||
4. 移除掉一些没用的代码
|
||||
|
||||
|
||||
2018-01-01
|
||||
tank-1.0.0
|
||||
完成基本核心功能
|
||||
@@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 蓝眼
|
||||
|
||||
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.
|
||||
@@ -1,70 +1,51 @@
|
||||

|
||||
[](https://github.com/eyebluecn/tank)
|
||||
|
||||
# 蓝眼云盘前端
|
||||
[English Version](https://tank-doc.eyeblue.cn/en)
|
||||
|
||||
##### [在线Demo](http://tank.eyeblue.cn) (体验账号: demo 密码:123456)
|
||||
# 蓝眼云盘(3.1.2)
|
||||
[在线Demo](https://tank.eyeblue.cn) (体验账号: demo 密码:123456)
|
||||
|
||||
##### [配套后端tank](https://github.com/eyebluecn/tank)
|
||||
蓝眼云盘是蓝眼开源系列代表作品之一,致力于打造精致,优雅,简约的云盘。核心功能如下:
|
||||
1. 文件列表
|
||||
2. 文件/文件夹上传 + 拖拽上传
|
||||
3. 文件分享
|
||||
4. 文件监控统计
|
||||
5. 回收站
|
||||
6. 多用户
|
||||
7. [WebDav](https://tank-doc.eyeblue.cn/advance/webdav.html)
|
||||
8. [扫描磁盘任务](https://tank-doc.eyeblue.cn/advance/scan.html)
|
||||
9. [在线预览及自定义配置预览引擎](https://tank-doc.eyeblue.cn/advance/preview.html)
|
||||
|
||||
### 简介
|
||||
蓝眼云盘是前后端彻底分离的项目,本项目主要为后端提供静态资源文件。更多关于蓝眼云盘的介绍,请参考[蓝眼云盘后端](https://github.com/eyebluecn/tank)
|
||||
[更多内容请移步至文档](https://tank-doc.eyeblue.cn/)
|
||||
|
||||
如果您觉得蓝眼云盘对您有帮助,请不要吝惜您的star :smile:
|
||||
|
||||
### 技术栈
|
||||
|
||||
vue2.0 + vue-router + vuex + vue-resource + webpack + es6 + less
|
||||
|
||||
|
||||
### 运行
|
||||
|
||||
```
|
||||
npm install
|
||||
|
||||
npm run serve
|
||||
```
|
||||
|
||||
### 打包
|
||||
|
||||
```
|
||||
npm run build
|
||||
```
|
||||
打包的结果在`dist`文件夹下,将该文件夹下的内容放置在[后端tank](https://github.com/eyebluecn/tank)的`build/html`文件夹下即可。
|
||||
|
||||
|
||||
### 配套后端
|
||||
此项目有配套后端项目,对golang感兴趣的同学可以猛戳 [配套后端tank](https://github.com/eyebluecn/tank)
|
||||
|
||||
### 总结
|
||||
1、 蓝眼的宗旨是专注于开源精致而优雅的软件,所以在代码的构建过程中我们不停地思考与迭代,追求最优质的代码。
|
||||
|
||||
2、 蓝眼云盘前端代码的构建完全面向对象,可扩展能力强,涉及多用户,多权限功能。
|
||||
|
||||
3、 蓝眼云盘后端采用了更贴近底层golang语言,更加适用于文件传输类的软件,速度更快,用户体验更好。
|
||||
|
||||
### Contribution
|
||||
|
||||
感谢所有蓝眼云盘的贡献者 [@zicla](https://github.com/zicla),[@seaheart](https://github.com/seaheart),@heying,[@hxsherry](https://github.com/hxsherry)
|
||||
|
||||
如果您也想参与进来,请尽情的fork, star, post issue, pull requests
|
||||
前端技术栈:Typescript + React + Ant Design 4.0 + OOP
|
||||
|
||||
### 软件截图
|
||||
|
||||
#### PC端截图
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
#### 手机端截图
|
||||
|
||||

|
||||

|
||||
|
||||
## [安装文档](https://tank-doc.eyeblue.cn/basic/install.html)
|
||||
|
||||
### Contribution
|
||||
|
||||
感谢所有蓝眼云盘的贡献者 [@zicla](https://github.com/zicla),[@seaheart](https://github.com/seaheart),[@yemuhe](https://github.com/yemuhe),[@hxsherry](https://github.com/hxsherry)
|
||||
|
||||
如果您也想参与进来,请尽情的fork, star, post issue, pull requests
|
||||
|
||||
当然你可以加入钉钉群一起直接交流,在钉钉群中可以获取最新beta版本。
|
||||
|
||||

|
||||
|
||||
群号:23156361
|
||||
|
||||
### License
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
module.exports = {
|
||||
presets: [
|
||||
'@vue/app'
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const paths = require('./paths');
|
||||
|
||||
// Make sure that including paths.js after env.js will read .env variables.
|
||||
delete require.cache[require.resolve('./paths')];
|
||||
|
||||
const NODE_ENV = process.env.NODE_ENV;
|
||||
if (!NODE_ENV) {
|
||||
throw new Error(
|
||||
'The NODE_ENV environment variable is required but was not specified.'
|
||||
);
|
||||
}
|
||||
|
||||
// https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use
|
||||
const dotenvFiles = [
|
||||
`${paths.dotenv}.${NODE_ENV}.local`,
|
||||
`${paths.dotenv}.${NODE_ENV}`,
|
||||
// Don't include `.env.local` for `test` environment
|
||||
// since normally you expect tests to produce the same
|
||||
// results for everyone
|
||||
NODE_ENV !== 'test' && `${paths.dotenv}.local`,
|
||||
paths.dotenv,
|
||||
].filter(Boolean);
|
||||
|
||||
// Load environment variables from .env* files. Suppress warnings using silent
|
||||
// if this file is missing. dotenv will never modify any environment variables
|
||||
// that have already been set. Variable expansion is supported in .env files.
|
||||
// https://github.com/motdotla/dotenv
|
||||
// https://github.com/motdotla/dotenv-expand
|
||||
dotenvFiles.forEach(dotenvFile => {
|
||||
if (fs.existsSync(dotenvFile)) {
|
||||
require('dotenv-expand')(
|
||||
require('dotenv').config({
|
||||
path: dotenvFile,
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// We support resolving modules according to `NODE_PATH`.
|
||||
// This lets you use absolute paths in imports inside large monorepos:
|
||||
// https://github.com/facebook/create-react-app/issues/253.
|
||||
// It works similar to `NODE_PATH` in Node itself:
|
||||
// https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders
|
||||
// Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored.
|
||||
// Otherwise, we risk importing Node.js core modules into an app instead of webpack shims.
|
||||
// https://github.com/facebook/create-react-app/issues/1023#issuecomment-265344421
|
||||
// We also resolve them to make sure all tools using them work consistently.
|
||||
const appDirectory = fs.realpathSync(process.cwd());
|
||||
process.env.NODE_PATH = (process.env.NODE_PATH || '')
|
||||
.split(path.delimiter)
|
||||
.filter(folder => folder && !path.isAbsolute(folder))
|
||||
.map(folder => path.resolve(appDirectory, folder))
|
||||
.join(path.delimiter);
|
||||
|
||||
// Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be
|
||||
// injected into the application via DefinePlugin in webpack configuration.
|
||||
const REACT_APP = /^REACT_APP_/i;
|
||||
|
||||
function getClientEnvironment(publicUrl) {
|
||||
const raw = Object.keys(process.env)
|
||||
.filter(key => REACT_APP.test(key))
|
||||
.reduce(
|
||||
(env, key) => {
|
||||
env[key] = process.env[key];
|
||||
return env;
|
||||
},
|
||||
{
|
||||
// Useful for determining whether we’re running in production mode.
|
||||
// Most importantly, it switches React into the correct mode.
|
||||
NODE_ENV: process.env.NODE_ENV || 'development',
|
||||
// Useful for resolving the correct path to static assets in `public`.
|
||||
// For example, <img src={process.env.PUBLIC_URL + '/img/logo.png'} />.
|
||||
// This should only be used as an escape hatch. Normally you would put
|
||||
// images into the `src` and `import` them in code to get their paths.
|
||||
PUBLIC_URL: publicUrl,
|
||||
// We support configuring the sockjs pathname during development.
|
||||
// These settings let a developer run multiple simultaneous projects.
|
||||
// They are used as the connection `hostname`, `pathname` and `port`
|
||||
// in webpackHotDevClient. They are used as the `sockHost`, `sockPath`
|
||||
// and `sockPort` options in webpack-dev-server.
|
||||
WDS_SOCKET_HOST: process.env.WDS_SOCKET_HOST,
|
||||
WDS_SOCKET_PATH: process.env.WDS_SOCKET_PATH,
|
||||
WDS_SOCKET_PORT: process.env.WDS_SOCKET_PORT,
|
||||
}
|
||||
);
|
||||
// Stringify all values so we can feed into webpack DefinePlugin
|
||||
const stringified = {
|
||||
'process.env': Object.keys(raw).reduce((env, key) => {
|
||||
env[key] = JSON.stringify(raw[key]);
|
||||
return env;
|
||||
}, {}),
|
||||
};
|
||||
|
||||
return { raw, stringified };
|
||||
}
|
||||
|
||||
module.exports = getClientEnvironment;
|
||||
@@ -0,0 +1,66 @@
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const crypto = require('crypto');
|
||||
const chalk = require('react-dev-utils/chalk');
|
||||
const paths = require('./paths');
|
||||
|
||||
// Ensure the certificate and key provided are valid and if not
|
||||
// throw an easy to debug error
|
||||
function validateKeyAndCerts({ cert, key, keyFile, crtFile }) {
|
||||
let encrypted;
|
||||
try {
|
||||
// publicEncrypt will throw an error with an invalid cert
|
||||
encrypted = crypto.publicEncrypt(cert, Buffer.from('test'));
|
||||
} catch (err) {
|
||||
throw new Error(
|
||||
`The certificate "${chalk.yellow(crtFile)}" is invalid.\n${err.message}`
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
// privateDecrypt will throw an error with an invalid key
|
||||
crypto.privateDecrypt(key, encrypted);
|
||||
} catch (err) {
|
||||
throw new Error(
|
||||
`The certificate key "${chalk.yellow(keyFile)}" is invalid.\n${
|
||||
err.message
|
||||
}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Read file and throw an error if it doesn't exist
|
||||
function readEnvFile(file, type) {
|
||||
if (!fs.existsSync(file)) {
|
||||
throw new Error(
|
||||
`You specified ${chalk.cyan(
|
||||
type
|
||||
)} in your env, but the file "${chalk.yellow(file)}" can't be found.`
|
||||
);
|
||||
}
|
||||
return fs.readFileSync(file);
|
||||
}
|
||||
|
||||
// Get the https config
|
||||
// Return cert files if provided in env, otherwise just true or false
|
||||
function getHttpsConfig() {
|
||||
const { SSL_CRT_FILE, SSL_KEY_FILE, HTTPS } = process.env;
|
||||
const isHttps = HTTPS === 'true';
|
||||
|
||||
if (isHttps && SSL_CRT_FILE && SSL_KEY_FILE) {
|
||||
const crtFile = path.resolve(paths.appPath, SSL_CRT_FILE);
|
||||
const keyFile = path.resolve(paths.appPath, SSL_KEY_FILE);
|
||||
const config = {
|
||||
cert: readEnvFile(crtFile, 'SSL_CRT_FILE'),
|
||||
key: readEnvFile(keyFile, 'SSL_KEY_FILE'),
|
||||
};
|
||||
|
||||
validateKeyAndCerts({ ...config, keyFile, crtFile });
|
||||
return config;
|
||||
}
|
||||
return isHttps;
|
||||
}
|
||||
|
||||
module.exports = getHttpsConfig;
|
||||
@@ -0,0 +1,14 @@
|
||||
'use strict';
|
||||
|
||||
// This is a custom Jest transformer turning style imports into empty objects.
|
||||
// http://facebook.github.io/jest/docs/en/webpack.html
|
||||
|
||||
module.exports = {
|
||||
process() {
|
||||
return 'module.exports = {};';
|
||||
},
|
||||
getCacheKey() {
|
||||
// The output is always the same.
|
||||
return 'cssTransform';
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,40 @@
|
||||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
const camelcase = require('camelcase');
|
||||
|
||||
// This is a custom Jest transformer turning file imports into filenames.
|
||||
// http://facebook.github.io/jest/docs/en/webpack.html
|
||||
|
||||
module.exports = {
|
||||
process(src, filename) {
|
||||
const assetFilename = JSON.stringify(path.basename(filename));
|
||||
|
||||
if (filename.match(/\.svg$/)) {
|
||||
// Based on how SVGR generates a component name:
|
||||
// https://github.com/smooth-code/svgr/blob/01b194cf967347d43d4cbe6b434404731b87cf27/packages/core/src/state.js#L6
|
||||
const pascalCaseFilename = camelcase(path.parse(filename).name, {
|
||||
pascalCase: true,
|
||||
});
|
||||
const componentName = `Svg${pascalCaseFilename}`;
|
||||
return `const React = require('react');
|
||||
module.exports = {
|
||||
__esModule: true,
|
||||
default: ${assetFilename},
|
||||
ReactComponent: React.forwardRef(function ${componentName}(props, ref) {
|
||||
return {
|
||||
$$typeof: Symbol.for('react.element'),
|
||||
type: 'svg',
|
||||
ref: ref,
|
||||
key: null,
|
||||
props: Object.assign({}, props, {
|
||||
children: ${assetFilename}
|
||||
})
|
||||
};
|
||||
}),
|
||||
};`;
|
||||
}
|
||||
|
||||
return `module.exports = ${assetFilename};`;
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,141 @@
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const paths = require('./paths');
|
||||
const chalk = require('react-dev-utils/chalk');
|
||||
const resolve = require('resolve');
|
||||
|
||||
/**
|
||||
* Get additional module paths based on the baseUrl of a compilerOptions object.
|
||||
*
|
||||
* @param {Object} options
|
||||
*/
|
||||
function getAdditionalModulePaths(options = {}) {
|
||||
const baseUrl = options.baseUrl;
|
||||
|
||||
// We need to explicitly check for null and undefined (and not a falsy value) because
|
||||
// TypeScript treats an empty string as `.`.
|
||||
if (baseUrl == null) {
|
||||
// If there's no baseUrl set we respect NODE_PATH
|
||||
// Note that NODE_PATH is deprecated and will be removed
|
||||
// in the next major release of create-react-app.
|
||||
|
||||
const nodePath = process.env.NODE_PATH || '';
|
||||
return nodePath.split(path.delimiter).filter(Boolean);
|
||||
}
|
||||
|
||||
const baseUrlResolved = path.resolve(paths.appPath, baseUrl);
|
||||
|
||||
// We don't need to do anything if `baseUrl` is set to `node_modules`. This is
|
||||
// the default behavior.
|
||||
if (path.relative(paths.appNodeModules, baseUrlResolved) === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Allow the user set the `baseUrl` to `appSrc`.
|
||||
if (path.relative(paths.appSrc, baseUrlResolved) === '') {
|
||||
return [paths.appSrc];
|
||||
}
|
||||
|
||||
// If the path is equal to the root directory we ignore it here.
|
||||
// We don't want to allow importing from the root directly as source files are
|
||||
// not transpiled outside of `src`. We do allow importing them with the
|
||||
// absolute path (e.g. `src/Components/Button.js`) but we set that up with
|
||||
// an alias.
|
||||
if (path.relative(paths.appPath, baseUrlResolved) === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Otherwise, throw an error.
|
||||
throw new Error(
|
||||
chalk.red.bold(
|
||||
"Your project's `baseUrl` can only be set to `src` or `node_modules`." +
|
||||
' Create React App does not support other values at this time.'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get webpack aliases based on the baseUrl of a compilerOptions object.
|
||||
*
|
||||
* @param {*} options
|
||||
*/
|
||||
function getWebpackAliases(options = {}) {
|
||||
const baseUrl = options.baseUrl;
|
||||
|
||||
if (!baseUrl) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const baseUrlResolved = path.resolve(paths.appPath, baseUrl);
|
||||
|
||||
if (path.relative(paths.appPath, baseUrlResolved) === '') {
|
||||
return {
|
||||
src: paths.appSrc,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get jest aliases based on the baseUrl of a compilerOptions object.
|
||||
*
|
||||
* @param {*} options
|
||||
*/
|
||||
function getJestAliases(options = {}) {
|
||||
const baseUrl = options.baseUrl;
|
||||
|
||||
if (!baseUrl) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const baseUrlResolved = path.resolve(paths.appPath, baseUrl);
|
||||
|
||||
if (path.relative(paths.appPath, baseUrlResolved) === '') {
|
||||
return {
|
||||
'^src/(.*)$': '<rootDir>/src/$1',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function getModules() {
|
||||
// Check if TypeScript is setup
|
||||
const hasTsConfig = fs.existsSync(paths.appTsConfig);
|
||||
const hasJsConfig = fs.existsSync(paths.appJsConfig);
|
||||
|
||||
if (hasTsConfig && hasJsConfig) {
|
||||
throw new Error(
|
||||
'You have both a tsconfig.json and a jsconfig.json. If you are using TypeScript please remove your jsconfig.json file.'
|
||||
);
|
||||
}
|
||||
|
||||
let config;
|
||||
|
||||
// If there's a tsconfig.json we assume it's a
|
||||
// TypeScript project and set up the config
|
||||
// based on tsconfig.json
|
||||
if (hasTsConfig) {
|
||||
const ts = require(resolve.sync('typescript', {
|
||||
basedir: paths.appNodeModules,
|
||||
}));
|
||||
config = ts.readConfigFile(paths.appTsConfig, ts.sys.readFile).config;
|
||||
// Otherwise we'll check if there is jsconfig.json
|
||||
// for non TS projects.
|
||||
} else if (hasJsConfig) {
|
||||
config = require(paths.appJsConfig);
|
||||
}
|
||||
|
||||
config = config || {};
|
||||
const options = config.compilerOptions || {};
|
||||
|
||||
const additionalModulePaths = getAdditionalModulePaths(options);
|
||||
|
||||
return {
|
||||
additionalModulePaths: additionalModulePaths,
|
||||
webpackAliases: getWebpackAliases(options),
|
||||
jestAliases: getJestAliases(options),
|
||||
hasTsConfig,
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = getModules();
|
||||
@@ -0,0 +1,72 @@
|
||||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const getPublicUrlOrPath = require('react-dev-utils/getPublicUrlOrPath');
|
||||
|
||||
// Make sure any symlinks in the project folder are resolved:
|
||||
// https://github.com/facebook/create-react-app/issues/637
|
||||
const appDirectory = fs.realpathSync(process.cwd());
|
||||
const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
|
||||
|
||||
// We use `PUBLIC_URL` environment variable or "homepage" field to infer
|
||||
// "public path" at which the app is served.
|
||||
// webpack needs to know it to put the right <script> hrefs into HTML even in
|
||||
// single-page apps that may serve index.html for nested URLs like /todos/42.
|
||||
// We can't use a relative path in HTML because we don't want to load something
|
||||
// like /todos/42/static/js/bundle.7289d.js. We have to know the root.
|
||||
const publicUrlOrPath = getPublicUrlOrPath(
|
||||
process.env.NODE_ENV === 'development',
|
||||
require(resolveApp('package.json')).homepage,
|
||||
process.env.PUBLIC_URL
|
||||
);
|
||||
|
||||
const moduleFileExtensions = [
|
||||
'web.mjs',
|
||||
'mjs',
|
||||
'web.js',
|
||||
'js',
|
||||
'web.ts',
|
||||
'ts',
|
||||
'web.tsx',
|
||||
'tsx',
|
||||
'json',
|
||||
'web.jsx',
|
||||
'jsx',
|
||||
];
|
||||
|
||||
// Resolve file paths in the same order as webpack
|
||||
const resolveModule = (resolveFn, filePath) => {
|
||||
const extension = moduleFileExtensions.find(extension =>
|
||||
fs.existsSync(resolveFn(`${filePath}.${extension}`))
|
||||
);
|
||||
|
||||
if (extension) {
|
||||
return resolveFn(`${filePath}.${extension}`);
|
||||
}
|
||||
|
||||
return resolveFn(`${filePath}.js`);
|
||||
};
|
||||
|
||||
// config after eject: we're in ./config/
|
||||
module.exports = {
|
||||
dotenv: resolveApp('.env'),
|
||||
appPath: resolveApp('.'),
|
||||
appBuild: resolveApp('build'),
|
||||
appPublic: resolveApp('public'),
|
||||
appHtml: resolveApp('public/index.html'),
|
||||
appIndexJs: resolveModule(resolveApp, 'src/index'),
|
||||
appPackageJson: resolveApp('package.json'),
|
||||
appSrc: resolveApp('src'),
|
||||
appTsConfig: resolveApp('tsconfig.json'),
|
||||
appJsConfig: resolveApp('jsconfig.json'),
|
||||
yarnLockFile: resolveApp('yarn.lock'),
|
||||
testsSetup: resolveModule(resolveApp, 'src/setupTests'),
|
||||
proxySetup: resolveApp('config/setupProxy.js'),
|
||||
appNodeModules: resolveApp('node_modules'),
|
||||
publicUrlOrPath,
|
||||
};
|
||||
|
||||
|
||||
|
||||
module.exports.moduleFileExtensions = moduleFileExtensions;
|
||||
@@ -0,0 +1,35 @@
|
||||
'use strict';
|
||||
|
||||
const { resolveModuleName } = require('ts-pnp');
|
||||
|
||||
exports.resolveModuleName = (
|
||||
typescript,
|
||||
moduleName,
|
||||
containingFile,
|
||||
compilerOptions,
|
||||
resolutionHost
|
||||
) => {
|
||||
return resolveModuleName(
|
||||
moduleName,
|
||||
containingFile,
|
||||
compilerOptions,
|
||||
resolutionHost,
|
||||
typescript.resolveModuleName
|
||||
);
|
||||
};
|
||||
|
||||
exports.resolveTypeReferenceDirective = (
|
||||
typescript,
|
||||
moduleName,
|
||||
containingFile,
|
||||
compilerOptions,
|
||||
resolutionHost
|
||||
) => {
|
||||
return resolveModuleName(
|
||||
moduleName,
|
||||
containingFile,
|
||||
compilerOptions,
|
||||
resolutionHost,
|
||||
typescript.resolveTypeReferenceDirective
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
const proxy = require('http-proxy-middleware');
|
||||
|
||||
module.exports = function (app) {
|
||||
|
||||
//为了解决前端开发时跨域问题,配置后台接口代理。
|
||||
app.use(proxy(
|
||||
'/api',
|
||||
{
|
||||
target: 'http://localhost:6010',
|
||||
changeOrigin: true,
|
||||
pathRewrite: {
|
||||
'^/api': '/api'
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
};
|
||||
@@ -0,0 +1,691 @@
|
||||
"use strict";
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const webpack = require("webpack");
|
||||
const resolve = require("resolve");
|
||||
const PnpWebpackPlugin = require("pnp-webpack-plugin");
|
||||
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
||||
const CaseSensitivePathsPlugin = require("case-sensitive-paths-webpack-plugin");
|
||||
const InlineChunkHtmlPlugin = require("react-dev-utils/InlineChunkHtmlPlugin");
|
||||
const TerserPlugin = require("terser-webpack-plugin");
|
||||
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
||||
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
|
||||
const safePostCssParser = require("postcss-safe-parser");
|
||||
const ManifestPlugin = require("webpack-manifest-plugin");
|
||||
const InterpolateHtmlPlugin = require("react-dev-utils/InterpolateHtmlPlugin");
|
||||
const WatchMissingNodeModulesPlugin = require("react-dev-utils/WatchMissingNodeModulesPlugin");
|
||||
const ModuleScopePlugin = require("react-dev-utils/ModuleScopePlugin");
|
||||
const getCSSModuleLocalIdent = require("react-dev-utils/getCSSModuleLocalIdent");
|
||||
const paths = require("./paths");
|
||||
const modules = require("./modules");
|
||||
const getClientEnvironment = require("./env");
|
||||
const ModuleNotFoundPlugin = require("react-dev-utils/ModuleNotFoundPlugin");
|
||||
const ForkTsCheckerWebpackPlugin = require("react-dev-utils/ForkTsCheckerWebpackPlugin");
|
||||
const typescriptFormatter = require("react-dev-utils/typescriptFormatter");
|
||||
|
||||
const postcssNormalize = require("postcss-normalize");
|
||||
|
||||
const appPackageJson = require(paths.appPackageJson);
|
||||
|
||||
// Source maps are resource heavy and can cause out of memory issue for large source files.
|
||||
const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== "false";
|
||||
// Some apps do not need the benefits of saving a web request, so not inlining the chunk
|
||||
// makes for a smoother build process.
|
||||
const shouldInlineRuntimeChunk = process.env.INLINE_RUNTIME_CHUNK !== "false";
|
||||
|
||||
const imageInlineSizeLimit = parseInt(
|
||||
process.env.IMAGE_INLINE_SIZE_LIMIT || "10000"
|
||||
);
|
||||
|
||||
// Check if TypeScript is setup
|
||||
const useTypeScript = fs.existsSync(paths.appTsConfig);
|
||||
|
||||
// style files regexes
|
||||
const cssRegex = /\.css$/;
|
||||
const cssModuleRegex = /\.module\.css$/;
|
||||
const sassRegex = /\.(scss|sass)$/;
|
||||
const sassModuleRegex = /\.module\.(scss|sass)$/;
|
||||
|
||||
const lessRegex = /\.less$/;
|
||||
const lessModuleRegex = /\.module\.less$/;
|
||||
|
||||
// This is the production and development configuration.
|
||||
// It is focused on developer experience, fast rebuilds, and a minimal bundle.
|
||||
module.exports = function (webpackEnv) {
|
||||
const isEnvDevelopment = webpackEnv === "development";
|
||||
const isEnvProduction = webpackEnv === "production";
|
||||
|
||||
// Variable used for enabling profiling in Production
|
||||
// passed into alias object. Uses a flag if passed into the build command
|
||||
const isEnvProductionProfile =
|
||||
isEnvProduction && process.argv.includes("--profile");
|
||||
|
||||
// We will provide `paths.publicUrlOrPath` to our app
|
||||
// as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript.
|
||||
// Omit trailing slash as %PUBLIC_URL%/xyz looks better than %PUBLIC_URL%xyz.
|
||||
// Get environment variables to inject into our app.
|
||||
const env = getClientEnvironment(paths.publicUrlOrPath.slice(0, -1));
|
||||
|
||||
// common function to get style loaders
|
||||
const getStyleLoaders = (cssOptions, preProcessor) => {
|
||||
const loaders = [
|
||||
isEnvDevelopment && require.resolve("style-loader"),
|
||||
isEnvProduction && {
|
||||
loader: MiniCssExtractPlugin.loader,
|
||||
// css is located in `static/css`, use '../../' to locate index.html folder
|
||||
// in production `paths.publicUrlOrPath` can be a relative path
|
||||
options: paths.publicUrlOrPath.startsWith(".")
|
||||
? { publicPath: "../../" }
|
||||
: {},
|
||||
},
|
||||
{
|
||||
loader: require.resolve("css-loader"),
|
||||
options: cssOptions,
|
||||
},
|
||||
{
|
||||
// Options for PostCSS as we reference these options twice
|
||||
// Adds vendor prefixing based on your specified browser support in
|
||||
// package.json
|
||||
loader: require.resolve("postcss-loader"),
|
||||
options: {
|
||||
// Necessary for external CSS imports to work
|
||||
// https://github.com/facebook/create-react-app/issues/2677
|
||||
ident: "postcss",
|
||||
plugins: () => [
|
||||
require("postcss-flexbugs-fixes"),
|
||||
require("postcss-preset-env")({
|
||||
autoprefixer: {
|
||||
flexbox: "no-2009",
|
||||
},
|
||||
stage: 3,
|
||||
}),
|
||||
// Adds PostCSS Normalize as the reset css with default options,
|
||||
// so that it honors browserslist config in package.json
|
||||
// which in turn let's users customize the target behavior as per their needs.
|
||||
postcssNormalize(),
|
||||
],
|
||||
sourceMap: isEnvProduction && shouldUseSourceMap,
|
||||
},
|
||||
},
|
||||
].filter(Boolean);
|
||||
if (preProcessor) {
|
||||
loaders.push(
|
||||
{
|
||||
loader: require.resolve("resolve-url-loader"),
|
||||
options: {
|
||||
sourceMap: isEnvProduction && shouldUseSourceMap,
|
||||
},
|
||||
},
|
||||
preProcessor
|
||||
);
|
||||
}
|
||||
return loaders;
|
||||
};
|
||||
|
||||
return {
|
||||
mode: isEnvProduction ? "production" : isEnvDevelopment && "development",
|
||||
// Stop compilation early in production
|
||||
bail: isEnvProduction,
|
||||
devtool: isEnvProduction
|
||||
? shouldUseSourceMap
|
||||
? "source-map"
|
||||
: false
|
||||
: isEnvDevelopment && "cheap-module-source-map",
|
||||
// These are the "entry points" to our application.
|
||||
// This means they will be the "root" imports that are included in JS bundle.
|
||||
entry: [
|
||||
// Include an alternative client for WebpackDevServer. A client's job is to
|
||||
// connect to WebpackDevServer by a socket and get notified about changes.
|
||||
// When you save a file, the client will either apply hot updates (in case
|
||||
// of CSS changes), or refresh the page (in case of JS changes). When you
|
||||
// make a syntax error, this client will display a syntax error overlay.
|
||||
// Note: instead of the default WebpackDevServer client, we use a custom one
|
||||
// to bring better experience for Create React App users. You can replace
|
||||
// the line below with these two lines if you prefer the stock client:
|
||||
// require.resolve('webpack-dev-server/client') + '?/',
|
||||
// require.resolve('webpack/hot/dev-server'),
|
||||
isEnvDevelopment &&
|
||||
require.resolve("react-dev-utils/webpackHotDevClient"),
|
||||
// Finally, this is your app's code:
|
||||
paths.appIndexJs,
|
||||
// We include the app code last so that if there is a runtime error during
|
||||
// initialization, it doesn't blow up the WebpackDevServer client, and
|
||||
// changing JS code would still trigger a refresh.
|
||||
].filter(Boolean),
|
||||
output: {
|
||||
// The build folder.
|
||||
path: isEnvProduction ? paths.appBuild : undefined,
|
||||
// Add /* filename */ comments to generated require()s in the output.
|
||||
pathinfo: isEnvDevelopment,
|
||||
// There will be one main bundle, and one file per asynchronous chunk.
|
||||
// In development, it does not produce real files.
|
||||
filename: isEnvProduction
|
||||
? "static/js/[name].[contenthash:8].js"
|
||||
: isEnvDevelopment && "static/js/bundle.js",
|
||||
// TODO: remove this when upgrading to webpack 5
|
||||
futureEmitAssets: true,
|
||||
// There are also additional JS chunk files if you use code splitting.
|
||||
chunkFilename: isEnvProduction
|
||||
? "static/js/[name].[contenthash:8].chunk.js"
|
||||
: isEnvDevelopment && "static/js/[name].chunk.js",
|
||||
// webpack uses `publicPath` to determine where the app is being served from.
|
||||
// It requires a trailing slash, or the file assets will get an incorrect path.
|
||||
// We inferred the "public path" (such as / or /my-project) from homepage.
|
||||
publicPath: paths.publicUrlOrPath,
|
||||
// Point sourcemap entries to original disk location (format as URL on Windows)
|
||||
devtoolModuleFilenameTemplate: isEnvProduction
|
||||
? (info) =>
|
||||
path
|
||||
.relative(paths.appSrc, info.absoluteResourcePath)
|
||||
.replace(/\\/g, "/")
|
||||
: isEnvDevelopment &&
|
||||
((info) =>
|
||||
path.resolve(info.absoluteResourcePath).replace(/\\/g, "/")),
|
||||
// Prevents conflicts when multiple webpack runtimes (from different apps)
|
||||
// are used on the same page.
|
||||
jsonpFunction: `webpackJsonp${appPackageJson.name}`,
|
||||
// this defaults to 'window', but by setting it to 'this' then
|
||||
// module chunks which are built will work in web workers as well.
|
||||
globalObject: "this",
|
||||
},
|
||||
optimization: {
|
||||
minimize: isEnvProduction,
|
||||
minimizer: [
|
||||
// This is only used in production mode
|
||||
new TerserPlugin({
|
||||
terserOptions: {
|
||||
parse: {
|
||||
// We want terser to parse ecma 8 code. However, we don't want it
|
||||
// to apply any minification steps that turns valid ecma 5 code
|
||||
// into invalid ecma 5 code. This is why the 'compress' and 'output'
|
||||
// sections only apply transformations that are ecma 5 safe
|
||||
// https://github.com/facebook/create-react-app/pull/4234
|
||||
ecma: 8,
|
||||
},
|
||||
compress: {
|
||||
ecma: 5,
|
||||
warnings: false,
|
||||
// Disabled because of an issue with Uglify breaking seemingly valid code:
|
||||
// https://github.com/facebook/create-react-app/issues/2376
|
||||
// Pending further investigation:
|
||||
// https://github.com/mishoo/UglifyJS2/issues/2011
|
||||
comparisons: false,
|
||||
// Disabled because of an issue with Terser breaking valid code:
|
||||
// https://github.com/facebook/create-react-app/issues/5250
|
||||
// Pending further investigation:
|
||||
// https://github.com/terser-js/terser/issues/120
|
||||
inline: 2,
|
||||
//保持类名 by zicla
|
||||
keep_fnames: true,
|
||||
},
|
||||
mangle: {
|
||||
safari10: true,
|
||||
//保持类名 by zicla
|
||||
keep_fnames: true,
|
||||
},
|
||||
// Added for profiling in devtools
|
||||
keep_classnames: isEnvProductionProfile,
|
||||
keep_fnames: isEnvProductionProfile,
|
||||
output: {
|
||||
ecma: 5,
|
||||
comments: false,
|
||||
// Turned on because emoji and regex is not minified properly using default
|
||||
// https://github.com/facebook/create-react-app/issues/2488
|
||||
ascii_only: true,
|
||||
},
|
||||
},
|
||||
sourceMap: shouldUseSourceMap,
|
||||
}),
|
||||
// This is only used in production mode
|
||||
new OptimizeCSSAssetsPlugin({
|
||||
cssProcessorOptions: {
|
||||
parser: safePostCssParser,
|
||||
map: shouldUseSourceMap
|
||||
? {
|
||||
// `inline: false` forces the sourcemap to be output into a
|
||||
// separate file
|
||||
inline: false,
|
||||
// `annotation: true` appends the sourceMappingURL to the end of
|
||||
// the css file, helping the browser find the sourcemap
|
||||
annotation: true,
|
||||
}
|
||||
: false,
|
||||
},
|
||||
cssProcessorPluginOptions: {
|
||||
preset: ["default", { minifyFontValues: { removeQuotes: false } }],
|
||||
},
|
||||
}),
|
||||
],
|
||||
// Automatically split vendor and commons
|
||||
// https://twitter.com/wSokra/status/969633336732905474
|
||||
// https://medium.com/webpack/webpack-4-code-splitting-chunk-graph-and-the-splitchunks-optimization-be739a861366
|
||||
splitChunks: {
|
||||
chunks: "all",
|
||||
name: false,
|
||||
},
|
||||
// Keep the runtime chunk separated to enable long term caching
|
||||
// https://twitter.com/wSokra/status/969679223278505985
|
||||
// https://github.com/facebook/create-react-app/issues/5358
|
||||
runtimeChunk: {
|
||||
name: (entrypoint) => `runtime-${entrypoint.name}`,
|
||||
},
|
||||
},
|
||||
resolve: {
|
||||
// This allows you to set a fallback for where webpack should look for modules.
|
||||
// We placed these paths second because we want `node_modules` to "win"
|
||||
// if there are any conflicts. This matches Node resolution mechanism.
|
||||
// https://github.com/facebook/create-react-app/issues/253
|
||||
modules: ["node_modules", paths.appNodeModules].concat(
|
||||
modules.additionalModulePaths || []
|
||||
),
|
||||
// These are the reasonable defaults supported by the Node ecosystem.
|
||||
// We also include JSX as a common component filename extension to support
|
||||
// some tools, although we do not recommend using it, see:
|
||||
// https://github.com/facebook/create-react-app/issues/290
|
||||
// `web` extension prefixes have been added for better support
|
||||
// for React Native Web.
|
||||
extensions: paths.moduleFileExtensions
|
||||
.map((ext) => `.${ext}`)
|
||||
.filter((ext) => useTypeScript || !ext.includes("ts")),
|
||||
alias: {
|
||||
// Support React Native Web
|
||||
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
|
||||
"react-native": "react-native-web",
|
||||
// Allows for better profiling with ReactDevTools
|
||||
...(isEnvProductionProfile && {
|
||||
"react-dom$": "react-dom/profiling",
|
||||
"scheduler/tracing": "scheduler/tracing-profiling",
|
||||
}),
|
||||
...(modules.webpackAliases || {}),
|
||||
},
|
||||
plugins: [
|
||||
// Adds support for installing with Plug'n'Play, leading to faster installs and adding
|
||||
// guards against forgotten dependencies and such.
|
||||
PnpWebpackPlugin,
|
||||
// Prevents users from importing files from outside of src/ (or node_modules/).
|
||||
// This often causes confusion because we only process files within src/ with babel.
|
||||
// To fix this, we prevent you from importing files out of src/ -- if you'd like to,
|
||||
// please link the files into your node_modules/ and let module-resolution kick in.
|
||||
// Make sure your source files are compiled, as they will not be processed in any way.
|
||||
new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]),
|
||||
],
|
||||
},
|
||||
resolveLoader: {
|
||||
plugins: [
|
||||
// Also related to Plug'n'Play, but this time it tells webpack to load its loaders
|
||||
// from the current package.
|
||||
PnpWebpackPlugin.moduleLoader(module),
|
||||
],
|
||||
},
|
||||
module: {
|
||||
strictExportPresence: true,
|
||||
rules: [
|
||||
// Disable require.ensure as it's not a standard language feature.
|
||||
{ parser: { requireEnsure: false } },
|
||||
|
||||
{
|
||||
// "oneOf" will traverse all following loaders until one will
|
||||
// match the requirements. When no loader matches it will fall
|
||||
// back to the "file" loader at the end of the loader list.
|
||||
oneOf: [
|
||||
// "url" loader works like "file" loader except that it embeds assets
|
||||
// smaller than specified limit in bytes as data URLs to avoid requests.
|
||||
// A missing `test` is equivalent to a match.
|
||||
{
|
||||
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
|
||||
loader: require.resolve("url-loader"),
|
||||
options: {
|
||||
limit: imageInlineSizeLimit,
|
||||
name: "static/media/[name].[hash:8].[ext]",
|
||||
},
|
||||
},
|
||||
// Process application JS with Babel.
|
||||
// The preset includes JSX, Flow, TypeScript, and some ESnext features.
|
||||
{
|
||||
test: /\.(js|mjs|jsx|ts|tsx)$/,
|
||||
include: paths.appSrc,
|
||||
loader: require.resolve("babel-loader"),
|
||||
options: {
|
||||
customize: require.resolve(
|
||||
"babel-preset-react-app/webpack-overrides"
|
||||
),
|
||||
|
||||
plugins: [
|
||||
[
|
||||
require.resolve("babel-plugin-named-asset-import"),
|
||||
{
|
||||
loaderMap: {
|
||||
svg: {
|
||||
ReactComponent:
|
||||
"@svgr/webpack?-svgo,+titleProp,+ref![path]",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
// This is a feature of `babel-loader` for webpack (not Babel itself).
|
||||
// It enables caching results in ./node_modules/.cache/babel-loader/
|
||||
// directory for faster rebuilds.
|
||||
cacheDirectory: true,
|
||||
// See #6846 for context on why cacheCompression is disabled
|
||||
cacheCompression: false,
|
||||
compact: isEnvProduction,
|
||||
},
|
||||
},
|
||||
// Process any JS outside of the app with Babel.
|
||||
// Unlike the application JS, we only compile the standard ES features.
|
||||
{
|
||||
test: /\.(js|mjs)$/,
|
||||
exclude: /@babel(?:\/|\\{1,2})runtime/,
|
||||
loader: require.resolve("babel-loader"),
|
||||
options: {
|
||||
babelrc: false,
|
||||
configFile: false,
|
||||
compact: false,
|
||||
presets: [
|
||||
[
|
||||
require.resolve("babel-preset-react-app/dependencies"),
|
||||
{ helpers: true },
|
||||
],
|
||||
],
|
||||
cacheDirectory: true,
|
||||
// See #6846 for context on why cacheCompression is disabled
|
||||
cacheCompression: false,
|
||||
|
||||
// Babel sourcemaps are needed for debugging into node_modules
|
||||
// code. Without the options below, debuggers like VSCode
|
||||
// show incorrect code and set breakpoints on the wrong lines.
|
||||
sourceMaps: shouldUseSourceMap,
|
||||
inputSourceMap: shouldUseSourceMap,
|
||||
},
|
||||
},
|
||||
// "postcss" loader applies autoprefixer to our CSS.
|
||||
// "css" loader resolves paths in CSS and adds assets as dependencies.
|
||||
// "style" loader turns CSS into JS modules that inject <style> tags.
|
||||
// In production, we use MiniCSSExtractPlugin to extract that CSS
|
||||
// to a file, but in development "style" loader enables hot editing
|
||||
// of CSS.
|
||||
// By default we support CSS Modules with the extension .module.css
|
||||
{
|
||||
test: cssRegex,
|
||||
exclude: cssModuleRegex,
|
||||
use: getStyleLoaders({
|
||||
importLoaders: 1,
|
||||
sourceMap: isEnvProduction && shouldUseSourceMap,
|
||||
}),
|
||||
// Don't consider CSS imports dead code even if the
|
||||
// containing package claims to have no side effects.
|
||||
// Remove this when webpack adds a warning or an error for this.
|
||||
// See https://github.com/webpack/webpack/issues/6571
|
||||
sideEffects: true,
|
||||
},
|
||||
// Adds support for CSS Modules (https://github.com/css-modules/css-modules)
|
||||
// using the extension .module.css
|
||||
{
|
||||
test: cssModuleRegex,
|
||||
use: getStyleLoaders({
|
||||
importLoaders: 1,
|
||||
sourceMap: isEnvProduction && shouldUseSourceMap,
|
||||
modules: {
|
||||
getLocalIdent: getCSSModuleLocalIdent,
|
||||
},
|
||||
}),
|
||||
},
|
||||
// Opt-in support for SASS (using .scss or .sass extensions).
|
||||
// By default we support SASS Modules with the
|
||||
// extensions .module.scss or .module.sass
|
||||
{
|
||||
test: sassRegex,
|
||||
exclude: sassModuleRegex,
|
||||
use: getStyleLoaders(
|
||||
{
|
||||
importLoaders: 3,
|
||||
sourceMap: isEnvProduction && shouldUseSourceMap,
|
||||
},
|
||||
{
|
||||
loader: "sass-loader",
|
||||
options: {
|
||||
sourceMap: true,
|
||||
},
|
||||
}
|
||||
),
|
||||
// Don't consider CSS imports dead code even if the
|
||||
// containing package claims to have no side effects.
|
||||
// Remove this when webpack adds a warning or an error for this.
|
||||
// See https://github.com/webpack/webpack/issues/6571
|
||||
sideEffects: true,
|
||||
},
|
||||
// Adds support for CSS Modules, but using SASS
|
||||
// using the extension .module.scss or .module.sass
|
||||
{
|
||||
test: sassModuleRegex,
|
||||
use: getStyleLoaders(
|
||||
{
|
||||
importLoaders: 3,
|
||||
sourceMap: isEnvProduction && shouldUseSourceMap,
|
||||
modules: {
|
||||
getLocalIdent: getCSSModuleLocalIdent,
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: "sass-loader",
|
||||
options: {
|
||||
sourceMap: true,
|
||||
},
|
||||
}
|
||||
),
|
||||
},
|
||||
|
||||
// less-loader by zicla
|
||||
{
|
||||
test: lessRegex,
|
||||
exclude: lessModuleRegex,
|
||||
use: getStyleLoaders(
|
||||
{
|
||||
importLoaders: 2,
|
||||
sourceMap: isEnvProduction && shouldUseSourceMap,
|
||||
},
|
||||
{
|
||||
loader: "less-loader",
|
||||
options: {
|
||||
sourceMap: true,
|
||||
lessOptions: {
|
||||
modifyVars: {
|
||||
'primary-color': '#215891',
|
||||
},
|
||||
javascriptEnabled: true,
|
||||
}
|
||||
},
|
||||
}
|
||||
),
|
||||
sideEffects: true,
|
||||
},
|
||||
// less-loader by zicla
|
||||
{
|
||||
test: lessModuleRegex,
|
||||
use: getStyleLoaders(
|
||||
{
|
||||
importLoaders: 2,
|
||||
sourceMap: isEnvProduction && shouldUseSourceMap,
|
||||
modules: true,
|
||||
getLocalIdent: getCSSModuleLocalIdent,
|
||||
},
|
||||
{
|
||||
loader: "less-loader",
|
||||
options: {
|
||||
sourceMap: true,
|
||||
lessOptions: {
|
||||
modifyVars: {
|
||||
'primary-color': '#215891',
|
||||
},
|
||||
javascriptEnabled: true,
|
||||
}
|
||||
},
|
||||
}
|
||||
),
|
||||
},
|
||||
// "file" loader makes sure those assets get served by WebpackDevServer.
|
||||
// When you `import` an asset, you get its (virtual) filename.
|
||||
// In production, they would get copied to the `build` folder.
|
||||
// This loader doesn't use a "test" so it will catch all modules
|
||||
// that fall through the other loaders.
|
||||
{
|
||||
loader: require.resolve("file-loader"),
|
||||
// Exclude `js` files to keep "css" loader working as it injects
|
||||
// its runtime that would otherwise be processed through "file" loader.
|
||||
// Also exclude `html` and `json` extensions so they get processed
|
||||
// by webpacks internal loaders.
|
||||
exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
|
||||
options: {
|
||||
name: "static/media/[name].[hash:8].[ext]",
|
||||
},
|
||||
},
|
||||
// ** STOP ** Are you adding a new loader?
|
||||
// Make sure to add the new loader(s) before the "file" loader.
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
// Generates an `index.html` file with the <script> injected.
|
||||
new HtmlWebpackPlugin(
|
||||
Object.assign(
|
||||
{},
|
||||
{
|
||||
inject: true,
|
||||
template: paths.appHtml,
|
||||
},
|
||||
isEnvProduction
|
||||
? {
|
||||
minify: {
|
||||
removeComments: true,
|
||||
collapseWhitespace: true,
|
||||
removeRedundantAttributes: true,
|
||||
useShortDoctype: true,
|
||||
removeEmptyAttributes: true,
|
||||
removeStyleLinkTypeAttributes: true,
|
||||
keepClosingSlash: true,
|
||||
minifyJS: true,
|
||||
minifyCSS: true,
|
||||
minifyURLs: true,
|
||||
},
|
||||
}
|
||||
: undefined
|
||||
)
|
||||
),
|
||||
// Inlines the webpack runtime script. This script is too small to warrant
|
||||
// a network request.
|
||||
// https://github.com/facebook/create-react-app/issues/5358
|
||||
isEnvProduction &&
|
||||
shouldInlineRuntimeChunk &&
|
||||
new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime-.+[.]js/]),
|
||||
// Makes some environment variables available in index.html.
|
||||
// The public URL is available as %PUBLIC_URL% in index.html, e.g.:
|
||||
// <link rel="icon" href="%PUBLIC_URL%/favicon.ico">
|
||||
// It will be an empty string unless you specify "homepage"
|
||||
// in `package.json`, in which case it will be the pathname of that URL.
|
||||
new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),
|
||||
// This gives some necessary context to module not found errors, such as
|
||||
// the requesting resource.
|
||||
new ModuleNotFoundPlugin(paths.appPath),
|
||||
// Makes some environment variables available to the JS code, for example:
|
||||
// if (process.env.NODE_ENV === 'production') { ... }. See `./env.js`.
|
||||
// It is absolutely essential that NODE_ENV is set to production
|
||||
// during a production build.
|
||||
// Otherwise React will be compiled in the very slow development mode.
|
||||
new webpack.DefinePlugin(env.stringified),
|
||||
// This is necessary to emit hot updates (currently CSS only):
|
||||
isEnvDevelopment && new webpack.HotModuleReplacementPlugin(),
|
||||
// Watcher doesn't work well if you mistype casing in a path so we use
|
||||
// a plugin that prints an error when you attempt to do this.
|
||||
// See https://github.com/facebook/create-react-app/issues/240
|
||||
isEnvDevelopment && new CaseSensitivePathsPlugin(),
|
||||
// If you require a missing module and then `npm install` it, you still have
|
||||
// to restart the development server for webpack to discover it. This plugin
|
||||
// makes the discovery automatic so you don't have to restart.
|
||||
// See https://github.com/facebook/create-react-app/issues/186
|
||||
isEnvDevelopment &&
|
||||
new WatchMissingNodeModulesPlugin(paths.appNodeModules),
|
||||
isEnvProduction &&
|
||||
new MiniCssExtractPlugin({
|
||||
// Options similar to the same options in webpackOptions.output
|
||||
// both options are optional
|
||||
filename: "static/css/[name].[contenthash:8].css",
|
||||
chunkFilename: "static/css/[name].[contenthash:8].chunk.css",
|
||||
}),
|
||||
// Generate an asset manifest file with the following content:
|
||||
// - "files" key: Mapping of all asset filenames to their corresponding
|
||||
// output file so that tools can pick it up without having to parse
|
||||
// `index.html`
|
||||
// - "entrypoints" key: Array of files which are included in `index.html`,
|
||||
// can be used to reconstruct the HTML if necessary
|
||||
new ManifestPlugin({
|
||||
fileName: "asset-manifest.json",
|
||||
publicPath: paths.publicUrlOrPath,
|
||||
generate: (seed, files, entrypoints) => {
|
||||
const manifestFiles = files.reduce((manifest, file) => {
|
||||
manifest[file.name] = file.path;
|
||||
return manifest;
|
||||
}, seed);
|
||||
const entrypointFiles = entrypoints.main.filter(
|
||||
(fileName) => !fileName.endsWith(".map")
|
||||
);
|
||||
|
||||
return {
|
||||
files: manifestFiles,
|
||||
entrypoints: entrypointFiles,
|
||||
};
|
||||
},
|
||||
}),
|
||||
// Moment.js is an extremely popular library that bundles large locale files
|
||||
// by default due to how webpack interprets its code. This is a practical
|
||||
// solution that requires the user to opt into importing specific locales.
|
||||
// https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
|
||||
// You can remove this if you don't use Moment.js:
|
||||
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
|
||||
// TypeScript type checking
|
||||
useTypeScript &&
|
||||
new ForkTsCheckerWebpackPlugin({
|
||||
typescript: resolve.sync("typescript", {
|
||||
basedir: paths.appNodeModules,
|
||||
}),
|
||||
async: isEnvDevelopment,
|
||||
useTypescriptIncrementalApi: true,
|
||||
checkSyntacticErrors: true,
|
||||
resolveModuleNameModule: process.versions.pnp
|
||||
? `${__dirname}/pnpTs.js`
|
||||
: undefined,
|
||||
resolveTypeReferenceDirectiveModule: process.versions.pnp
|
||||
? `${__dirname}/pnpTs.js`
|
||||
: undefined,
|
||||
tsconfig: paths.appTsConfig,
|
||||
reportFiles: [
|
||||
"**",
|
||||
"!**/__tests__/**",
|
||||
"!**/?(*.)(spec|test).*",
|
||||
"!**/src/setupProxy.*",
|
||||
"!**/src/setupTests.*",
|
||||
],
|
||||
silent: true,
|
||||
// The formatter is invoked directly in WebpackDevServerUtils during development
|
||||
formatter: isEnvProduction ? typescriptFormatter : undefined,
|
||||
}),
|
||||
].filter(Boolean),
|
||||
// Some libraries import Node modules but don't use them in the browser.
|
||||
// Tell webpack to provide empty mocks for them so importing them works.
|
||||
node: {
|
||||
module: "empty",
|
||||
dgram: "empty",
|
||||
dns: "mock",
|
||||
fs: "empty",
|
||||
http2: "empty",
|
||||
net: "empty",
|
||||
tls: "empty",
|
||||
child_process: "empty",
|
||||
},
|
||||
// Turn off performance processing because we utilize
|
||||
// our own hints via the FileSizeReporter
|
||||
performance: false,
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,130 @@
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const errorOverlayMiddleware = require('react-dev-utils/errorOverlayMiddleware');
|
||||
const evalSourceMapMiddleware = require('react-dev-utils/evalSourceMapMiddleware');
|
||||
const noopServiceWorkerMiddleware = require('react-dev-utils/noopServiceWorkerMiddleware');
|
||||
const ignoredFiles = require('react-dev-utils/ignoredFiles');
|
||||
const redirectServedPath = require('react-dev-utils/redirectServedPathMiddleware');
|
||||
const paths = require('./paths');
|
||||
const getHttpsConfig = require('./getHttpsConfig');
|
||||
|
||||
const host = process.env.HOST || '0.0.0.0';
|
||||
const sockHost = process.env.WDS_SOCKET_HOST;
|
||||
const sockPath = process.env.WDS_SOCKET_PATH; // default: '/sockjs-node'
|
||||
const sockPort = process.env.WDS_SOCKET_PORT;
|
||||
|
||||
module.exports = function(proxy, allowedHost) {
|
||||
return {
|
||||
// WebpackDevServer 2.4.3 introduced a security fix that prevents remote
|
||||
// websites from potentially accessing local content through DNS rebinding:
|
||||
// https://github.com/webpack/webpack-dev-server/issues/887
|
||||
// https://medium.com/webpack/webpack-dev-server-middleware-security-issues-1489d950874a
|
||||
// However, it made several existing use cases such as development in cloud
|
||||
// environment or subdomains in development significantly more complicated:
|
||||
// https://github.com/facebook/create-react-app/issues/2271
|
||||
// https://github.com/facebook/create-react-app/issues/2233
|
||||
// While we're investigating better solutions, for now we will take a
|
||||
// compromise. Since our WDS configuration only serves files in the `public`
|
||||
// folder we won't consider accessing them a vulnerability. However, if you
|
||||
// use the `proxy` feature, it gets more dangerous because it can expose
|
||||
// remote code execution vulnerabilities in backends like Django and Rails.
|
||||
// So we will disable the host check normally, but enable it if you have
|
||||
// specified the `proxy` setting. Finally, we let you override it if you
|
||||
// really know what you're doing with a special environment variable.
|
||||
disableHostCheck:
|
||||
!proxy || process.env.DANGEROUSLY_DISABLE_HOST_CHECK === 'true',
|
||||
// Enable gzip compression of generated files.
|
||||
compress: true,
|
||||
// Silence WebpackDevServer's own logs since they're generally not useful.
|
||||
// It will still show compile warnings and errors with this setting.
|
||||
clientLogLevel: 'none',
|
||||
// By default WebpackDevServer serves physical files from current directory
|
||||
// in addition to all the virtual build products that it serves from memory.
|
||||
// This is confusing because those files won’t automatically be available in
|
||||
// production build folder unless we copy them. However, copying the whole
|
||||
// project directory is dangerous because we may expose sensitive files.
|
||||
// Instead, we establish a convention that only files in `public` directory
|
||||
// get served. Our build script will copy `public` into the `build` folder.
|
||||
// In `index.html`, you can get URL of `public` folder with %PUBLIC_URL%:
|
||||
// <link rel="icon" href="%PUBLIC_URL%/favicon.ico">
|
||||
// In JavaScript code, you can access it with `process.env.PUBLIC_URL`.
|
||||
// Note that we only recommend to use `public` folder as an escape hatch
|
||||
// for files like `favicon.ico`, `manifest.json`, and libraries that are
|
||||
// for some reason broken when imported through webpack. If you just want to
|
||||
// use an image, put it in `src` and `import` it from JavaScript instead.
|
||||
contentBase: paths.appPublic,
|
||||
contentBasePublicPath: paths.publicUrlOrPath,
|
||||
// By default files from `contentBase` will not trigger a page reload.
|
||||
watchContentBase: true,
|
||||
// Enable hot reloading server. It will provide WDS_SOCKET_PATH endpoint
|
||||
// for the WebpackDevServer client so it can learn when the files were
|
||||
// updated. The WebpackDevServer client is included as an entry point
|
||||
// in the webpack development configuration. Note that only changes
|
||||
// to CSS are currently hot reloaded. JS changes will refresh the browser.
|
||||
hot: true,
|
||||
// Use 'ws' instead of 'sockjs-node' on server since we're using native
|
||||
// websockets in `webpackHotDevClient`.
|
||||
transportMode: 'ws',
|
||||
// Prevent a WS client from getting injected as we're already including
|
||||
// `webpackHotDevClient`.
|
||||
injectClient: false,
|
||||
// Enable custom sockjs pathname for websocket connection to hot reloading server.
|
||||
// Enable custom sockjs hostname, pathname and port for websocket connection
|
||||
// to hot reloading server.
|
||||
sockHost,
|
||||
sockPath,
|
||||
sockPort,
|
||||
// It is important to tell WebpackDevServer to use the same "publicPath" path as
|
||||
// we specified in the webpack config. When homepage is '.', default to serving
|
||||
// from the root.
|
||||
// remove last slash so user can land on `/test` instead of `/test/`
|
||||
publicPath: paths.publicUrlOrPath.slice(0, -1),
|
||||
// WebpackDevServer is noisy by default so we emit custom message instead
|
||||
// by listening to the compiler events with `compiler.hooks[...].tap` calls above.
|
||||
quiet: true,
|
||||
// Reportedly, this avoids CPU overload on some systems.
|
||||
// https://github.com/facebook/create-react-app/issues/293
|
||||
// src/node_modules is not ignored to support absolute imports
|
||||
// https://github.com/facebook/create-react-app/issues/1065
|
||||
watchOptions: {
|
||||
ignored: ignoredFiles(paths.appSrc),
|
||||
},
|
||||
https: getHttpsConfig(),
|
||||
host,
|
||||
overlay: false,
|
||||
historyApiFallback: {
|
||||
// Paths with dots should still use the history fallback.
|
||||
// See https://github.com/facebook/create-react-app/issues/387.
|
||||
disableDotRule: true,
|
||||
index: paths.publicUrlOrPath,
|
||||
},
|
||||
public: allowedHost,
|
||||
// `proxy` is run between `before` and `after` `webpack-dev-server` hooks
|
||||
proxy,
|
||||
before(app, server) {
|
||||
// Keep `evalSourceMapMiddleware` and `errorOverlayMiddleware`
|
||||
// middlewares before `redirectServedPath` otherwise will not have any effect
|
||||
// This lets us fetch source contents from webpack for the error overlay
|
||||
app.use(evalSourceMapMiddleware(server));
|
||||
// This lets us open files from the runtime error overlay.
|
||||
app.use(errorOverlayMiddleware());
|
||||
|
||||
if (fs.existsSync(paths.proxySetup)) {
|
||||
// This registers user provided middleware for proxy reasons
|
||||
require(paths.proxySetup)(app);
|
||||
}
|
||||
},
|
||||
after(app) {
|
||||
// Redirect to `PUBLIC_URL` or `homepage` from `package.json` if url not match
|
||||
app.use(redirectServedPath(paths.publicUrlOrPath));
|
||||
|
||||
// This service worker file is effectively a 'no-op' that will reset any
|
||||
// previous service worker registered for the same host:port combination.
|
||||
// We do this in development to avoid hitting the production cache if
|
||||
// it used the same host and port.
|
||||
// https://github.com/facebook/create-react-app/issues/2272#issuecomment-302832432
|
||||
app.use(noopServiceWorkerMiddleware(paths.publicUrlOrPath));
|
||||
},
|
||||
};
|
||||
};
|
||||
|
After Width: | Height: | Size: 122 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 135 KiB |
|
After Width: | Height: | Size: 63 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 63 KiB |
@@ -1,33 +0,0 @@
|
||||
## change default port to 6015
|
||||
create file `vue.config.js` next to `package.json`
|
||||
```js
|
||||
module.exports = {
|
||||
devServer: {
|
||||
port: 6015
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Add less support
|
||||
|
||||
npm install -D less-loader less
|
||||
|
||||
## Add http proxy
|
||||
|
||||
```
|
||||
module.exports = {
|
||||
devServer: {
|
||||
proxy: {
|
||||
'/api': {
|
||||
//target: 'https://tank.eyeblue.cn',
|
||||
target: 'http://127.0.0.1:6010',
|
||||
changeOrigin: true,
|
||||
pathRewrite: {
|
||||
'^/api': '/api'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1,79 +1,102 @@
|
||||
{
|
||||
"name": "EyeblueTank",
|
||||
"version": "0.1.0",
|
||||
"name": "tank-front",
|
||||
"version": "3.1.2",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build",
|
||||
"lint": "vue-cli-service lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"animate.css": "^3.7.0",
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"bootstrap": "^3.4.1",
|
||||
"clipboard": "^2.0.4",
|
||||
"core-js": "^2.6.5",
|
||||
"echarts": "^4.2.1",
|
||||
"element-ui": "^2.8.2",
|
||||
"enquire.js": "^2.1.6",
|
||||
"font-awesome": "^4.7.0",
|
||||
"icheck": "^1.0.2",
|
||||
"jquery": "^3.4.1",
|
||||
"js-cookie": "^2.2.0",
|
||||
"perfect-scrollbar": "^1.4.0",
|
||||
"swiper": "^4.5.0",
|
||||
"velocity-animate": "^1.5.2",
|
||||
"vue": "^2.6.10",
|
||||
"vue-echarts": "^4.0.2",
|
||||
"vue-i18n": "^8.11.2",
|
||||
"vue-multiselect": "^2.1.6",
|
||||
"vue-nprogress": "^0.1.5",
|
||||
"vue-resource": "^1.5.1",
|
||||
"vue-router": "^3.0.6",
|
||||
"vuex": "^3.1.1",
|
||||
"vuex-router-sync": "^5.0.0",
|
||||
"x-photoswipe": "^4.1.3-rc.1"
|
||||
"@ant-design/icons": "4.2.1",
|
||||
"pretty-format": "25.5.0",
|
||||
"@types/echarts": "^4.6.1",
|
||||
"@types/photoswipe": "^4.1.0",
|
||||
"antd": "4.4.3",
|
||||
"axios": "^0.19.2",
|
||||
"camelcase": "^5.3.1",
|
||||
"comma-separated-values": "^3.6.4",
|
||||
"dotenv": "8.2.0",
|
||||
"dotenv-expand": "5.1.0",
|
||||
"echarts": "^4.8.0",
|
||||
"echarts-for-react": "^2.0.16",
|
||||
"fs-extra": "^8.1.0",
|
||||
"identity-obj-proxy": "3.0.0",
|
||||
"photoswipe": "^4.1.3",
|
||||
"qs": "^6.9.4",
|
||||
"react": "^16.13.1",
|
||||
"react-app-polyfill": "^1.0.6",
|
||||
"react-dev-utils": "^10.2.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-router": "^5.2.0",
|
||||
"react-router-dom": "^5.2.0",
|
||||
"semver": "6.3.0",
|
||||
"ts-pnp": "1.1.6",
|
||||
"velocity-react": "^1.4.3"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "node scripts/start.js",
|
||||
"build": "node scripts/build.js"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"babel": {
|
||||
"presets": [
|
||||
"react-app"
|
||||
],
|
||||
"plugins": [
|
||||
[
|
||||
"import",
|
||||
{
|
||||
"libraryName": "antd",
|
||||
"style": true
|
||||
},
|
||||
"antd"
|
||||
]
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "^3.7.0",
|
||||
"@vue/cli-plugin-eslint": "^3.7.0",
|
||||
"@vue/cli-service": "^3.7.0",
|
||||
"@vue/eslint-config-standard": "^4.0.0",
|
||||
"babel-eslint": "^10.0.1",
|
||||
"eslint": "^5.16.0",
|
||||
"eslint-config-standard": "^12.0.0",
|
||||
"eslint-plugin-html": "^5.0.5",
|
||||
"eslint-plugin-import": "^2.17.2",
|
||||
"eslint-plugin-node": "^9.0.1",
|
||||
"eslint-plugin-promise": "^4.1.1",
|
||||
"eslint-plugin-standard": "^4.0.0",
|
||||
"eslint-plugin-vue": "^5.0.0",
|
||||
"less": "^3.9.0",
|
||||
"less-loader": "^5.0.0",
|
||||
"vue-template-compiler": "^2.5.21"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"root": true,
|
||||
"env": {
|
||||
"node": true
|
||||
},
|
||||
"extends": [
|
||||
"plugin:vue/essential",
|
||||
"eslint:recommended",
|
||||
"@vue/standard"
|
||||
],
|
||||
"rules": {},
|
||||
"parserOptions": {
|
||||
"parser": "babel-eslint"
|
||||
}
|
||||
},
|
||||
"postcss": {
|
||||
"plugins": {
|
||||
"autoprefixer": {}
|
||||
}
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
"last 2 versions"
|
||||
]
|
||||
"@babel/core": "7.9.0",
|
||||
"@svgr/webpack": "4.3.3",
|
||||
"@types/node": "^12.0.0",
|
||||
"@types/qs": "^6.9.3",
|
||||
"@types/react": "^16.9.0",
|
||||
"@types/react-dom": "^16.9.0",
|
||||
"@types/react-router-dom": "^5.1.5",
|
||||
"@types/react-transition-group": "^4.4.0",
|
||||
"babel-loader": "8.1.0",
|
||||
"babel-plugin-import": "^1.13.0",
|
||||
"babel-plugin-named-asset-import": "^0.3.6",
|
||||
"babel-preset-react-app": "^9.1.2",
|
||||
"case-sensitive-paths-webpack-plugin": "2.3.0",
|
||||
"css-loader": "3.4.2",
|
||||
"file-loader": "4.3.0",
|
||||
"html-webpack-plugin": "4.0.0-beta.11",
|
||||
"less": "^3.11.2",
|
||||
"less-loader": "^6.1.0",
|
||||
"mini-css-extract-plugin": "0.9.0",
|
||||
"optimize-css-assets-webpack-plugin": "5.0.3",
|
||||
"pnp-webpack-plugin": "1.6.4",
|
||||
"postcss-flexbugs-fixes": "4.1.0",
|
||||
"postcss-loader": "3.0.0",
|
||||
"postcss-normalize": "8.0.1",
|
||||
"postcss-preset-env": "6.7.0",
|
||||
"postcss-safe-parser": "4.0.1",
|
||||
"prettier": "^2.0.5",
|
||||
"resolve": "1.15.0",
|
||||
"resolve-url-loader": "3.1.1",
|
||||
"sass-loader": "8.0.2",
|
||||
"style-loader": "0.23.1",
|
||||
"terser-webpack-plugin": "2.3.5",
|
||||
"typescript": "~3.7.2",
|
||||
"url-loader": "2.3.0",
|
||||
"webpack": "4.42.0",
|
||||
"webpack-dev-server": "3.10.3",
|
||||
"webpack-manifest-plugin": "2.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<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 %>favicon.ico">
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
name="description"
|
||||
content="eyeblue tank"
|
||||
/>
|
||||
<title>EyeblueTank</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<strong>We're sorry but tank-front-tmp doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
<noscript>You need to enable JavaScript to run EyeblueTank.</noscript>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,211 @@
|
||||
'use strict';
|
||||
|
||||
// Do this as the first thing so that any code reading it knows the right env.
|
||||
process.env.BABEL_ENV = 'production';
|
||||
process.env.NODE_ENV = 'production';
|
||||
|
||||
// Makes the script crash on unhandled rejections instead of silently
|
||||
// ignoring them. In the future, promise rejections that are not handled will
|
||||
// terminate the Node.js process with a non-zero exit code.
|
||||
process.on('unhandledRejection', err => {
|
||||
throw err;
|
||||
});
|
||||
|
||||
// Ensure environment variables are read.
|
||||
require('../config/env');
|
||||
|
||||
|
||||
const path = require('path');
|
||||
const chalk = require('react-dev-utils/chalk');
|
||||
const fs = require('fs-extra');
|
||||
const webpack = require('webpack');
|
||||
const configFactory = require('../config/webpack.config');
|
||||
const paths = require('../config/paths');
|
||||
const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
|
||||
const formatWebpackMessages = require('react-dev-utils/formatWebpackMessages');
|
||||
const printHostingInstructions = require('react-dev-utils/printHostingInstructions');
|
||||
const FileSizeReporter = require('react-dev-utils/FileSizeReporter');
|
||||
const printBuildError = require('react-dev-utils/printBuildError');
|
||||
|
||||
const measureFileSizesBeforeBuild =
|
||||
FileSizeReporter.measureFileSizesBeforeBuild;
|
||||
const printFileSizesAfterBuild = FileSizeReporter.printFileSizesAfterBuild;
|
||||
const useYarn = fs.existsSync(paths.yarnLockFile);
|
||||
|
||||
// These sizes are pretty large. We'll warn for bundles exceeding them.
|
||||
const WARN_AFTER_BUNDLE_GZIP_SIZE = 512 * 1024;
|
||||
const WARN_AFTER_CHUNK_GZIP_SIZE = 1024 * 1024;
|
||||
|
||||
const isInteractive = process.stdout.isTTY;
|
||||
|
||||
// Warn and crash if required files are missing
|
||||
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Generate configuration
|
||||
const config = configFactory('production');
|
||||
|
||||
// We require that you explicitly set browsers and do not fall back to
|
||||
// browserslist defaults.
|
||||
const { checkBrowsers } = require('react-dev-utils/browsersHelper');
|
||||
checkBrowsers(paths.appPath, isInteractive)
|
||||
.then(() => {
|
||||
// First, read the current file sizes in build directory.
|
||||
// This lets us display how much they changed later.
|
||||
return measureFileSizesBeforeBuild(paths.appBuild);
|
||||
})
|
||||
.then(previousFileSizes => {
|
||||
// Remove all content but keep the directory so that
|
||||
// if you're in it, you don't end up in Trash
|
||||
fs.emptyDirSync(paths.appBuild);
|
||||
// Merge with the public folder
|
||||
copyPublicFolder();
|
||||
// Start the webpack build
|
||||
return build(previousFileSizes);
|
||||
})
|
||||
.then(
|
||||
({ stats, previousFileSizes, warnings }) => {
|
||||
if (warnings.length) {
|
||||
console.log(chalk.yellow('Compiled with warnings.\n'));
|
||||
console.log(warnings.join('\n\n'));
|
||||
console.log(
|
||||
'\nSearch for the ' +
|
||||
chalk.underline(chalk.yellow('keywords')) +
|
||||
' to learn more about each warning.'
|
||||
);
|
||||
console.log(
|
||||
'To ignore, add ' +
|
||||
chalk.cyan('// eslint-disable-next-line') +
|
||||
' to the line before.\n'
|
||||
);
|
||||
} else {
|
||||
console.log(chalk.green('Compiled successfully.\n'));
|
||||
}
|
||||
|
||||
console.log('File sizes after gzip:\n');
|
||||
printFileSizesAfterBuild(
|
||||
stats,
|
||||
previousFileSizes,
|
||||
paths.appBuild,
|
||||
WARN_AFTER_BUNDLE_GZIP_SIZE,
|
||||
WARN_AFTER_CHUNK_GZIP_SIZE
|
||||
);
|
||||
console.log();
|
||||
|
||||
const appPackage = require(paths.appPackageJson);
|
||||
const publicUrl = paths.publicUrlOrPath;
|
||||
const publicPath = config.output.publicPath;
|
||||
const buildFolder = path.relative(process.cwd(), paths.appBuild);
|
||||
printHostingInstructions(
|
||||
appPackage,
|
||||
publicUrl,
|
||||
publicPath,
|
||||
buildFolder,
|
||||
useYarn
|
||||
);
|
||||
},
|
||||
err => {
|
||||
const tscCompileOnError = process.env.TSC_COMPILE_ON_ERROR === 'true';
|
||||
if (tscCompileOnError) {
|
||||
console.log(
|
||||
chalk.yellow(
|
||||
'Compiled with the following type errors (you may want to check these before deploying your app):\n'
|
||||
)
|
||||
);
|
||||
printBuildError(err);
|
||||
} else {
|
||||
console.log(chalk.red('Failed to compile.\n'));
|
||||
printBuildError(err);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
)
|
||||
.catch(err => {
|
||||
if (err && err.message) {
|
||||
console.log(err.message);
|
||||
}
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
// Create the production build and print the deployment instructions.
|
||||
function build(previousFileSizes) {
|
||||
// We used to support resolving modules according to `NODE_PATH`.
|
||||
// This now has been deprecated in favor of jsconfig/tsconfig.json
|
||||
// This lets you use absolute paths in imports inside large monorepos:
|
||||
if (process.env.NODE_PATH) {
|
||||
console.log(
|
||||
chalk.yellow(
|
||||
'Setting NODE_PATH to resolve modules absolutely has been deprecated in favor of setting baseUrl in jsconfig.json (or tsconfig.json if you are using TypeScript) and will be removed in a future major release of create-react-app.'
|
||||
)
|
||||
);
|
||||
console.log();
|
||||
}
|
||||
|
||||
console.log('Creating an optimized production build...');
|
||||
|
||||
const compiler = webpack(config);
|
||||
return new Promise((resolve, reject) => {
|
||||
compiler.run((err, stats) => {
|
||||
let messages;
|
||||
if (err) {
|
||||
if (!err.message) {
|
||||
return reject(err);
|
||||
}
|
||||
|
||||
let errMessage = err.message;
|
||||
|
||||
// Add additional information for postcss errors
|
||||
if (Object.prototype.hasOwnProperty.call(err, 'postcssNode')) {
|
||||
errMessage +=
|
||||
'\nCompileError: Begins at CSS selector ' +
|
||||
err['postcssNode'].selector;
|
||||
}
|
||||
|
||||
messages = formatWebpackMessages({
|
||||
errors: [errMessage],
|
||||
warnings: [],
|
||||
});
|
||||
} else {
|
||||
messages = formatWebpackMessages(
|
||||
stats.toJson({ all: false, warnings: true, errors: true })
|
||||
);
|
||||
}
|
||||
if (messages.errors.length) {
|
||||
// Only keep the first error. Others are often indicative
|
||||
// of the same problem, but confuse the reader with noise.
|
||||
if (messages.errors.length > 1) {
|
||||
messages.errors.length = 1;
|
||||
}
|
||||
return reject(new Error(messages.errors.join('\n\n')));
|
||||
}
|
||||
if (
|
||||
process.env.CI &&
|
||||
(typeof process.env.CI !== 'string' ||
|
||||
process.env.CI.toLowerCase() !== 'false') &&
|
||||
messages.warnings.length
|
||||
) {
|
||||
console.log(
|
||||
chalk.yellow(
|
||||
'\nTreating warnings as errors because process.env.CI = true.\n' +
|
||||
'Most CI servers set it automatically.\n'
|
||||
)
|
||||
);
|
||||
return reject(new Error(messages.warnings.join('\n\n')));
|
||||
}
|
||||
|
||||
return resolve({
|
||||
stats,
|
||||
previousFileSizes,
|
||||
warnings: messages.warnings,
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function copyPublicFolder() {
|
||||
fs.copySync(paths.appPublic, paths.appBuild, {
|
||||
dereference: true,
|
||||
filter: file => file !== paths.appHtml,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
'use strict';
|
||||
|
||||
// Do this as the first thing so that any code reading it knows the right env.
|
||||
process.env.BABEL_ENV = 'development';
|
||||
process.env.NODE_ENV = 'development';
|
||||
|
||||
// Makes the script crash on unhandled rejections instead of silently
|
||||
// ignoring them. In the future, promise rejections that are not handled will
|
||||
// terminate the Node.js process with a non-zero exit code.
|
||||
process.on('unhandledRejection', err => {
|
||||
throw err;
|
||||
});
|
||||
|
||||
// Ensure environment variables are read.
|
||||
require('../config/env');
|
||||
|
||||
|
||||
const fs = require('fs');
|
||||
const chalk = require('react-dev-utils/chalk');
|
||||
const webpack = require('webpack');
|
||||
const WebpackDevServer = require('webpack-dev-server');
|
||||
const clearConsole = require('react-dev-utils/clearConsole');
|
||||
const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
|
||||
const {
|
||||
choosePort,
|
||||
createCompiler,
|
||||
prepareProxy,
|
||||
prepareUrls,
|
||||
} = require('react-dev-utils/WebpackDevServerUtils');
|
||||
const openBrowser = require('react-dev-utils/openBrowser');
|
||||
const paths = require('../config/paths');
|
||||
const configFactory = require('../config/webpack.config');
|
||||
const createDevServerConfig = require('../config/webpackDevServer.config');
|
||||
|
||||
const useYarn = fs.existsSync(paths.yarnLockFile);
|
||||
const isInteractive = process.stdout.isTTY;
|
||||
|
||||
// Warn and crash if required files are missing
|
||||
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Tools like Cloud9 rely on this.
|
||||
const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 6015;
|
||||
const HOST = process.env.HOST || '0.0.0.0';
|
||||
|
||||
if (process.env.HOST) {
|
||||
console.log(
|
||||
chalk.cyan(
|
||||
`Attempting to bind to HOST environment variable: ${chalk.yellow(
|
||||
chalk.bold(process.env.HOST)
|
||||
)}`
|
||||
)
|
||||
);
|
||||
console.log(
|
||||
`If this was unintentional, check that you haven't mistakenly set it in your shell.`
|
||||
);
|
||||
console.log(
|
||||
`Learn more here: ${chalk.yellow('https://bit.ly/CRA-advanced-config')}`
|
||||
);
|
||||
console.log();
|
||||
}
|
||||
|
||||
// We require that you explicitly set browsers and do not fall back to
|
||||
// browserslist defaults.
|
||||
const { checkBrowsers } = require('react-dev-utils/browsersHelper');
|
||||
checkBrowsers(paths.appPath, isInteractive)
|
||||
.then(() => {
|
||||
// We attempt to use the default port but if it is busy, we offer the user to
|
||||
// run on a different port. `choosePort()` Promise resolves to the next free port.
|
||||
return choosePort(HOST, DEFAULT_PORT);
|
||||
})
|
||||
.then(port => {
|
||||
if (port == null) {
|
||||
// We have not found a port.
|
||||
return;
|
||||
}
|
||||
|
||||
const config = configFactory('development');
|
||||
const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
|
||||
const appName = require(paths.appPackageJson).name;
|
||||
const useTypeScript = fs.existsSync(paths.appTsConfig);
|
||||
const tscCompileOnError = process.env.TSC_COMPILE_ON_ERROR === 'true';
|
||||
const urls = prepareUrls(
|
||||
protocol,
|
||||
HOST,
|
||||
port,
|
||||
paths.publicUrlOrPath.slice(0, -1)
|
||||
);
|
||||
const devSocket = {
|
||||
warnings: warnings =>
|
||||
devServer.sockWrite(devServer.sockets, 'warnings', warnings),
|
||||
errors: errors =>
|
||||
devServer.sockWrite(devServer.sockets, 'errors', errors),
|
||||
};
|
||||
// Create a webpack compiler that is configured with custom messages.
|
||||
const compiler = createCompiler({
|
||||
appName,
|
||||
config,
|
||||
devSocket,
|
||||
urls,
|
||||
useYarn,
|
||||
useTypeScript,
|
||||
tscCompileOnError,
|
||||
webpack,
|
||||
});
|
||||
// Load proxy config
|
||||
const proxySetting = require(paths.appPackageJson).proxy;
|
||||
const proxyConfig = prepareProxy(
|
||||
proxySetting,
|
||||
paths.appPublic,
|
||||
paths.publicUrlOrPath
|
||||
);
|
||||
// Serve webpack assets generated by the compiler over a web server.
|
||||
const serverConfig = createDevServerConfig(
|
||||
proxyConfig,
|
||||
urls.lanUrlForConfig
|
||||
);
|
||||
const devServer = new WebpackDevServer(compiler, serverConfig);
|
||||
// Launch WebpackDevServer.
|
||||
devServer.listen(port, HOST, err => {
|
||||
if (err) {
|
||||
return console.log(err);
|
||||
}
|
||||
if (isInteractive) {
|
||||
clearConsole();
|
||||
}
|
||||
|
||||
// We used to support resolving modules according to `NODE_PATH`.
|
||||
// This now has been deprecated in favor of jsconfig/tsconfig.json
|
||||
// This lets you use absolute paths in imports inside large monorepos:
|
||||
if (process.env.NODE_PATH) {
|
||||
console.log(
|
||||
chalk.yellow(
|
||||
'Setting NODE_PATH to resolve modules absolutely has been deprecated in favor of setting baseUrl in jsconfig.json (or tsconfig.json if you are using TypeScript) and will be removed in a future major release of create-react-app.'
|
||||
)
|
||||
);
|
||||
console.log();
|
||||
}
|
||||
|
||||
console.log(chalk.cyan('Starting the development server...\n'));
|
||||
openBrowser(urls.localUrlForBrowser);
|
||||
});
|
||||
|
||||
['SIGINT', 'SIGTERM'].forEach(function(sig) {
|
||||
process.on(sig, function() {
|
||||
devServer.close();
|
||||
process.exit();
|
||||
});
|
||||
});
|
||||
|
||||
if (isInteractive || process.env.CI !== 'true') {
|
||||
// Gracefully exit when stdin ends
|
||||
process.stdin.on('end', function() {
|
||||
devServer.close();
|
||||
process.exit();
|
||||
});
|
||||
process.stdin.resume();
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
if (err && err.message) {
|
||||
console.log(err.message);
|
||||
}
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -0,0 +1,53 @@
|
||||
'use strict';
|
||||
|
||||
// Do this as the first thing so that any code reading it knows the right env.
|
||||
process.env.BABEL_ENV = 'test';
|
||||
process.env.NODE_ENV = 'test';
|
||||
process.env.PUBLIC_URL = '';
|
||||
|
||||
// Makes the script crash on unhandled rejections instead of silently
|
||||
// ignoring them. In the future, promise rejections that are not handled will
|
||||
// terminate the Node.js process with a non-zero exit code.
|
||||
process.on('unhandledRejection', err => {
|
||||
throw err;
|
||||
});
|
||||
|
||||
// Ensure environment variables are read.
|
||||
require('../config/env');
|
||||
|
||||
|
||||
const jest = require('jest');
|
||||
const execSync = require('child_process').execSync;
|
||||
let argv = process.argv.slice(2);
|
||||
|
||||
function isInGitRepository() {
|
||||
try {
|
||||
execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' });
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function isInMercurialRepository() {
|
||||
try {
|
||||
execSync('hg --cwd . root', { stdio: 'ignore' });
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Watch unless on CI or explicitly running all tests
|
||||
if (
|
||||
!process.env.CI &&
|
||||
argv.indexOf('--watchAll') === -1 &&
|
||||
argv.indexOf('--watchAll=false') === -1
|
||||
) {
|
||||
// https://github.com/facebook/create-react-app/issues/5210
|
||||
const hasSourceControl = isInGitRepository() || isInMercurialRepository();
|
||||
argv.push(hasSourceControl ? '--watch' : '--watchAll');
|
||||
}
|
||||
|
||||
|
||||
jest.run(argv);
|
||||
@@ -0,0 +1,2 @@
|
||||
//import global style.
|
||||
@import './assets/css/index.less';
|
||||
@@ -0,0 +1,20 @@
|
||||
import React from 'react';
|
||||
import {BrowserRouter as Router} from "react-router-dom";
|
||||
import {ConfigProvider} from 'antd';
|
||||
import Frame from "./pages/Frame";
|
||||
import en_US from 'antd/es/locale/en_US';
|
||||
|
||||
// global less 须放在Frame组件之后,不然会出现按需加载的less文件覆盖样式问题
|
||||
import './App.less';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<Router>
|
||||
<ConfigProvider locale={en_US}>
|
||||
<Frame/>
|
||||
</ConfigProvider>
|
||||
</Router>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
@@ -1,97 +0,0 @@
|
||||
<template>
|
||||
<div class="nb-app">
|
||||
|
||||
<NprogressContainer/>
|
||||
<router-view/>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NprogressContainer from 'vue-nprogress/src/NprogressContainer'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
preference: this.$store.state.preference
|
||||
}
|
||||
},
|
||||
computed: {},
|
||||
components: {
|
||||
NprogressContainer
|
||||
},
|
||||
mounted() {
|
||||
|
||||
let that = this
|
||||
this.preference.httpFetch()
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="less" rel="stylesheet/less">
|
||||
|
||||
@import "~font-awesome/css/font-awesome.css";
|
||||
@import "./assets/css/app.less";
|
||||
|
||||
.nb-app {
|
||||
|
||||
height: 100%;
|
||||
|
||||
.nprogress-container {
|
||||
position: fixed !important;
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
z-index: 2048;
|
||||
pointer-events: none;
|
||||
|
||||
#nprogress {
|
||||
//@color: #48e79a;
|
||||
@color: #1ab394;
|
||||
|
||||
.bar {
|
||||
background: @color;
|
||||
}
|
||||
|
||||
.peg {
|
||||
box-shadow: 0 0 10px @color, 0 0 5px @color;
|
||||
}
|
||||
|
||||
.spinner-icon {
|
||||
border-top-color: @color;
|
||||
border-left-color: @color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//所有的滚动条样式
|
||||
::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track-piece {
|
||||
background-color: #eee;
|
||||
margin: -2px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: #aaa;
|
||||
min-height: 150px;
|
||||
min-width: 150px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:vertical:hover {
|
||||
background: #555555
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:horizontal:hover {
|
||||
background: #555555
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
@@ -1,169 +0,0 @@
|
||||
//global css.
|
||||
//Include font-awesome
|
||||
//Include what we need in bootstrap.
|
||||
@import "bootstrap/bootstrap.less";
|
||||
@import "inspinia/style.less";
|
||||
//Animated
|
||||
@import "~animate.css/animate.min.css";
|
||||
//element-ui
|
||||
@import "~element-ui/lib/theme-chalk/index.css";
|
||||
//使用自定义的主题
|
||||
@import "global/border.less";
|
||||
@import "global/button.less";
|
||||
@import "global/color.less";
|
||||
@import "global/font.less";
|
||||
@import "global/layout.less";
|
||||
@import "global/miscellaneous.less";
|
||||
@import "global/responsive.less";
|
||||
|
||||
//h2被污染了
|
||||
.el-notification__title {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.el-dialog__wrapper {
|
||||
.el-dialog__body {
|
||||
padding: 0 20px 20px 20px;
|
||||
}
|
||||
}
|
||||
|
||||
//手机端的弹出框太大了
|
||||
@media (max-width: 768px) {
|
||||
.el-message-box__wrapper {
|
||||
.el-message-box {
|
||||
width: 90%;
|
||||
}
|
||||
}
|
||||
|
||||
.el-dialog__wrapper {
|
||||
.el-dialog {
|
||||
width: 90%;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
html, body {
|
||||
font-family: "微软雅黑", Microsoft YaHei, "Helvetica Neue", Helvetica, Arial, sans-serif, "open sans";
|
||||
font-size: 13px;
|
||||
color: @text-color;
|
||||
background-color: white;
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//列表单元格的样式。
|
||||
.nb-app {
|
||||
|
||||
//media-body下的p字体大小
|
||||
.media-body {
|
||||
p {
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
|
||||
.cell-title {
|
||||
font-size: 17px;
|
||||
color: @app-color-title;
|
||||
.one-line;
|
||||
|
||||
a {
|
||||
font-size: 17px;
|
||||
color: @app-color-title;
|
||||
|
||||
&:hover {
|
||||
color: @brand-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.cell-content {
|
||||
font-size: 12px;
|
||||
color: @app-color-title;
|
||||
letter-spacing: 0;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.cell-description {
|
||||
font-size: 12px;
|
||||
color: @app-color-content;
|
||||
letter-spacing: 0;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//超链接颜色.
|
||||
a {
|
||||
color: @brand-primary;
|
||||
|
||||
&:hover, &:focus {
|
||||
color: @brand-info;
|
||||
}
|
||||
}
|
||||
|
||||
//段落统一样式
|
||||
p {
|
||||
color: #333;
|
||||
font-size: 15px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
//每个页面导航处样式
|
||||
.pedia-navigation {
|
||||
margin-bottom: 10px;
|
||||
border-bottom: 1px solid #E6E6E6;
|
||||
position: relative;
|
||||
|
||||
.item {
|
||||
font-size: 16px;
|
||||
color: #778195;
|
||||
margin-top: 15px;
|
||||
margin-right: 20px;
|
||||
display: inline-block;
|
||||
box-sizing: content-box;
|
||||
line-height: 30px;
|
||||
|
||||
&:hover, &.is-link-active, &.active {
|
||||
color: @brand-primary;
|
||||
|
||||
border-bottom: 2px solid @brand-primary;
|
||||
}
|
||||
}
|
||||
|
||||
.tool {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 5px;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
//markdown中默认图片剧中
|
||||
p {
|
||||
> img {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
//列表页中展开的标准样式
|
||||
.form-info {
|
||||
margin-bottom: 10px;
|
||||
|
||||
> span:first-child:not(.label) {
|
||||
width: 150px;
|
||||
color: #99a9bf;
|
||||
font-size: 15px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
> span:last-child:not(.label) {
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
/*!
|
||||
* Bootstrap v3.3.7 (http://getbootstrap.com)
|
||||
* Copyright 2011-2016 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
*/
|
||||
// Core variables and mixins
|
||||
@import "../global/variables.less";
|
||||
|
||||
|
||||
|
||||
@import "~bootstrap/less/mixins.less";
|
||||
// Reset and dependencies
|
||||
@import "~bootstrap/less/normalize.less";
|
||||
@import "~bootstrap/less/print.less";
|
||||
//We DO NOT use bootstrap's icon. We use font-awesome
|
||||
//@import "~bootstrap/less/glyphicons.less";
|
||||
// Core CSS
|
||||
@import "~bootstrap/less/scaffolding.less";
|
||||
@import "~bootstrap/less/type.less";
|
||||
@import "~bootstrap/less/code.less";
|
||||
@import "~bootstrap/less/grid.less";
|
||||
@import "~bootstrap/less/tables.less";
|
||||
@import "~bootstrap/less/forms.less";
|
||||
@import "~bootstrap/less/buttons.less";
|
||||
// Components
|
||||
@import "~bootstrap/less/component-animations.less";
|
||||
@import "~bootstrap/less/dropdowns.less";
|
||||
@import "~bootstrap/less/button-groups.less";
|
||||
@import "~bootstrap/less/input-groups.less";
|
||||
@import "~bootstrap/less/navs.less";
|
||||
@import "~bootstrap/less/navbar.less";
|
||||
@import "~bootstrap/less/breadcrumbs.less";
|
||||
@import "~bootstrap/less/pagination.less";
|
||||
@import "~bootstrap/less/pager.less";
|
||||
@import "~bootstrap/less/labels.less";
|
||||
@import "~bootstrap/less/badges.less";
|
||||
@import "~bootstrap/less/jumbotron.less";
|
||||
@import "~bootstrap/less/thumbnails.less";
|
||||
@import "~bootstrap/less/alerts.less";
|
||||
@import "~bootstrap/less/progress-bars.less";
|
||||
@import "~bootstrap/less/media.less";
|
||||
@import "~bootstrap/less/list-group.less";
|
||||
@import "~bootstrap/less/panels.less";
|
||||
@import "~bootstrap/less/responsive-embed.less";
|
||||
@import "~bootstrap/less/wells.less";
|
||||
@import "~bootstrap/less/close.less";
|
||||
// Components w/ JavaScript
|
||||
@import "~bootstrap/less/modals.less";
|
||||
@import "~bootstrap/less/tooltip.less";
|
||||
@import "~bootstrap/less/popovers.less";
|
||||
@import "~bootstrap/less/carousel.less";
|
||||
// Utility classes
|
||||
@import "~bootstrap/less/utilities.less";
|
||||
@import "~bootstrap/less/responsive-utilities.less";
|
||||
@@ -14,14 +14,11 @@
|
||||
@gray-light: lighten(@gray-base, 46.7%); // #777
|
||||
@gray-lighter: lighten(@gray-base, 93.5%); // #eee
|
||||
|
||||
//zhengxianqian Theme.
|
||||
@brand-primary: #23B7E5;
|
||||
@brand-success: #1ab394;
|
||||
@brand-info: #5EC1C5;
|
||||
@brand-warning: #FEC62E;
|
||||
@brand-danger: #FE8768;
|
||||
@brand-gray: #c2c2c2;
|
||||
@brand-laxative: #B3EE3A;
|
||||
@brand-primary: darken(#428bca, 6.5%); // #337ab7
|
||||
@brand-success: #5cb85c;
|
||||
@brand-info: #5bc0de;
|
||||
@brand-warning: #f0ad4e;
|
||||
@brand-danger: #d9534f;
|
||||
|
||||
|
||||
//== Scaffolding
|
||||
@@ -109,9 +106,9 @@
|
||||
@border-radius-large: 6px;
|
||||
@border-radius-small: 3px;
|
||||
|
||||
//** Global color for active items (e.g., navs or dropdowns).
|
||||
//** Global color for active pendants (e.g., navs or dropdowns).
|
||||
@component-active-color: #fff;
|
||||
//** Global background color for active items (e.g., navs or dropdowns).
|
||||
//** Global background color for active pendants (e.g., navs or dropdowns).
|
||||
@component-active-bg: @brand-primary;
|
||||
|
||||
//** Width of the `border` for generating carets that indicate dropdowns.
|
||||
@@ -193,7 +190,6 @@
|
||||
//** `<input>` border color
|
||||
@input-border: #ccc;
|
||||
|
||||
// TODO: Rename `@input-border-radius` to `@input-border-radius-base` in v4
|
||||
//** Default `.form-control` border radius
|
||||
// This has no effect on `<select>`s in some browsers, due to the limited stylability of `<select>`s in CSS.
|
||||
@input-border-radius: @border-radius-base;
|
||||
@@ -240,7 +236,7 @@
|
||||
@dropdown-border: rgba(0,0,0,.15);
|
||||
//** Dropdown menu `border-color` **for IE8**.
|
||||
@dropdown-fallback-border: #ccc;
|
||||
//** Divider color for between dropdown items.
|
||||
//** Divider color for between dropdown pendants.
|
||||
@dropdown-divider-bg: #e5e5e5;
|
||||
|
||||
//** Dropdown link text color.
|
||||
@@ -678,22 +674,22 @@
|
||||
//** List group border radius
|
||||
@list-group-border-radius: @border-radius-base;
|
||||
|
||||
//** Background color of single list items on hover
|
||||
//** Background color of single list pendants on hover
|
||||
@list-group-hover-bg: #f5f5f5;
|
||||
//** Text color of active list items
|
||||
//** Text color of active list pendants
|
||||
@list-group-active-color: @component-active-color;
|
||||
//** Background color of active list items
|
||||
//** Background color of active list pendants
|
||||
@list-group-active-bg: @component-active-bg;
|
||||
//** Border color of active list elements
|
||||
@list-group-active-border: @list-group-active-bg;
|
||||
//** Text color for content within active list items
|
||||
//** Text color for content within active list pendants
|
||||
@list-group-active-text-color: lighten(@list-group-active-bg, 40%);
|
||||
|
||||
//** Text color of disabled list items
|
||||
//** Text color of disabled list pendants
|
||||
@list-group-disabled-color: @gray-light;
|
||||
//** Background color of disabled list items
|
||||
//** Background color of disabled list pendants
|
||||
@list-group-disabled-bg: @gray-lighter;
|
||||
//** Text color for content within disabled list items
|
||||
//** Text color for content within disabled list pendants
|
||||
@list-group-disabled-text-color: @list-group-disabled-color;
|
||||
|
||||
@list-group-link-color: #555;
|
||||
|
||||
@@ -36,6 +36,6 @@
|
||||
}
|
||||
|
||||
.border-bottom {
|
||||
border-bottom: 1px solid #eee;
|
||||
border-bottom: 1px solid #F9F9F9;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,31 +1,83 @@
|
||||
@import "variables";
|
||||
|
||||
.btn {
|
||||
display: inline-block;
|
||||
margin-bottom: 0;
|
||||
font-weight: normal;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
-ms-touch-action: manipulation;
|
||||
touch-action: manipulation;
|
||||
cursor: pointer;
|
||||
background-image: none;
|
||||
border: 1px solid transparent;
|
||||
padding: 6px 12px;
|
||||
font-size: 14px;
|
||||
line-height: 1.42857143;
|
||||
border-radius: 4px;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.btn-action {
|
||||
margin: 0 3px;
|
||||
display: inline-block;
|
||||
opacity: 0.85;
|
||||
-webkit-transition: all 0.1s;
|
||||
-o-transition: all 0.1s;
|
||||
transition: all 0.1s;
|
||||
cursor: pointer;
|
||||
margin: 0 3px;
|
||||
display: inline-block;
|
||||
opacity: 0.85;
|
||||
-webkit-transition: all 0.1s;
|
||||
-o-transition: all 0.1s;
|
||||
transition: all 0.1s;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
opacity: 1;
|
||||
-moz-transform: scale(1.2);
|
||||
-webkit-transform: scale(1.2);
|
||||
-o-transform: scale(1.2);
|
||||
-ms-transform: scale(1.2);
|
||||
transform: scale(1.2);
|
||||
}
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
opacity: 1;
|
||||
-moz-transform: scale(1.2);
|
||||
-webkit-transform: scale(1.2);
|
||||
-o-transform: scale(1.2);
|
||||
-ms-transform: scale(1.2);
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
color: #fff;
|
||||
background-color: #337ab7;
|
||||
border-color: #2e6da4;
|
||||
}
|
||||
.btn-primary:focus,
|
||||
.btn-primary.focus {
|
||||
color: #fff;
|
||||
background-color: #286090;
|
||||
border-color: #122b40;
|
||||
}
|
||||
.btn-primary:hover {
|
||||
color: #fff;
|
||||
background-color: #286090;
|
||||
border-color: #204d74;
|
||||
}
|
||||
|
||||
.btn-sm {
|
||||
padding: 5px 10px;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
//编辑区域按钮,鼠标一上去按钮变大
|
||||
.action-buttons {
|
||||
a {
|
||||
.btn-action;
|
||||
}
|
||||
a {
|
||||
.btn-action;
|
||||
}
|
||||
}
|
||||
|
||||
.cursor {
|
||||
cursor: pointer;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@@ -1,358 +1,113 @@
|
||||
@import "./variables.less";
|
||||
|
||||
.bg-primary {
|
||||
background-color: @brand-primary;
|
||||
color: white;
|
||||
}
|
||||
.bg-primary{ background-color: @brand-primary; color: white;}
|
||||
.bg-success{ background-color: @brand-success; color: white; }
|
||||
.bg-info{ background-color: @brand-info; color: white; }
|
||||
.bg-warning{ background-color: @brand-warning; color: white; }
|
||||
.bg-danger{ background-color: @brand-danger; color: white; }
|
||||
.bg-gray{ background-color: @brand-gray; color: white; }
|
||||
.bg-laxative{ background-color: @brand-laxative; color: white; }
|
||||
|
||||
.bg-success {
|
||||
background-color: @brand-success;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.bg-info {
|
||||
background-color: @brand-info;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.bg-warning {
|
||||
background-color: @brand-warning;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.bg-danger {
|
||||
background-color: @brand-danger;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.bg-gray {
|
||||
background-color: @brand-gray;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.bg-laxative {
|
||||
background-color: @brand-laxative;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.text-primary {
|
||||
color: @brand-primary;
|
||||
}
|
||||
|
||||
.bg-navy {
|
||||
background-color: #001F3F;
|
||||
}
|
||||
|
||||
.bg-blue {
|
||||
background-color: #0074D9;
|
||||
}
|
||||
|
||||
.bg-aqua {
|
||||
background-color: #7FDBFF;
|
||||
}
|
||||
|
||||
.bg-aliceblue {
|
||||
background-color: aliceblue;
|
||||
}
|
||||
|
||||
.bg-pink {
|
||||
background-color: pink;
|
||||
}
|
||||
|
||||
.bg-azure {
|
||||
background-color: azure;
|
||||
}
|
||||
|
||||
.bg-teal {
|
||||
background-color: #39CCCC;
|
||||
}
|
||||
|
||||
.bg-olive {
|
||||
background-color: #3D9970;
|
||||
}
|
||||
|
||||
.bg-green {
|
||||
background-color: #2ECC40;
|
||||
}
|
||||
|
||||
.bg-lime {
|
||||
background-color: #01FF70;
|
||||
}
|
||||
|
||||
.bg-yellow {
|
||||
background-color: #FFDC00;
|
||||
}
|
||||
|
||||
.bg-pink {
|
||||
color: pink;
|
||||
}
|
||||
|
||||
.bg-orange {
|
||||
background-color: #FF851B;
|
||||
}
|
||||
|
||||
.bg-red {
|
||||
background-color: #FF4136;
|
||||
}
|
||||
|
||||
.bg-fuchsia {
|
||||
background-color: #F012BE;
|
||||
}
|
||||
|
||||
.bg-purple {
|
||||
background-color: #B10DC9;
|
||||
}
|
||||
|
||||
.bg-maroon {
|
||||
background-color: #85144B;
|
||||
}
|
||||
|
||||
.bg-white {
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
|
||||
.bg-gray {
|
||||
background-color: #AAAAAA;
|
||||
}
|
||||
|
||||
.bg-silver {
|
||||
background-color: #DDDDDD;
|
||||
}
|
||||
.text-primary{ color: @brand-primary;}
|
||||
.text-success{ color: @brand-success; }
|
||||
.text-info{ color: @brand-info; }
|
||||
.text-warning{ color: @brand-warning; }
|
||||
.text-danger{ color: @brand-danger; }
|
||||
.text-gray{ color: @brand-gray; }
|
||||
.text-laxative{ color: @brand-laxative; }
|
||||
.text-theme { color: @primary-color; }
|
||||
|
||||
.bg-navy { background-color: #001F3F;}
|
||||
.bg-blue { background-color: #0074D9;}
|
||||
.bg-aqua { background-color: #7FDBFF;}
|
||||
.bg-aliceblue { background-color: aliceblue;}
|
||||
.bg-pink { background-color: pink;}
|
||||
.bg-azure { background-color: azure;}
|
||||
.bg-teal { background-color: #39CCCC;}
|
||||
.bg-olive { background-color: #3D9970;}
|
||||
.bg-green { background-color: #2ECC40;}
|
||||
.bg-lime { background-color: #01FF70;}
|
||||
.bg-yellow { background-color: #FFDC00;}
|
||||
.bg-pink { color: pink; }
|
||||
.bg-orange { background-color: #FF851B;}
|
||||
.bg-red { background-color: #FF4136;}
|
||||
.bg-fuchsia { background-color: #F012BE;}
|
||||
.bg-purple { background-color: #B10DC9;}
|
||||
.bg-maroon { background-color: #85144B;}
|
||||
.bg-white { background-color: #FFFFFF;}
|
||||
.bg-gray { background-color: #AAAAAA;}
|
||||
.bg-silver { background-color: #DDDDDD;}
|
||||
.bg-silver-white {
|
||||
background-color: #EEEEEE;
|
||||
background-color: #EEEEEE;
|
||||
}
|
||||
.bg-black { background-color: #111111;}
|
||||
|
||||
.bg-black {
|
||||
background-color: #111111;
|
||||
}
|
||||
.bg-111{ background-color:#111 }
|
||||
.bg-222{ background-color:#222 }
|
||||
.bg-333{ background-color:#333 }
|
||||
.bg-444{ background-color:#444 }
|
||||
.bg-555{ background-color:#555 }
|
||||
.bg-666{ background-color:#666 }
|
||||
.bg-777{ background-color:#777 }
|
||||
.bg-888{ background-color:#888 }
|
||||
.bg-999{ background-color:#999 }
|
||||
.bg-aaa{ background-color:#aaa }
|
||||
.bg-bbb{ background-color:#bbb }
|
||||
.bg-ccc{ background-color:#ccc }
|
||||
.bg-ddd{ background-color:#ddd }
|
||||
.bg-eee{ background-color:#eee }
|
||||
|
||||
.bg-111 {
|
||||
background-color: #111
|
||||
}
|
||||
|
||||
.bg-222 {
|
||||
background-color: #222
|
||||
}
|
||||
|
||||
.bg-333 {
|
||||
background-color: #333
|
||||
}
|
||||
|
||||
.bg-444 {
|
||||
background-color: #444
|
||||
}
|
||||
|
||||
.bg-555 {
|
||||
background-color: #555
|
||||
}
|
||||
|
||||
.bg-666 {
|
||||
background-color: #666
|
||||
}
|
||||
|
||||
.bg-777 {
|
||||
background-color: #777
|
||||
}
|
||||
|
||||
.bg-888 {
|
||||
background-color: #888
|
||||
}
|
||||
|
||||
.bg-999 {
|
||||
background-color: #999
|
||||
}
|
||||
|
||||
.bg-aaa {
|
||||
background-color: #aaa
|
||||
}
|
||||
|
||||
.bg-bbb {
|
||||
background-color: #bbb
|
||||
}
|
||||
|
||||
.bg-ccc {
|
||||
background-color: #ccc
|
||||
}
|
||||
|
||||
.bg-ddd {
|
||||
background-color: #ddd
|
||||
}
|
||||
|
||||
.bg-eee {
|
||||
background-color: #eee
|
||||
}
|
||||
|
||||
/* Colors */
|
||||
.navy {
|
||||
color: #001F3F;
|
||||
}
|
||||
.navy { color: #001F3F;}
|
||||
.blue { color: #0074D9;}
|
||||
.aqua { color: #7FDBFF;}
|
||||
.teal { color: #39CCCC;}
|
||||
.olive { color: #3D9970;}
|
||||
.green { color: #2ECC40;}
|
||||
.lime { color: #01FF70;}
|
||||
.yellow { color: #FFDC00;}
|
||||
.pink { color: pink; }
|
||||
.orange { color: #FF851B;}
|
||||
.red { color: #FF4136;}
|
||||
.fuchsia { color: #F012BE;}
|
||||
.purple { color: #B10DC9;}
|
||||
.maroon { color: #85144B;}
|
||||
.white { color: #FFFFFF;}
|
||||
.silver { color: #DDDDDD;}
|
||||
.gray { color: #AAAAAA;}
|
||||
.black { color: #111111;}
|
||||
|
||||
.blue {
|
||||
color: #0074D9;
|
||||
}
|
||||
|
||||
.aqua {
|
||||
color: #7FDBFF;
|
||||
}
|
||||
.color-111{color:#111}
|
||||
.color-222{color:#222}
|
||||
.color-333{color:#333}
|
||||
.color-444{color:#444}
|
||||
.color-555{color:#555}
|
||||
.color-666{color:#666}
|
||||
.color-777{color:#777}
|
||||
.color-888{color:#888}
|
||||
.color-999{color:#999}
|
||||
.color-aaa{color:#aaa}
|
||||
.color-bbb{color:#bbb}
|
||||
.color-ccc{color:#ccc}
|
||||
.color-ddd{color:#ddd}
|
||||
.color-eee{color:#eee}
|
||||
|
||||
.teal {
|
||||
color: #39CCCC;
|
||||
}
|
||||
|
||||
.olive {
|
||||
color: #3D9970;
|
||||
}
|
||||
.color-text { color: #660E7A;}
|
||||
.color-doc { color: #295496;}
|
||||
.color-xls { color: #1E6C41;}
|
||||
.color-ppt { color: #D04324;}
|
||||
.color-pdf { color: #E40B0B;}
|
||||
.color-audio { color: #5bc0de;}
|
||||
.color-video { color: #5cb85c;}
|
||||
.color-image { color: #0074D9;}
|
||||
.color-archive { color: #4437f2;}
|
||||
|
||||
.green {
|
||||
color: #2ECC40;
|
||||
}
|
||||
.color-light-active{ color: #ffc60c;}
|
||||
.color-light-inactive{ color:#ccc;}
|
||||
|
||||
.lime {
|
||||
color: #01FF70;
|
||||
}
|
||||
|
||||
.yellow {
|
||||
color: #FFDC00;
|
||||
}
|
||||
|
||||
.pink {
|
||||
color: pink;
|
||||
}
|
||||
|
||||
.orange {
|
||||
color: #FF851B;
|
||||
}
|
||||
|
||||
.red {
|
||||
color: #FF4136;
|
||||
}
|
||||
|
||||
.fuchsia {
|
||||
color: #F012BE;
|
||||
}
|
||||
|
||||
.purple {
|
||||
color: #B10DC9;
|
||||
}
|
||||
|
||||
.maroon {
|
||||
color: #85144B;
|
||||
}
|
||||
|
||||
.white {
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.silver {
|
||||
color: #DDDDDD;
|
||||
}
|
||||
|
||||
.gray {
|
||||
color: #AAAAAA;
|
||||
}
|
||||
|
||||
.black {
|
||||
color: #111111;
|
||||
}
|
||||
|
||||
.color-111 {
|
||||
color: #111
|
||||
}
|
||||
|
||||
.color-222 {
|
||||
color: #222
|
||||
}
|
||||
|
||||
.color-333 {
|
||||
color: #333
|
||||
}
|
||||
|
||||
.color-444 {
|
||||
color: #444
|
||||
}
|
||||
|
||||
.color-555 {
|
||||
color: #555
|
||||
}
|
||||
|
||||
.color-666 {
|
||||
color: #666
|
||||
}
|
||||
|
||||
.color-777 {
|
||||
color: #777
|
||||
}
|
||||
|
||||
.color-888 {
|
||||
color: #888
|
||||
}
|
||||
|
||||
.color-999 {
|
||||
color: #999
|
||||
}
|
||||
|
||||
.color-aaa {
|
||||
color: #aaa
|
||||
}
|
||||
|
||||
.color-bbb {
|
||||
color: #bbb
|
||||
}
|
||||
|
||||
.color-ccc {
|
||||
color: #ccc
|
||||
}
|
||||
|
||||
.color-ddd {
|
||||
color: #ddd
|
||||
}
|
||||
|
||||
.color-eee {
|
||||
color: #eee
|
||||
}
|
||||
|
||||
.color-text {
|
||||
color: #660E7A;
|
||||
}
|
||||
|
||||
.color-doc {
|
||||
color: #295496;
|
||||
}
|
||||
|
||||
.color-xls {
|
||||
color: #1E6C41;
|
||||
}
|
||||
|
||||
.color-ppt {
|
||||
color: #D04324;
|
||||
}
|
||||
|
||||
.color-pdf {
|
||||
color: #E40B0B;
|
||||
}
|
||||
|
||||
.color-audio {
|
||||
color: #5bc0de;
|
||||
}
|
||||
|
||||
.color-video {
|
||||
color: #5cb85c;
|
||||
}
|
||||
|
||||
.color-image {
|
||||
color: #0074D9;
|
||||
}
|
||||
|
||||
.color-archive {
|
||||
color: #4437f2;
|
||||
}
|
||||
|
||||
.color-light-active {
|
||||
color: #ffc60c;
|
||||
}
|
||||
|
||||
.color-light-inactive {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,132 +1,143 @@
|
||||
#layout{
|
||||
.margin(@from,@end,@step){
|
||||
.mX(@f,@e,@s) when (@e >= @f){
|
||||
.m@{e}{
|
||||
margin:@e*1px;
|
||||
/**
|
||||
全局常用样式定义
|
||||
使用ml、pt等缩写表示常用的布局方式,数字表示像素值
|
||||
比如ml10表示margin-left:10px;
|
||||
*/
|
||||
#layout {
|
||||
.margin(@from,@end,@step) {
|
||||
.mX(@f,@e,@s) when (@e >= @f) {
|
||||
.m@{e} {
|
||||
margin: @e*1px;
|
||||
}
|
||||
.mt@{e}{
|
||||
margin-top:@e*1px;
|
||||
.mt@{e} {
|
||||
margin-top: @e*1px;
|
||||
}
|
||||
.mr@{e}{
|
||||
margin-right:@e*1px;
|
||||
.mr@{e} {
|
||||
margin-right: @e*1px;
|
||||
}
|
||||
.mb@{e}{
|
||||
.mb@{e} {
|
||||
margin-bottom: @e*1px;
|
||||
}
|
||||
.ml@{e}{
|
||||
.ml@{e} {
|
||||
margin-left: @e*1px;
|
||||
}
|
||||
.mv@{e}{
|
||||
.mv@{e} {
|
||||
margin-top: @e*1px;
|
||||
margin-bottom: @e*1px;
|
||||
}
|
||||
.mh@{e}{
|
||||
.mh@{e} {
|
||||
margin-left: @e*1px;
|
||||
margin-right: @e*1px*1px;
|
||||
}
|
||||
.mX(@f,@e - @s,@s);
|
||||
.mX(@f, @e - @s, @s);
|
||||
}
|
||||
.mX(@from,@end,@step);
|
||||
.mX(@from, @end, @step);
|
||||
}
|
||||
.padding(@from,@end,@step){
|
||||
.pX(@f,@e,@s) when (@e >= @f){
|
||||
.p@{e}{
|
||||
padding:@e*1px;
|
||||
.padding(@from,@end,@step) {
|
||||
.pX(@f,@e,@s) when (@e >= @f) {
|
||||
.p@{e} {
|
||||
padding: @e*1px;
|
||||
}
|
||||
.pt@{e}{
|
||||
padding-top:@e*1px;
|
||||
.pt@{e} {
|
||||
padding-top: @e*1px;
|
||||
}
|
||||
.pr@{e}{
|
||||
padding-right:@e*1px;
|
||||
.pr@{e} {
|
||||
padding-right: @e*1px;
|
||||
}
|
||||
.pb@{e}{
|
||||
.pb@{e} {
|
||||
padding-bottom: @e*1px;
|
||||
}
|
||||
.pl@{e}{
|
||||
.pl@{e} {
|
||||
padding-left: @e*1px;
|
||||
}
|
||||
.pv@{e}{
|
||||
.pv@{e} {
|
||||
padding-top: @e*1px;
|
||||
padding-bottom: @e*1px;
|
||||
}
|
||||
.ph@{e}{
|
||||
.ph@{e} {
|
||||
padding-left: @e*1px;
|
||||
padding-right: @e*1px;
|
||||
}
|
||||
.pX(@f,@e - @s,@s);
|
||||
.pX(@f, @e - @s, @s);
|
||||
}
|
||||
.pX(@from,@end,@step);
|
||||
.pX(@from, @end, @step);
|
||||
}
|
||||
.width(@from,@end,@step){
|
||||
.wX(@f,@e,@s) when (@e >= @f){
|
||||
.w@{e}{
|
||||
width:@e*1px;
|
||||
.width(@from,@end,@step) {
|
||||
.wX(@f,@e,@s) when (@e >= @f) {
|
||||
.w@{e} {
|
||||
width: @e*1px;
|
||||
}
|
||||
.w@{e}m{
|
||||
max-width:@e*1px;
|
||||
.w@{e}m {
|
||||
max-width: @e*1px;
|
||||
}
|
||||
.w@{e}n{
|
||||
min-width:@e*1px;
|
||||
.w@{e}n {
|
||||
min-width: @e*1px;
|
||||
}
|
||||
.w@{e}i{
|
||||
width:@e*1px!important;
|
||||
.w@{e}i {
|
||||
width: @e*1px !important;
|
||||
}
|
||||
.wX(@f,@e - @s,@s);
|
||||
.wX(@f, @e - @s, @s);
|
||||
}
|
||||
.wX(@from,@end,@step);
|
||||
.wX(@from, @end, @step);
|
||||
}
|
||||
.height(@from,@end,@step){
|
||||
.hX(@f,@e,@s) when (@e >= @f){
|
||||
.h@{e}{
|
||||
height:@e*1px;
|
||||
.height(@from,@end,@step) {
|
||||
.hX(@f,@e,@s) when (@e >= @f) {
|
||||
.h@{e} {
|
||||
height: @e*1px;
|
||||
}
|
||||
.lh@{e}{
|
||||
line-height:@e*1px;
|
||||
.lh@{e} {
|
||||
line-height: @e*1px;
|
||||
}
|
||||
.h@{e}m{
|
||||
max-height:@e*1px;
|
||||
.h@{e}m {
|
||||
max-height: @e*1px;
|
||||
}
|
||||
.h@{e}n{
|
||||
min-height:@e*1px;
|
||||
.h@{e}n {
|
||||
min-height: @e*1px;
|
||||
}
|
||||
.h@{e}i{
|
||||
height:@e*1px!important;
|
||||
.h@{e}i {
|
||||
height: @e*1px !important;
|
||||
}
|
||||
.hX(@f,@e - @s,@s);
|
||||
.hX(@f, @e - @s, @s);
|
||||
}
|
||||
.hX(@from,@end,@step);
|
||||
.hX(@from, @end, @step);
|
||||
}
|
||||
}
|
||||
|
||||
.wp20{
|
||||
width:20%;
|
||||
.wp20 {
|
||||
width: 20%;
|
||||
}
|
||||
.wp25{
|
||||
width:25%;
|
||||
|
||||
.wp25 {
|
||||
width: 25%;
|
||||
}
|
||||
.wp33{
|
||||
width:33%;
|
||||
|
||||
.wp33 {
|
||||
width: 33%;
|
||||
}
|
||||
.wp100{
|
||||
width:100%;
|
||||
|
||||
.wp100 {
|
||||
width: 100%;
|
||||
}
|
||||
.wp50{
|
||||
width:50%;
|
||||
|
||||
.wp50 {
|
||||
width: 50%;
|
||||
}
|
||||
.hp100{
|
||||
height:100%;
|
||||
|
||||
.hp100 {
|
||||
height: 100%;
|
||||
}
|
||||
.hp50{
|
||||
|
||||
.hp50 {
|
||||
height: 50%;
|
||||
}
|
||||
|
||||
#layout > .margin(20,200,5);
|
||||
#layout > .margin(0,19,1);
|
||||
#layout > .padding(20,200,5);
|
||||
#layout > .padding(0,19,1);
|
||||
#layout > .width(20,400,10);
|
||||
#layout > .width(0,19,1);
|
||||
#layout > .height(20,400,10);
|
||||
#layout > .height(0,19,1);
|
||||
#layout > .margin(20, 200, 5);
|
||||
#layout > .margin(0, 19, 1);
|
||||
#layout > .padding(20, 200, 5);
|
||||
#layout > .padding(0, 19, 1);
|
||||
#layout > .width(20, 400, 5);
|
||||
#layout > .width(0, 19, 1);
|
||||
#layout > .height(20, 400, 5);
|
||||
#layout > .height(0, 19, 1);
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
@import "variables";
|
||||
|
||||
.compulsory {
|
||||
&:before {
|
||||
content: "*";
|
||||
@@ -21,27 +23,8 @@
|
||||
|
||||
}
|
||||
|
||||
.btn-file {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
|
||||
> input {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
margin: 0;
|
||||
opacity: 0;
|
||||
filter: alpha(opacity=0);
|
||||
font-size: 23px;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
direction: ltr;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
//超出三行使用点点点
|
||||
.list-text-restriction {
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
@@ -67,9 +50,101 @@
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.tank-box {
|
||||
//讨厌的outline
|
||||
a {
|
||||
outline: none;
|
||||
|
||||
&:focus, &:hover, &:active {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
//制造一个手机容器
|
||||
.mobile-container {
|
||||
max-width: 400px;
|
||||
border: 1px solid #eee;
|
||||
padding: 10px;
|
||||
margin: 10px auto;
|
||||
display: block;
|
||||
background-color: white;
|
||||
box-shadow: 0 0 5px rgba(0, 0, 0, .2);
|
||||
border-radius: 5px;
|
||||
padding: 20px 15px 10px 15px;
|
||||
}
|
||||
|
||||
|
||||
//按照字母来wrap,不然有些老长老长
|
||||
.wrap-word {
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.text-left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.text-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.text-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.display-none {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.pull-right {
|
||||
float: right !important;
|
||||
}
|
||||
|
||||
.pull-left {
|
||||
float: left !important;
|
||||
}
|
||||
|
||||
//超链接导航样式
|
||||
.link {
|
||||
color: #1890ff;
|
||||
text-decoration: none;
|
||||
background-color: transparent;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
transition: color 0.3s;
|
||||
text-decoration-skip: objects;
|
||||
}
|
||||
|
||||
|
||||
//头像
|
||||
.avatar-large {
|
||||
border-radius: 50%;
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.avatar-middle {
|
||||
border-radius: 50%;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.avatar-small {
|
||||
border-radius: 50%;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.relative {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.hot-area {
|
||||
position: relative;
|
||||
&:after {
|
||||
position: absolute;
|
||||
top: -10px;
|
||||
right: -10px;
|
||||
bottom: -10px;
|
||||
left: -10px;
|
||||
content: '';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
//超出三行使用点点点
|
||||
.line-ellipsis(@rows,@line-height) {
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
line-height: @line-height;
|
||||
max-height: @line-height * @rows;
|
||||
-webkit-line-clamp: @rows;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
@@ -19,18 +19,25 @@
|
||||
}
|
||||
|
||||
//浏览器滚动条样式
|
||||
.thin-scrollbar {
|
||||
::-webkit-scrollbar {
|
||||
width: 3px;
|
||||
height: 3px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
//滚动条样式
|
||||
::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
height: 10px
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
transition: all .3s ease;
|
||||
border-color: transparent;
|
||||
background-color: rgba(0, 0, 0, .1);
|
||||
z-index: 40
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
transition: all .3s ease;
|
||||
background-color: rgba(0, 0, 0, .15)
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-corner {
|
||||
background-color: #eaeaeb
|
||||
}
|
||||
|
||||
@@ -1,98 +1,22 @@
|
||||
@import "../bootstrap/variables.less";
|
||||
//Bootstrap Theme.
|
||||
//@brand-primary: darken(#428bca, 6.5%); // #337ab7
|
||||
//@brand-success: #5cb85c;
|
||||
//@brand-info: #5bc0de;
|
||||
//@brand-warning: #f0ad4e;
|
||||
//@brand-danger: #d9534f;
|
||||
//@brand-gray: #c2c2c2;
|
||||
|
||||
//Angulr Theme.
|
||||
//@brand-primary: #7266ba;
|
||||
//@brand-info: #23b7e5;
|
||||
//@brand-success: #27c24c;
|
||||
//@brand-warning: #fad733;
|
||||
//@brand-danger: #f05050;
|
||||
//@brand-light: #edf1f2;
|
||||
//@brand-dark: #3a3f51;
|
||||
//@brand-black: #1c2b36;
|
||||
//@brand-gray: #c2c2c2;
|
||||
//@brand-laxative: #B3EE3A;
|
||||
|
||||
//Inspina Theme.
|
||||
//@brand-primary: #1ab394;
|
||||
//@brand-success: #1c84c6;
|
||||
//@brand-info: #23c6c8;
|
||||
//@brand-warning: #f8ac59;
|
||||
//@brand-danger: #ED5565;
|
||||
//@brand-gray: #c2c2c2;
|
||||
//@brand-laxative: #B3EE3A;
|
||||
|
||||
|
||||
//zhengxianqian Theme.
|
||||
//@brand-primary: #23B7E5;
|
||||
@brand-primary: #006699;
|
||||
@brand-success: #1ab394;
|
||||
@brand-info: #5EC1C5;
|
||||
@brand-warning: #FEC62E;
|
||||
@brand-danger: #FE8768;
|
||||
//custom basic color
|
||||
@brand-primary: #215891;
|
||||
@brand-success: #67C23A;
|
||||
@brand-info: #2DB7F5;
|
||||
@brand-warning: #E6A23C;
|
||||
@brand-danger: #FF756F;
|
||||
@brand-gray: #c2c2c2;
|
||||
@brand-laxative: #B3EE3A;
|
||||
|
||||
//主题默认颜色
|
||||
@primary-color: @brand-primary;
|
||||
|
||||
@navy: @brand-primary; // Primary color
|
||||
@dark-gray: @brand-gray; // Default color
|
||||
@blue: @brand-success; // Success color
|
||||
@lazur: @brand-info; // Info color
|
||||
@yellow: @brand-warning; // Warrning color
|
||||
@red: @brand-danger; // Danger color
|
||||
@green: @brand-laxative; // Danger color
|
||||
|
||||
@gray-base: #000;
|
||||
@gray-darker: lighten(@gray-base, 13.5%); // #222
|
||||
@gray-dark: lighten(@gray-base, 20%); // #333
|
||||
@gray: lighten(@gray-base, 33.5%); // #555
|
||||
@gray-light: lighten(@gray-base, 46.7%); // #777
|
||||
@gray-lighter: lighten(@gray-base, 93.5%); // #eee
|
||||
|
||||
// Various colors
|
||||
@text-color: #676a6c; // Body text
|
||||
@gray: #f3f3f4; // Background wrapper color
|
||||
@light-gray: #D1DADE; // Default label, badget
|
||||
@label-badget-color: #5E5E5E;
|
||||
@light-blue: #f3f6fb;
|
||||
|
||||
// Spiner color and margin
|
||||
@spin-color: @navy;
|
||||
@spin-margin: 0 auto;
|
||||
|
||||
// IBOX colors ( default panel colors)
|
||||
@border-color: #e7eaec; // IBox border
|
||||
@ibox-title-bg: #ffffff; // IBox Background header
|
||||
@ibox-content-bg: #ffffff; // IBox Background content
|
||||
|
||||
//Sidebar width
|
||||
@sidebar-width: 170px;
|
||||
|
||||
// Boxed layout width
|
||||
@boxed-width: 1200px;
|
||||
|
||||
//Border radius for buttons
|
||||
@btn-border-radius: 3px;
|
||||
|
||||
//Navigation
|
||||
@nav-bg: #2F4050;
|
||||
@nav-text-color: #a7b1c2;
|
||||
|
||||
//左侧菜单宽度
|
||||
@sidebar-width: 200px;
|
||||
|
||||
//顶部导航栏宽度
|
||||
@top-navigation-height: 45px;
|
||||
|
||||
@app-color-title: #474747;
|
||||
@app-color-content: #8A8A8A;
|
||||
|
||||
//上方导航栏高度
|
||||
@frame-header-height: 80px;
|
||||
|
||||
//下方蓝眼云盘高度
|
||||
@power-footer-height: 40px;
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
//使用自定义的主题
|
||||
@import "global/animation";
|
||||
@import "global/border";
|
||||
@import "global/button";
|
||||
@import "global/color";
|
||||
@import "global/font";
|
||||
@import "global/layout";
|
||||
@import "global/miscellaneous";
|
||||
@import "global/responsive";
|
||||
|
||||
html, body {
|
||||
font-family: "微软雅黑", Microsoft YaHei, "Helvetica Neue", Helvetica, Arial, sans-serif, "open sans";
|
||||
font-size: 13px;
|
||||
color: @text-color;
|
||||
|
||||
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
|
||||
.label {
|
||||
background-color: @light-gray;
|
||||
color: @label-badget-color;
|
||||
font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
padding: 3px 8px;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.badge {
|
||||
background-color: @light-gray;
|
||||
color: @label-badget-color;
|
||||
font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
padding-bottom: 4px;
|
||||
padding-left: 6px;
|
||||
padding-right: 6px;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.label-primary, .badge-primary {
|
||||
background-color: @navy;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.label-success, .badge-success {
|
||||
background-color: @blue;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.label-warning, .badge-warning {
|
||||
background-color: @yellow;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.label-warning-light, .badge-warning-light {
|
||||
background-color: @yellow;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.label-danger, .badge-danger {
|
||||
background-color: @red;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.label-info, .badge-info {
|
||||
background-color: @lazur;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.label-inverse, .badge-inverse {
|
||||
background-color: #262626;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.label-laxative, .badge-laxative {
|
||||
background-color: @green;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.label-white, .badge-white {
|
||||
background-color: #FFFFFF;
|
||||
color: #5E5E5E;
|
||||
}
|
||||
|
||||
.label-white, .badge-disable {
|
||||
background-color: #2A2E36;
|
||||
color: #8B91A0;
|
||||
}
|
||||
@@ -1,309 +0,0 @@
|
||||
|
||||
.btn {
|
||||
border-radius: @btn-border-radius;
|
||||
}
|
||||
|
||||
.float-e-margins .btn {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.btn-w-m {
|
||||
min-width: 120px;
|
||||
}
|
||||
|
||||
.btn-primary.btn-outline {
|
||||
color: @navy;
|
||||
}
|
||||
|
||||
.btn-success.btn-outline {
|
||||
color: @blue;
|
||||
}
|
||||
|
||||
.btn-info.btn-outline {
|
||||
color: @lazur;
|
||||
}
|
||||
|
||||
.btn-warning.btn-outline {
|
||||
color: @yellow;
|
||||
}
|
||||
|
||||
.btn-danger.btn-outline {
|
||||
color: @red;
|
||||
}
|
||||
|
||||
.btn-primary.btn-outline:hover,
|
||||
.btn-success.btn-outline:hover,
|
||||
.btn-info.btn-outline:hover,
|
||||
.btn-warning.btn-outline:hover,
|
||||
.btn-danger.btn-outline:hover {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: @navy;
|
||||
border-color: @navy;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.btn-primary:hover, .btn-primary:focus, .btn-primary:active, .btn-primary.active, .open .dropdown-toggle.btn-primary, .btn-primary:active:focus, .btn-primary:active:hover, .btn-primary.active:hover, .btn-primary.active:focus {
|
||||
background-color: darken(@navy, 3%);
|
||||
border-color: darken(@navy, 3%);
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.btn-primary:active, .btn-primary.active, .open .dropdown-toggle.btn-primary {
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
.btn-primary.disabled, .btn-primary.disabled:hover, .btn-primary.disabled:focus, .btn-primary.disabled:active, .btn-primary.disabled.active, .btn-primary[disabled], .btn-primary[disabled]:hover, .btn-primary[disabled]:focus, .btn-primary[disabled]:active, .btn-primary.active[disabled], fieldset[disabled] .btn-primary, fieldset[disabled] .btn-primary:hover, fieldset[disabled] .btn-primary:focus, fieldset[disabled] .btn-primary:active, fieldset[disabled] .btn-primary.active {
|
||||
background-color: lighten(@navy, 4%);
|
||||
border-color: lighten(@navy, 4%);
|
||||
}
|
||||
|
||||
.btn-success {
|
||||
background-color: @blue;
|
||||
border-color: @blue;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.btn-success:hover, .btn-success:focus, .btn-success:active, .btn-success.active, .open .dropdown-toggle.btn-success, .btn-success:active:focus, .btn-success:active:hover, .btn-success.active:hover, .btn-success.active:focus {
|
||||
background-color: darken(@blue, 3%);
|
||||
border-color: darken(@blue, 3%);
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.btn-success:active, .btn-success.active, .open .dropdown-toggle.btn-success {
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
.btn-success.disabled, .btn-success.disabled:hover, .btn-success.disabled:focus, .btn-success.disabled:active, .btn-success.disabled.active, .btn-success[disabled], .btn-success[disabled]:hover, .btn-success[disabled]:focus, .btn-success[disabled]:active, .btn-success.active[disabled], fieldset[disabled] .btn-success, fieldset[disabled] .btn-success:hover, fieldset[disabled] .btn-success:focus, fieldset[disabled] .btn-success:active, fieldset[disabled] .btn-success.active {
|
||||
background-color: lighten(@blue, 4%);
|
||||
border-color: lighten(@blue, 4%);
|
||||
}
|
||||
|
||||
.btn-info {
|
||||
background-color: @lazur;
|
||||
border-color: @lazur;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.btn-info:hover, .btn-info:focus, .btn-info:active, .btn-info.active, .open .dropdown-toggle.btn-info, .btn-info:active:focus, .btn-info:active:hover, .btn-info.active:hover, .btn-info.active:focus {
|
||||
background-color: darken(@lazur, 3%);
|
||||
border-color: darken(@lazur, 3%);
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.btn-info:active, .btn-info.active, .open .dropdown-toggle.btn-info {
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
.btn-info.disabled, .btn-info.disabled:hover, .btn-info.disabled:focus, .btn-info.disabled:active, .btn-info.disabled.active, .btn-info[disabled], .btn-info[disabled]:hover, .btn-info[disabled]:focus, .btn-info[disabled]:active, .btn-info.active[disabled], fieldset[disabled] .btn-info, fieldset[disabled] .btn-info:hover, fieldset[disabled] .btn-info:focus, fieldset[disabled] .btn-info:active, fieldset[disabled] .btn-info.active {
|
||||
background-color: lighten(@lazur, 4%);
|
||||
border-color: lighten(@lazur, 4%);
|
||||
}
|
||||
|
||||
.btn-default {
|
||||
color: inherit;
|
||||
background: white;
|
||||
border: 1px solid @border-color;
|
||||
}
|
||||
|
||||
.btn-default:hover, .btn-default:focus, .btn-default:active, .btn-default.active, .open .dropdown-toggle.btn-default, .btn-default:active:focus, .btn-default:active:hover, .btn-default.active:hover, .btn-default.active:focus {
|
||||
color: inherit;
|
||||
border: 1px solid #d2d2d2;
|
||||
}
|
||||
|
||||
.btn-default:active, .btn-default.active, .open .dropdown-toggle.btn-default {
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15) inset;
|
||||
}
|
||||
|
||||
.btn-default.disabled, .btn-default.disabled:hover, .btn-default.disabled:focus, .btn-default.disabled:active, .btn-default.disabled.active, .btn-default[disabled], .btn-default[disabled]:hover, .btn-default[disabled]:focus, .btn-default[disabled]:active, .btn-default.active[disabled], fieldset[disabled] .btn-default, fieldset[disabled] .btn-default:hover, fieldset[disabled] .btn-default:focus, fieldset[disabled] .btn-default:active, fieldset[disabled] .btn-default.active {
|
||||
color: #cacaca;
|
||||
}
|
||||
|
||||
.btn-warning {
|
||||
background-color: @yellow;
|
||||
border-color: @yellow;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.btn-warning:hover, .btn-warning:focus, .btn-warning:active, .btn-warning.active, .open .dropdown-toggle.btn-warning, .btn-warning:active:focus, .btn-warning:active:hover, .btn-warning.active:hover, .btn-warning.active:focus {
|
||||
background-color: darken(@yellow, 3%);
|
||||
border-color: darken(@yellow, 3%);
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.btn-warning:active, .btn-warning.active, .open .dropdown-toggle.btn-warning {
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
.btn-warning.disabled, .btn-warning.disabled:hover, .btn-warning.disabled:focus, .btn-warning.disabled:active, .btn-warning.disabled.active, .btn-warning[disabled], .btn-warning[disabled]:hover, .btn-warning[disabled]:focus, .btn-warning[disabled]:active, .btn-warning.active[disabled], fieldset[disabled] .btn-warning, fieldset[disabled] .btn-warning:hover, fieldset[disabled] .btn-warning:focus, fieldset[disabled] .btn-warning:active, fieldset[disabled] .btn-warning.active {
|
||||
background-color: lighten(@yellow, 4%);
|
||||
border-color: lighten(@yellow, 4%);
|
||||
}
|
||||
|
||||
.btn-danger {
|
||||
background-color: @red;
|
||||
border-color: @red;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.btn-danger:hover, .btn-danger:focus, .btn-danger:active, .btn-danger.active, .open .dropdown-toggle.btn-danger, .btn-danger:active:focus, .btn-danger:active:hover, .btn-danger.active:hover, .btn-danger.active:focus {
|
||||
background-color: darken(@red, 3%);
|
||||
border-color: darken(@red, 3%);
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.btn-danger:active, .btn-danger.active, .open .dropdown-toggle.btn-danger {
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
.btn-danger.disabled, .btn-danger.disabled:hover, .btn-danger.disabled:focus, .btn-danger.disabled:active, .btn-danger.disabled.active, .btn-danger[disabled], .btn-danger[disabled]:hover, .btn-danger[disabled]:focus, .btn-danger[disabled]:active, .btn-danger.active[disabled], fieldset[disabled] .btn-danger, fieldset[disabled] .btn-danger:hover, fieldset[disabled] .btn-danger:focus, fieldset[disabled] .btn-danger:active, fieldset[disabled] .btn-danger.active {
|
||||
background-color: lighten(@red, 4%);
|
||||
border-color: lighten(@red, 4%);
|
||||
}
|
||||
|
||||
.btn-link {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.btn-link:hover, .btn-link:focus, .btn-link:active, .btn-link.active, .open .dropdown-toggle.btn-link {
|
||||
color: @navy;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.btn-link:active, .btn-link.active, .open .dropdown-toggle.btn-link {
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
.btn-link.disabled, .btn-link.disabled:hover, .btn-link.disabled:focus, .btn-link.disabled:active, .btn-link.disabled.active, .btn-link[disabled], .btn-link[disabled]:hover, .btn-link[disabled]:focus, .btn-link[disabled]:active, .btn-link.active[disabled], fieldset[disabled] .btn-link, fieldset[disabled] .btn-link:hover, fieldset[disabled] .btn-link:focus, fieldset[disabled] .btn-link:active, fieldset[disabled] .btn-link.active {
|
||||
color: #cacaca;
|
||||
}
|
||||
|
||||
.btn-white {
|
||||
color: inherit;
|
||||
background: white;
|
||||
border: 1px solid @border-color;
|
||||
}
|
||||
|
||||
.btn-white:hover, .btn-white:focus, .btn-white:active, .btn-white.active, .open .dropdown-toggle.btn-white, .btn-white:active:focus, .btn-white:active:hover, .btn-white.active:hover, .btn-white.active:focus {
|
||||
color: inherit;
|
||||
border: 1px solid #d2d2d2;
|
||||
}
|
||||
|
||||
.btn-white:active, .btn-white.active {
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15) inset;
|
||||
}
|
||||
|
||||
.btn-white:active, .btn-white.active, .open .dropdown-toggle.btn-white {
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
.btn-white.disabled, .btn-white.disabled:hover, .btn-white.disabled:focus, .btn-white.disabled:active, .btn-white.disabled.active, .btn-white[disabled], .btn-white[disabled]:hover, .btn-white[disabled]:focus, .btn-white[disabled]:active, .btn-white.active[disabled], fieldset[disabled] .btn-white, fieldset[disabled] .btn-white:hover, fieldset[disabled] .btn-white:focus, fieldset[disabled] .btn-white:active, fieldset[disabled] .btn-white.active {
|
||||
color: #cacaca;
|
||||
}
|
||||
|
||||
.form-control, .form-control:focus, .has-error .form-control:focus, .has-success .form-control:focus, .has-warning .form-control:focus, .navbar-collapse, .navbar-form, .navbar-form-custom .form-control:focus, .navbar-form-custom .form-control:hover, .open .btn.dropdown-toggle, .panel, .popover, .progress, .progress-bar {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.btn-outline {
|
||||
color: inherit;
|
||||
background-color: transparent;
|
||||
transition: all .5s;
|
||||
}
|
||||
|
||||
.btn-rounded {
|
||||
border-radius: 50px;
|
||||
}
|
||||
|
||||
.btn-large-dim {
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
font-size: 42px;
|
||||
}
|
||||
|
||||
button.dim {
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
text-transform: uppercase;
|
||||
text-align: center;
|
||||
padding-top: 6px;
|
||||
margin-right: 10px;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
border-radius: 5px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 20px !important;
|
||||
}
|
||||
|
||||
button.dim:active {
|
||||
top: 3px;
|
||||
}
|
||||
|
||||
button.btn-primary.dim {
|
||||
box-shadow: inset 0 0 0 darken(@navy, 6%), 0 5px 0 0 darken(@navy, 6%), 0 10px 5px #999;
|
||||
}
|
||||
|
||||
button.btn-primary.dim:active {
|
||||
box-shadow: inset 0 0 0 darken(@navy, 6%), 0 2px 0 0 darken(@navy, 6%), 0 5px 3px #999;
|
||||
}
|
||||
|
||||
button.btn-default.dim {
|
||||
box-shadow: inset 0 0 0 darken(@dark-gray, 6%), 0 5px 0 0 darken(@dark-gray, 6%), 0 10px 5px #999;
|
||||
}
|
||||
|
||||
button.btn-default.dim:active {
|
||||
box-shadow: inset 0 0 0 darken(@dark-gray, 6%), 0 2px 0 0 darken(@dark-gray, 6%), 0 5px 3px #999;
|
||||
}
|
||||
|
||||
button.btn-warning.dim {
|
||||
box-shadow: inset 0 0 0 darken(@yellow, 6%), 0 5px 0 0 darken(@yellow, 6%), 0 10px 5px #999;
|
||||
}
|
||||
|
||||
button.btn-warning.dim:active {
|
||||
box-shadow: inset 0 0 0 darken(@yellow, 6%), 0 2px 0 0 darken(@yellow, 6%), 0 5px 3px #999;
|
||||
}
|
||||
|
||||
button.btn-info.dim {
|
||||
box-shadow: inset 0 0 0 darken(@lazur, 6%), 0 5px 0 0 darken(@lazur, 6%), 0 10px 5px #999;
|
||||
}
|
||||
|
||||
button.btn-info.dim:active {
|
||||
box-shadow: inset 0 0 0 darken(@lazur, 6%), 0 2px 0 0 darken(@lazur, 6%), 0 5px 3px #999;
|
||||
}
|
||||
|
||||
button.btn-success.dim {
|
||||
box-shadow: inset 0 0 0 darken(@blue, 6%), 0 5px 0 0 darken(@blue, 6%), 0 10px 5px #999;
|
||||
}
|
||||
|
||||
button.btn-success.dim:active {
|
||||
box-shadow: inset 0 0 0 darken(@blue, 6%), 0 2px 0 0 darken(@blue, 6%), 0 5px 3px #999;
|
||||
}
|
||||
|
||||
button.btn-danger.dim {
|
||||
box-shadow: inset 0 0 0 darken(@red, 6%), 0 5px 0 0 darken(@red, 6%), 0 10px 5px #999;
|
||||
}
|
||||
|
||||
button.btn-danger.dim:active {
|
||||
box-shadow: inset 0 0 0 darken(@red, 6%), 0 2px 0 0 darken(@red, 6%), 0 5px 3px #999;
|
||||
}
|
||||
|
||||
button.dim:before {
|
||||
font-size: 50px;
|
||||
line-height: 1em;
|
||||
font-weight: normal;
|
||||
color: #fff;
|
||||
display: block;
|
||||
padding-top: 10px;
|
||||
|
||||
}
|
||||
|
||||
button.dim:active:before {
|
||||
top: 7px;
|
||||
font-size: 50px;
|
||||
}
|
||||
|
||||
.btn:focus {
|
||||
outline: none !important;
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
#small-chat {
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
#small-chat .badge {
|
||||
position: absolute;
|
||||
top: -3px;
|
||||
right: -4px;
|
||||
}
|
||||
|
||||
.open-small-chat {
|
||||
height: 38px;
|
||||
width: 38px;
|
||||
display: block;
|
||||
background: #1ab394;
|
||||
padding: 9px 8px;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.open-small-chat:hover {
|
||||
color: white;
|
||||
background: #1ab394;
|
||||
}
|
||||
|
||||
.small-chat-box {
|
||||
display: none;
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
right: 75px;
|
||||
background: #fff;
|
||||
border: 1px solid @border-color;
|
||||
width: 230px;
|
||||
height: 320px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.small-chat-box.ng-small-chat {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
.small-chat-box.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.small-chat-box {
|
||||
|
||||
.heading {
|
||||
background: @nav-bg;
|
||||
padding: 8px 15px;
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.chat-date {
|
||||
opacity: 0.6;
|
||||
font-size: 10px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 15px 15px;
|
||||
|
||||
.author-name {
|
||||
font-weight: bold;
|
||||
margin-bottom: 3px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
> div {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
.chat-message {
|
||||
padding: 5px 10px;
|
||||
border-radius: 6px;
|
||||
font-size: 11px;
|
||||
line-height: 14px;
|
||||
max-width: 80%;
|
||||
background: #f3f3f4;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.chat-message.active {
|
||||
background: #1ab394;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.left {
|
||||
text-align: left;
|
||||
clear: both;
|
||||
|
||||
.chat-message {
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
text-align: right;
|
||||
clear: both;
|
||||
|
||||
.chat-message {
|
||||
float: right;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.form-chat {
|
||||
padding: 10px 10px;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
.border-radius (@radius: 3px) {
|
||||
-webkit-border-radius: @radius;
|
||||
-moz-border-radius: @radius;
|
||||
border-radius: @radius;
|
||||
|
||||
-moz-background-clip: padding;
|
||||
-webkit-background-clip: padding-box;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
.opacity (@opacity: 0.5) {
|
||||
-webkit-opacity: @opacity;
|
||||
-moz-opacity: @opacity;
|
||||
opacity: @opacity;
|
||||
}
|
||||
@@ -1,191 +0,0 @@
|
||||
.sidebard-panel {
|
||||
width: 220px;
|
||||
background: darken(@gray, 3%);
|
||||
padding: 10px 20px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.sidebard-panel .feed-element img.img-circle {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.sidebard-panel .feed-element, .media-body, .sidebard-panel p {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.sidebard-panel .feed-element {
|
||||
margin-top: 20px;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.sidebard-panel .list-group {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.sidebard-panel .list-group .list-group-item {
|
||||
padding: 5px 0;
|
||||
font-size: 12px;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.sidebar-content .wrapper, .wrapper.sidebar-content {
|
||||
padding-right: 230px !important;
|
||||
}
|
||||
|
||||
// Right sidebar
|
||||
|
||||
#right-sidebar {
|
||||
background-color: #fff;
|
||||
border-left: 1px solid #e7eaec;
|
||||
border-top: 1px solid #e7eaec;
|
||||
overflow: hidden;
|
||||
position: fixed;
|
||||
top: 60px;
|
||||
width: 260px !important;
|
||||
z-index: 1009;
|
||||
bottom: 0;
|
||||
right: -260px;
|
||||
}
|
||||
|
||||
#right-sidebar.sidebar-open {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
#right-sidebar.sidebar-open.sidebar-top {
|
||||
top: 0;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.sidebar-container {
|
||||
|
||||
ul.nav-tabs {
|
||||
border: none;
|
||||
}
|
||||
|
||||
ul.nav-tabs.navs-4 li {
|
||||
width: 25%;
|
||||
}
|
||||
ul.nav-tabs.navs-3 li {
|
||||
width: 33.3333%;
|
||||
}
|
||||
ul.nav-tabs.navs-2 li {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
ul.nav-tabs li {
|
||||
border: none;
|
||||
}
|
||||
|
||||
ul.nav-tabs li a {
|
||||
border: none;
|
||||
padding: 12px 10px;
|
||||
margin: 0;
|
||||
border-radius: 0;
|
||||
background: @nav-bg;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
|
||||
border-right: 1px solid lighten(@nav-bg, 2%);
|
||||
}
|
||||
|
||||
ul.nav-tabs li.active a {
|
||||
border: none;
|
||||
background: #f9f9f9;
|
||||
color: @text-color;
|
||||
font-weight: bold;
|
||||
|
||||
}
|
||||
|
||||
.nav-tabs > li.active > a:hover,
|
||||
.nav-tabs > li.active > a:focus {
|
||||
|
||||
border: none;
|
||||
|
||||
}
|
||||
|
||||
ul.sidebar-list {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ul.sidebar-list li {
|
||||
border-bottom: 1px solid @border-color;
|
||||
padding: 15px 20px;
|
||||
list-style: none;
|
||||
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
ul.sidebar-list li:nth-child(2n+2) {
|
||||
// background: #f9f9f9;
|
||||
}
|
||||
|
||||
.sidebar-message:nth-child(2n+2) {
|
||||
background: #f9f9f9;
|
||||
}
|
||||
|
||||
ul.sidebar-list li a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.sidebar-content {
|
||||
padding: 15px 20px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.date-item {
|
||||
|
||||
}
|
||||
|
||||
.sidebar-title {
|
||||
background: #f9f9f9;
|
||||
padding: 20px;
|
||||
border-bottom: 1px solid @border-color;
|
||||
|
||||
h3 {
|
||||
margin-bottom: 3px;
|
||||
padding-left: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
|
||||
h4 {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.sidebar-message > a > .pull-left {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.sidebar-message > a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.sidebar-message {
|
||||
padding: 15px 20px;
|
||||
}
|
||||
|
||||
.sidebar-message:hover {
|
||||
// background: #f9f9f9;
|
||||
}
|
||||
|
||||
.sidebar-message .message-avatar {
|
||||
height: 38px;
|
||||
width: 38px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.setings-item {
|
||||
padding: 15px 20px;
|
||||
border-bottom: 1px solid @border-color;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,997 +0,0 @@
|
||||
/*
|
||||
* Usage:
|
||||
*
|
||||
* <div class="sk-spinner sk-spinner-rotating-plane"></div>
|
||||
*
|
||||
*/
|
||||
|
||||
.sk-spinner-rotating-plane.sk-spinner {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
background-color: @spin-color;
|
||||
margin: @spin-margin;
|
||||
-webkit-animation: sk-rotatePlane 1.2s infinite ease-in-out;
|
||||
animation: sk-rotatePlane 1.2s infinite ease-in-out;
|
||||
}
|
||||
|
||||
@-webkit-keyframes sk-rotatePlane {
|
||||
0% {
|
||||
-webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg);
|
||||
transform: perspective(120px) rotateX(0deg) rotateY(0deg);
|
||||
}
|
||||
|
||||
50% {
|
||||
-webkit-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg);
|
||||
transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
|
||||
transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes sk-rotatePlane {
|
||||
0% {
|
||||
-webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg);
|
||||
transform: perspective(120px) rotateX(0deg) rotateY(0deg);
|
||||
}
|
||||
|
||||
50% {
|
||||
-webkit-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg);
|
||||
transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
|
||||
transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Usage:
|
||||
*
|
||||
* <div class="sk-spinner sk-spinner-double-bounce">
|
||||
* <div class="sk-double-bounce1"></div>
|
||||
* <div class="sk-double-bounce2"></div>
|
||||
* </div>
|
||||
*
|
||||
*/
|
||||
.sk-spinner-double-bounce.sk-spinner {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
position: relative;
|
||||
margin: @spin-margin;
|
||||
}
|
||||
|
||||
.sk-spinner-double-bounce .sk-double-bounce1, .sk-spinner-double-bounce .sk-double-bounce2 {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
background-color: @spin-color;
|
||||
opacity: 0.6;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
-webkit-animation: sk-doubleBounce 2s infinite ease-in-out;
|
||||
animation: sk-doubleBounce 2s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.sk-spinner-double-bounce .sk-double-bounce2 {
|
||||
-webkit-animation-delay: -1s;
|
||||
animation-delay: -1s;
|
||||
}
|
||||
|
||||
@-webkit-keyframes sk-doubleBounce {
|
||||
0%, 100% {
|
||||
-webkit-transform: scale(0);
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
50% {
|
||||
-webkit-transform: scale(1);
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes sk-doubleBounce {
|
||||
0%, 100% {
|
||||
-webkit-transform: scale(0);
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
50% {
|
||||
-webkit-transform: scale(1);
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Usage:
|
||||
*
|
||||
* <div class="sk-spinner sk-spinner-wave">
|
||||
* <div class="sk-rect1"></div>
|
||||
* <div class="sk-rect2"></div>
|
||||
* <div class="sk-rect3"></div>
|
||||
* <div class="sk-rect4"></div>
|
||||
* <div class="sk-rect5"></div>
|
||||
* </div>
|
||||
*
|
||||
*/
|
||||
.sk-spinner-wave.sk-spinner {
|
||||
margin: @spin-margin;
|
||||
width: 50px;
|
||||
height: 30px;
|
||||
text-align: center;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.sk-spinner-wave div {
|
||||
background-color: @spin-color;
|
||||
height: 100%;
|
||||
width: 6px;
|
||||
display: inline-block;
|
||||
-webkit-animation: sk-waveStretchDelay 1.2s infinite ease-in-out;
|
||||
animation: sk-waveStretchDelay 1.2s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.sk-spinner-wave .sk-rect2 {
|
||||
-webkit-animation-delay: -1.1s;
|
||||
animation-delay: -1.1s;
|
||||
}
|
||||
|
||||
.sk-spinner-wave .sk-rect3 {
|
||||
-webkit-animation-delay: -1s;
|
||||
animation-delay: -1s;
|
||||
}
|
||||
|
||||
.sk-spinner-wave .sk-rect4 {
|
||||
-webkit-animation-delay: -0.9s;
|
||||
animation-delay: -0.9s;
|
||||
}
|
||||
|
||||
.sk-spinner-wave .sk-rect5 {
|
||||
-webkit-animation-delay: -0.8s;
|
||||
animation-delay: -0.8s;
|
||||
}
|
||||
|
||||
@-webkit-keyframes sk-waveStretchDelay {
|
||||
0%, 40%, 100% {
|
||||
-webkit-transform: scaleY(0.4);
|
||||
transform: scaleY(0.4);
|
||||
}
|
||||
|
||||
20% {
|
||||
-webkit-transform: scaleY(1);
|
||||
transform: scaleY(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes sk-waveStretchDelay {
|
||||
0%, 40%, 100% {
|
||||
-webkit-transform: scaleY(0.4);
|
||||
transform: scaleY(0.4);
|
||||
}
|
||||
|
||||
20% {
|
||||
-webkit-transform: scaleY(1);
|
||||
transform: scaleY(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Usage:
|
||||
*
|
||||
* <div class="sk-spinner sk-spinner-wandering-cubes">
|
||||
* <div class="sk-cube1"></div>
|
||||
* <div class="sk-cube2"></div>
|
||||
* </div>
|
||||
*
|
||||
*/
|
||||
.sk-spinner-wandering-cubes.sk-spinner {
|
||||
margin: @spin-margin;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.sk-spinner-wandering-cubes .sk-cube1, .sk-spinner-wandering-cubes .sk-cube2 {
|
||||
background-color: @spin-color;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
-webkit-animation: sk-wanderingCubeMove 1.8s infinite ease-in-out;
|
||||
animation: sk-wanderingCubeMove 1.8s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.sk-spinner-wandering-cubes .sk-cube2 {
|
||||
-webkit-animation-delay: -0.9s;
|
||||
animation-delay: -0.9s;
|
||||
}
|
||||
|
||||
@-webkit-keyframes sk-wanderingCubeMove {
|
||||
25% {
|
||||
-webkit-transform: translateX(42px) rotate(-90deg) scale(0.5);
|
||||
transform: translateX(42px) rotate(-90deg) scale(0.5);
|
||||
}
|
||||
|
||||
50% {
|
||||
/* Hack to make FF rotate in the right direction */
|
||||
-webkit-transform: translateX(42px) translateY(42px) rotate(-179deg);
|
||||
transform: translateX(42px) translateY(42px) rotate(-179deg);
|
||||
}
|
||||
|
||||
50.1% {
|
||||
-webkit-transform: translateX(42px) translateY(42px) rotate(-180deg);
|
||||
transform: translateX(42px) translateY(42px) rotate(-180deg);
|
||||
}
|
||||
|
||||
75% {
|
||||
-webkit-transform: translateX(0px) translateY(42px) rotate(-270deg) scale(0.5);
|
||||
transform: translateX(0px) translateY(42px) rotate(-270deg) scale(0.5);
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: rotate(-360deg);
|
||||
transform: rotate(-360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes sk-wanderingCubeMove {
|
||||
25% {
|
||||
-webkit-transform: translateX(42px) rotate(-90deg) scale(0.5);
|
||||
transform: translateX(42px) rotate(-90deg) scale(0.5);
|
||||
}
|
||||
|
||||
50% {
|
||||
/* Hack to make FF rotate in the right direction */
|
||||
-webkit-transform: translateX(42px) translateY(42px) rotate(-179deg);
|
||||
transform: translateX(42px) translateY(42px) rotate(-179deg);
|
||||
}
|
||||
|
||||
50.1% {
|
||||
-webkit-transform: translateX(42px) translateY(42px) rotate(-180deg);
|
||||
transform: translateX(42px) translateY(42px) rotate(-180deg);
|
||||
}
|
||||
|
||||
75% {
|
||||
-webkit-transform: translateX(0px) translateY(42px) rotate(-270deg) scale(0.5);
|
||||
transform: translateX(0px) translateY(42px) rotate(-270deg) scale(0.5);
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: rotate(-360deg);
|
||||
transform: rotate(-360deg);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Usage:
|
||||
*
|
||||
* <div class="sk-spinner sk-spinner-pulse"></div>
|
||||
*
|
||||
*/
|
||||
.sk-spinner-pulse.sk-spinner {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin: @spin-margin;
|
||||
background-color: @spin-color;
|
||||
border-radius: 100%;
|
||||
-webkit-animation: sk-pulseScaleOut 1s infinite ease-in-out;
|
||||
animation: sk-pulseScaleOut 1s infinite ease-in-out;
|
||||
}
|
||||
|
||||
@-webkit-keyframes sk-pulseScaleOut {
|
||||
0% {
|
||||
-webkit-transform: scale(0);
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: scale(1);
|
||||
transform: scale(1);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes sk-pulseScaleOut {
|
||||
0% {
|
||||
-webkit-transform: scale(0);
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: scale(1);
|
||||
transform: scale(1);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Usage:
|
||||
*
|
||||
* <div class="sk-spinner sk-spinner-chasing-dots">
|
||||
* <div class="sk-dot1"></div>
|
||||
* <div class="sk-dot2"></div>
|
||||
* </div>
|
||||
*
|
||||
*/
|
||||
.sk-spinner-chasing-dots.sk-spinner {
|
||||
margin: @spin-margin;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
-webkit-animation: sk-chasingDotsRotate 2s infinite linear;
|
||||
animation: sk-chasingDotsRotate 2s infinite linear;
|
||||
}
|
||||
|
||||
.sk-spinner-chasing-dots .sk-dot1, .sk-spinner-chasing-dots .sk-dot2 {
|
||||
width: 60%;
|
||||
height: 60%;
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
background-color: @spin-color;
|
||||
border-radius: 100%;
|
||||
-webkit-animation: sk-chasingDotsBounce 2s infinite ease-in-out;
|
||||
animation: sk-chasingDotsBounce 2s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.sk-spinner-chasing-dots .sk-dot2 {
|
||||
top: auto;
|
||||
bottom: 0;
|
||||
-webkit-animation-delay: -1s;
|
||||
animation-delay: -1s;
|
||||
}
|
||||
|
||||
@-webkit-keyframes sk-chasingDotsRotate {
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes sk-chasingDotsRotate {
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes sk-chasingDotsBounce {
|
||||
0%, 100% {
|
||||
-webkit-transform: scale(0);
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
50% {
|
||||
-webkit-transform: scale(1);
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes sk-chasingDotsBounce {
|
||||
0%, 100% {
|
||||
-webkit-transform: scale(0);
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
50% {
|
||||
-webkit-transform: scale(1);
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Usage:
|
||||
*
|
||||
* <div class="sk-spinner sk-spinner-three-bounce">
|
||||
* <div class="sk-bounce1"></div>
|
||||
* <div class="sk-bounce2"></div>
|
||||
* <div class="sk-bounce3"></div>
|
||||
* </div>
|
||||
*
|
||||
*/
|
||||
.sk-spinner-three-bounce.sk-spinner {
|
||||
margin: @spin-margin;
|
||||
width: 70px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.sk-spinner-three-bounce div {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
background-color: @spin-color;
|
||||
border-radius: 100%;
|
||||
display: inline-block;
|
||||
-webkit-animation: sk-threeBounceDelay 1.4s infinite ease-in-out;
|
||||
animation: sk-threeBounceDelay 1.4s infinite ease-in-out;
|
||||
/* Prevent first frame from flickering when animation starts */
|
||||
-webkit-animation-fill-mode: both;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
|
||||
.sk-spinner-three-bounce .sk-bounce1 {
|
||||
-webkit-animation-delay: -0.32s;
|
||||
animation-delay: -0.32s;
|
||||
}
|
||||
|
||||
.sk-spinner-three-bounce .sk-bounce2 {
|
||||
-webkit-animation-delay: -0.16s;
|
||||
animation-delay: -0.16s;
|
||||
}
|
||||
|
||||
@-webkit-keyframes sk-threeBounceDelay {
|
||||
0%, 80%, 100% {
|
||||
-webkit-transform: scale(0);
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
40% {
|
||||
-webkit-transform: scale(1);
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes sk-threeBounceDelay {
|
||||
0%, 80%, 100% {
|
||||
-webkit-transform: scale(0);
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
40% {
|
||||
-webkit-transform: scale(1);
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Usage:
|
||||
*
|
||||
* <div class="sk-spinner sk-spinner-circle">
|
||||
* <div class="sk-circle1 sk-circle"></div>
|
||||
* <div class="sk-circle2 sk-circle"></div>
|
||||
* <div class="sk-circle3 sk-circle"></div>
|
||||
* <div class="sk-circle4 sk-circle"></div>
|
||||
* <div class="sk-circle5 sk-circle"></div>
|
||||
* <div class="sk-circle6 sk-circle"></div>
|
||||
* <div class="sk-circle7 sk-circle"></div>
|
||||
* <div class="sk-circle8 sk-circle"></div>
|
||||
* <div class="sk-circle9 sk-circle"></div>
|
||||
* <div class="sk-circle10 sk-circle"></div>
|
||||
* <div class="sk-circle11 sk-circle"></div>
|
||||
* <div class="sk-circle12 sk-circle"></div>
|
||||
* </div>
|
||||
*
|
||||
*/
|
||||
.sk-spinner-circle.sk-spinner {
|
||||
margin: @spin-margin;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.sk-spinner-circle .sk-circle {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.sk-spinner-circle .sk-circle:before {
|
||||
content: '';
|
||||
display: block;
|
||||
margin: @spin-margin;
|
||||
width: 20%;
|
||||
height: 20%;
|
||||
background-color: @spin-color;
|
||||
border-radius: 100%;
|
||||
-webkit-animation: sk-circleBounceDelay 1.2s infinite ease-in-out;
|
||||
animation: sk-circleBounceDelay 1.2s infinite ease-in-out;
|
||||
/* Prevent first frame from flickering when animation starts */
|
||||
-webkit-animation-fill-mode: both;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
|
||||
.sk-spinner-circle .sk-circle2 {
|
||||
-webkit-transform: rotate(30deg);
|
||||
-ms-transform: rotate(30deg);
|
||||
transform: rotate(30deg);
|
||||
}
|
||||
|
||||
.sk-spinner-circle .sk-circle3 {
|
||||
-webkit-transform: rotate(60deg);
|
||||
-ms-transform: rotate(60deg);
|
||||
transform: rotate(60deg);
|
||||
}
|
||||
|
||||
.sk-spinner-circle .sk-circle4 {
|
||||
-webkit-transform: rotate(90deg);
|
||||
-ms-transform: rotate(90deg);
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.sk-spinner-circle .sk-circle5 {
|
||||
-webkit-transform: rotate(120deg);
|
||||
-ms-transform: rotate(120deg);
|
||||
transform: rotate(120deg);
|
||||
}
|
||||
|
||||
.sk-spinner-circle .sk-circle6 {
|
||||
-webkit-transform: rotate(150deg);
|
||||
-ms-transform: rotate(150deg);
|
||||
transform: rotate(150deg);
|
||||
}
|
||||
|
||||
.sk-spinner-circle .sk-circle7 {
|
||||
-webkit-transform: rotate(180deg);
|
||||
-ms-transform: rotate(180deg);
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.sk-spinner-circle .sk-circle8 {
|
||||
-webkit-transform: rotate(210deg);
|
||||
-ms-transform: rotate(210deg);
|
||||
transform: rotate(210deg);
|
||||
}
|
||||
|
||||
.sk-spinner-circle .sk-circle9 {
|
||||
-webkit-transform: rotate(240deg);
|
||||
-ms-transform: rotate(240deg);
|
||||
transform: rotate(240deg);
|
||||
}
|
||||
|
||||
.sk-spinner-circle .sk-circle10 {
|
||||
-webkit-transform: rotate(270deg);
|
||||
-ms-transform: rotate(270deg);
|
||||
transform: rotate(270deg);
|
||||
}
|
||||
|
||||
.sk-spinner-circle .sk-circle11 {
|
||||
-webkit-transform: rotate(300deg);
|
||||
-ms-transform: rotate(300deg);
|
||||
transform: rotate(300deg);
|
||||
}
|
||||
|
||||
.sk-spinner-circle .sk-circle12 {
|
||||
-webkit-transform: rotate(330deg);
|
||||
-ms-transform: rotate(330deg);
|
||||
transform: rotate(330deg);
|
||||
}
|
||||
|
||||
.sk-spinner-circle .sk-circle2:before {
|
||||
-webkit-animation-delay: -1.1s;
|
||||
animation-delay: -1.1s;
|
||||
}
|
||||
|
||||
.sk-spinner-circle .sk-circle3:before {
|
||||
-webkit-animation-delay: -1s;
|
||||
animation-delay: -1s;
|
||||
}
|
||||
|
||||
.sk-spinner-circle .sk-circle4:before {
|
||||
-webkit-animation-delay: -0.9s;
|
||||
animation-delay: -0.9s;
|
||||
}
|
||||
|
||||
.sk-spinner-circle .sk-circle5:before {
|
||||
-webkit-animation-delay: -0.8s;
|
||||
animation-delay: -0.8s;
|
||||
}
|
||||
|
||||
.sk-spinner-circle .sk-circle6:before {
|
||||
-webkit-animation-delay: -0.7s;
|
||||
animation-delay: -0.7s;
|
||||
}
|
||||
|
||||
.sk-spinner-circle .sk-circle7:before {
|
||||
-webkit-animation-delay: -0.6s;
|
||||
animation-delay: -0.6s;
|
||||
}
|
||||
|
||||
.sk-spinner-circle .sk-circle8:before {
|
||||
-webkit-animation-delay: -0.5s;
|
||||
animation-delay: -0.5s;
|
||||
}
|
||||
|
||||
.sk-spinner-circle .sk-circle9:before {
|
||||
-webkit-animation-delay: -0.4s;
|
||||
animation-delay: -0.4s;
|
||||
}
|
||||
|
||||
.sk-spinner-circle .sk-circle10:before {
|
||||
-webkit-animation-delay: -0.3s;
|
||||
animation-delay: -0.3s;
|
||||
}
|
||||
|
||||
.sk-spinner-circle .sk-circle11:before {
|
||||
-webkit-animation-delay: -0.2s;
|
||||
animation-delay: -0.2s;
|
||||
}
|
||||
|
||||
.sk-spinner-circle .sk-circle12:before {
|
||||
-webkit-animation-delay: -0.1s;
|
||||
animation-delay: -0.1s;
|
||||
}
|
||||
|
||||
@-webkit-keyframes sk-circleBounceDelay {
|
||||
0%, 80%, 100% {
|
||||
-webkit-transform: scale(0);
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
40% {
|
||||
-webkit-transform: scale(1);
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes sk-circleBounceDelay {
|
||||
0%, 80%, 100% {
|
||||
-webkit-transform: scale(0);
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
40% {
|
||||
-webkit-transform: scale(1);
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Usage:
|
||||
*
|
||||
* <div class="sk-spinner sk-spinner-cube-grid">
|
||||
* <div class="sk-cube"></div>
|
||||
* <div class="sk-cube"></div>
|
||||
* <div class="sk-cube"></div>
|
||||
* <div class="sk-cube"></div>
|
||||
* <div class="sk-cube"></div>
|
||||
* <div class="sk-cube"></div>
|
||||
* <div class="sk-cube"></div>
|
||||
* <div class="sk-cube"></div>
|
||||
* <div class="sk-cube"></div>
|
||||
* </div>
|
||||
*
|
||||
*/
|
||||
.sk-spinner-cube-grid {
|
||||
/*
|
||||
* Spinner positions
|
||||
* 1 2 3
|
||||
* 4 5 6
|
||||
* 7 8 9
|
||||
*/
|
||||
}
|
||||
|
||||
.sk-spinner-cube-grid.sk-spinner {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
margin: @spin-margin;
|
||||
}
|
||||
|
||||
.sk-spinner-cube-grid .sk-cube {
|
||||
width: 33%;
|
||||
height: 33%;
|
||||
background-color: @spin-color;
|
||||
float: left;
|
||||
-webkit-animation: sk-cubeGridScaleDelay 1.3s infinite ease-in-out;
|
||||
animation: sk-cubeGridScaleDelay 1.3s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.sk-spinner-cube-grid .sk-cube:nth-child(1) {
|
||||
-webkit-animation-delay: 0.2s;
|
||||
animation-delay: 0.2s;
|
||||
}
|
||||
|
||||
.sk-spinner-cube-grid .sk-cube:nth-child(2) {
|
||||
-webkit-animation-delay: 0.3s;
|
||||
animation-delay: 0.3s;
|
||||
}
|
||||
|
||||
.sk-spinner-cube-grid .sk-cube:nth-child(3) {
|
||||
-webkit-animation-delay: 0.4s;
|
||||
animation-delay: 0.4s;
|
||||
}
|
||||
|
||||
.sk-spinner-cube-grid .sk-cube:nth-child(4) {
|
||||
-webkit-animation-delay: 0.1s;
|
||||
animation-delay: 0.1s;
|
||||
}
|
||||
|
||||
.sk-spinner-cube-grid .sk-cube:nth-child(5) {
|
||||
-webkit-animation-delay: 0.2s;
|
||||
animation-delay: 0.2s;
|
||||
}
|
||||
|
||||
.sk-spinner-cube-grid .sk-cube:nth-child(6) {
|
||||
-webkit-animation-delay: 0.3s;
|
||||
animation-delay: 0.3s;
|
||||
}
|
||||
|
||||
.sk-spinner-cube-grid .sk-cube:nth-child(7) {
|
||||
-webkit-animation-delay: 0s;
|
||||
animation-delay: 0s;
|
||||
}
|
||||
|
||||
.sk-spinner-cube-grid .sk-cube:nth-child(8) {
|
||||
-webkit-animation-delay: 0.1s;
|
||||
animation-delay: 0.1s;
|
||||
}
|
||||
|
||||
.sk-spinner-cube-grid .sk-cube:nth-child(9) {
|
||||
-webkit-animation-delay: 0.2s;
|
||||
animation-delay: 0.2s;
|
||||
}
|
||||
|
||||
@-webkit-keyframes sk-cubeGridScaleDelay {
|
||||
0%, 70%, 100% {
|
||||
-webkit-transform: scale3D(1, 1, 1);
|
||||
transform: scale3D(1, 1, 1);
|
||||
}
|
||||
|
||||
35% {
|
||||
-webkit-transform: scale3D(0, 0, 1);
|
||||
transform: scale3D(0, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes sk-cubeGridScaleDelay {
|
||||
0%, 70%, 100% {
|
||||
-webkit-transform: scale3D(1, 1, 1);
|
||||
transform: scale3D(1, 1, 1);
|
||||
}
|
||||
|
||||
35% {
|
||||
-webkit-transform: scale3D(0, 0, 1);
|
||||
transform: scale3D(0, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Usage:
|
||||
*
|
||||
* <div class="sk-spinner sk-spinner-wordpress">
|
||||
* <span class="sk-inner-circle"></span>
|
||||
* </div>
|
||||
*
|
||||
*/
|
||||
.sk-spinner-wordpress.sk-spinner {
|
||||
background-color: @spin-color;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 30px;
|
||||
position: relative;
|
||||
margin: @spin-margin;
|
||||
-webkit-animation: sk-innerCircle 1s linear infinite;
|
||||
animation: sk-innerCircle 1s linear infinite;
|
||||
}
|
||||
|
||||
.sk-spinner-wordpress .sk-inner-circle {
|
||||
display: block;
|
||||
background-color: #fff;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
position: absolute;
|
||||
border-radius: 8px;
|
||||
top: 5px;
|
||||
left: 5px;
|
||||
}
|
||||
|
||||
@-webkit-keyframes sk-innerCircle {
|
||||
0% {
|
||||
-webkit-transform: rotate(0);
|
||||
transform: rotate(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes sk-innerCircle {
|
||||
0% {
|
||||
-webkit-transform: rotate(0);
|
||||
transform: rotate(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Usage:
|
||||
*
|
||||
* <div class="sk-spinner sk-spinner-fading-circle">
|
||||
* <div class="sk-circle1 sk-circle"></div>
|
||||
* <div class="sk-circle2 sk-circle"></div>
|
||||
* <div class="sk-circle3 sk-circle"></div>
|
||||
* <div class="sk-circle4 sk-circle"></div>
|
||||
* <div class="sk-circle5 sk-circle"></div>
|
||||
* <div class="sk-circle6 sk-circle"></div>
|
||||
* <div class="sk-circle7 sk-circle"></div>
|
||||
* <div class="sk-circle8 sk-circle"></div>
|
||||
* <div class="sk-circle9 sk-circle"></div>
|
||||
* <div class="sk-circle10 sk-circle"></div>
|
||||
* <div class="sk-circle11 sk-circle"></div>
|
||||
* <div class="sk-circle12 sk-circle"></div>
|
||||
* </div>
|
||||
*
|
||||
*/
|
||||
.sk-spinner-fading-circle.sk-spinner {
|
||||
margin: @spin-margin;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.sk-spinner-fading-circle .sk-circle {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.sk-spinner-fading-circle .sk-circle:before {
|
||||
content: '';
|
||||
display: block;
|
||||
margin: @spin-margin;
|
||||
width: 18%;
|
||||
height: 18%;
|
||||
background-color: @spin-color;
|
||||
border-radius: 100%;
|
||||
-webkit-animation: sk-circleFadeDelay 1.2s infinite ease-in-out;
|
||||
animation: sk-circleFadeDelay 1.2s infinite ease-in-out;
|
||||
/* Prevent first frame from flickering when animation starts */
|
||||
-webkit-animation-fill-mode: both;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
|
||||
.sk-spinner-fading-circle .sk-circle2 {
|
||||
-webkit-transform: rotate(30deg);
|
||||
-ms-transform: rotate(30deg);
|
||||
transform: rotate(30deg);
|
||||
}
|
||||
|
||||
.sk-spinner-fading-circle .sk-circle3 {
|
||||
-webkit-transform: rotate(60deg);
|
||||
-ms-transform: rotate(60deg);
|
||||
transform: rotate(60deg);
|
||||
}
|
||||
|
||||
.sk-spinner-fading-circle .sk-circle4 {
|
||||
-webkit-transform: rotate(90deg);
|
||||
-ms-transform: rotate(90deg);
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.sk-spinner-fading-circle .sk-circle5 {
|
||||
-webkit-transform: rotate(120deg);
|
||||
-ms-transform: rotate(120deg);
|
||||
transform: rotate(120deg);
|
||||
}
|
||||
|
||||
.sk-spinner-fading-circle .sk-circle6 {
|
||||
-webkit-transform: rotate(150deg);
|
||||
-ms-transform: rotate(150deg);
|
||||
transform: rotate(150deg);
|
||||
}
|
||||
|
||||
.sk-spinner-fading-circle .sk-circle7 {
|
||||
-webkit-transform: rotate(180deg);
|
||||
-ms-transform: rotate(180deg);
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.sk-spinner-fading-circle .sk-circle8 {
|
||||
-webkit-transform: rotate(210deg);
|
||||
-ms-transform: rotate(210deg);
|
||||
transform: rotate(210deg);
|
||||
}
|
||||
|
||||
.sk-spinner-fading-circle .sk-circle9 {
|
||||
-webkit-transform: rotate(240deg);
|
||||
-ms-transform: rotate(240deg);
|
||||
transform: rotate(240deg);
|
||||
}
|
||||
|
||||
.sk-spinner-fading-circle .sk-circle10 {
|
||||
-webkit-transform: rotate(270deg);
|
||||
-ms-transform: rotate(270deg);
|
||||
transform: rotate(270deg);
|
||||
}
|
||||
|
||||
.sk-spinner-fading-circle .sk-circle11 {
|
||||
-webkit-transform: rotate(300deg);
|
||||
-ms-transform: rotate(300deg);
|
||||
transform: rotate(300deg);
|
||||
}
|
||||
|
||||
.sk-spinner-fading-circle .sk-circle12 {
|
||||
-webkit-transform: rotate(330deg);
|
||||
-ms-transform: rotate(330deg);
|
||||
transform: rotate(330deg);
|
||||
}
|
||||
|
||||
.sk-spinner-fading-circle .sk-circle2:before {
|
||||
-webkit-animation-delay: -1.1s;
|
||||
animation-delay: -1.1s;
|
||||
}
|
||||
|
||||
.sk-spinner-fading-circle .sk-circle3:before {
|
||||
-webkit-animation-delay: -1s;
|
||||
animation-delay: -1s;
|
||||
}
|
||||
|
||||
.sk-spinner-fading-circle .sk-circle4:before {
|
||||
-webkit-animation-delay: -0.9s;
|
||||
animation-delay: -0.9s;
|
||||
}
|
||||
|
||||
.sk-spinner-fading-circle .sk-circle5:before {
|
||||
-webkit-animation-delay: -0.8s;
|
||||
animation-delay: -0.8s;
|
||||
}
|
||||
|
||||
.sk-spinner-fading-circle .sk-circle6:before {
|
||||
-webkit-animation-delay: -0.7s;
|
||||
animation-delay: -0.7s;
|
||||
}
|
||||
|
||||
.sk-spinner-fading-circle .sk-circle7:before {
|
||||
-webkit-animation-delay: -0.6s;
|
||||
animation-delay: -0.6s;
|
||||
}
|
||||
|
||||
.sk-spinner-fading-circle .sk-circle8:before {
|
||||
-webkit-animation-delay: -0.5s;
|
||||
animation-delay: -0.5s;
|
||||
}
|
||||
|
||||
.sk-spinner-fading-circle .sk-circle9:before {
|
||||
-webkit-animation-delay: -0.4s;
|
||||
animation-delay: -0.4s;
|
||||
}
|
||||
|
||||
.sk-spinner-fading-circle .sk-circle10:before {
|
||||
-webkit-animation-delay: -0.3s;
|
||||
animation-delay: -0.3s;
|
||||
}
|
||||
|
||||
.sk-spinner-fading-circle .sk-circle11:before {
|
||||
-webkit-animation-delay: -0.2s;
|
||||
animation-delay: -0.2s;
|
||||
}
|
||||
|
||||
.sk-spinner-fading-circle .sk-circle12:before {
|
||||
-webkit-animation-delay: -0.1s;
|
||||
animation-delay: -0.1s;
|
||||
}
|
||||
|
||||
@-webkit-keyframes sk-circleFadeDelay {
|
||||
0%, 39%, 100% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
40% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes sk-circleFadeDelay {
|
||||
0%, 39%, 100% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
40% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* INSPINIA - Responsive Admin Theme
|
||||
* version 2.6.2
|
||||
*
|
||||
*/
|
||||
// Variables, Mixins
|
||||
@import "../global/variables.less";
|
||||
@import "mixins.less";
|
||||
// INSPINIA Theme Elements
|
||||
@import "typography.less";
|
||||
@import "buttons.less";
|
||||
@import "badgets_labels.less";
|
||||
@import "elements.less";
|
||||
@import "sidebar.less";
|
||||
@import "base.less";
|
||||
@import "pages.less";
|
||||
@import "chat.less";
|
||||
@import "spinners.less";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-weight: 100;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 30px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
h3, h4, h5 {
|
||||
margin-top: 5px;
|
||||
font-weight: 600;
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
@import "~bootstrap/less/variables.less";
|
||||
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 943 B After Width: | Height: | Size: 943 B |
|
Before Width: | Height: | Size: 828 B After Width: | Height: | Size: 828 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 943 B After Width: | Height: | Size: 943 B |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 743 B After Width: | Height: | Size: 743 B |
|
After Width: | Height: | Size: 4.5 KiB |
@@ -1,147 +0,0 @@
|
||||
<template>
|
||||
|
||||
<div id="body">
|
||||
|
||||
<div>
|
||||
<SideNavigation/>
|
||||
<div id="page-wrapper" :class="{'show-drawer':$store.state.config.showDrawer}" @click="blankClick">
|
||||
|
||||
<div>
|
||||
|
||||
<div class="mb10">
|
||||
|
||||
<router-link to="/" v-if="$store.state.breadcrumbs && $store.state.breadcrumbs.length">
|
||||
<i class="fa fa-home f16"></i>
|
||||
</router-link>
|
||||
|
||||
<span v-for="b in $store.state.breadcrumbs">
|
||||
<span>/</span>
|
||||
<router-link v-if="(b.name || b.path) && b.name !== $store.state.route.name" :to="b">
|
||||
{{b.displayDirect?b.title:$t(b.title)}}
|
||||
</router-link>
|
||||
<span v-else>
|
||||
{{b.displayDirect?b.title:$t(b.title)}}
|
||||
</span>
|
||||
|
||||
</span>
|
||||
|
||||
</div>
|
||||
<router-view></router-view>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<TopNavigation/>
|
||||
|
||||
<!--手机上不显示bottomNavigation,而采用弹出的形式-->
|
||||
<BottomNavigation/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SideNavigation from './layout/SideNavigation.vue'
|
||||
import TopNavigation from './layout/TopNavigation.vue'
|
||||
import BottomNavigation from './layout/BottomNavigation.vue'
|
||||
import enquire from 'enquire.js/dist/enquire'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
member: this.$store.state.member
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
config() {
|
||||
return this.$store.state.config
|
||||
}
|
||||
},
|
||||
components: {
|
||||
SideNavigation,
|
||||
TopNavigation,
|
||||
BottomNavigation
|
||||
},
|
||||
methods: {
|
||||
blankClick() {
|
||||
if (this.config.mobile) {
|
||||
if (this.config.showDrawer) {
|
||||
this.$store.state.config.showDrawer = false
|
||||
}
|
||||
}
|
||||
},
|
||||
listenResponsiveEvent() {
|
||||
let that = this
|
||||
enquire.register('(max-width: 768px)', {
|
||||
match: function () {
|
||||
that.$store.state.config.showDrawer = false
|
||||
that.$store.state.config.mobile = true
|
||||
},
|
||||
unmatch: function () {
|
||||
that.$store.state.config.showDrawer = true
|
||||
that.$store.state.config.mobile = false
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
},
|
||||
mounted() {
|
||||
let that = this
|
||||
this.$store.state.environment = 'backyard'
|
||||
this.listenResponsiveEvent()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" rel="stylesheet/less">
|
||||
@import "../assets/css/global/variables";
|
||||
|
||||
#page-wrapper {
|
||||
|
||||
position: fixed;
|
||||
left: @sidebar-width;
|
||||
top: @top-navigation-height;
|
||||
right: 0;
|
||||
bottom: @power-footer-height;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
z-index: 10;
|
||||
|
||||
padding: 10px;
|
||||
|
||||
-webkit-transition: all 0.4s;
|
||||
-moz-transition: all 0.4s;
|
||||
-o-transition: all 0.4s;
|
||||
transition: all 0.4s;
|
||||
|
||||
background-color: #f3f3f4;
|
||||
|
||||
//大屏幕
|
||||
@media (min-width: @screen-sm-min) {
|
||||
left: @sidebar-width;
|
||||
}
|
||||
//小屏幕
|
||||
@media (max-width: @screen-xs-max) {
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
&.show-drawer {
|
||||
//大屏幕
|
||||
@media (min-width: @screen-sm-min) {
|
||||
left: @sidebar-width;
|
||||
}
|
||||
|
||||
//小屏幕
|
||||
@media (max-width: @screen-xs-max) {
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,516 +0,0 @@
|
||||
<template>
|
||||
<div class="dashboard-index">
|
||||
|
||||
<div class="row mt20">
|
||||
<div class="col-lg-3 col-md-6 col-sm-12">
|
||||
<div class="text-block">
|
||||
<div class="upper">
|
||||
<div class="indicator">{{ $t('dashboard.totalInvokeNum') }}</div>
|
||||
<div class="amount">{{dashboard.totalInvokeNum}}</div>
|
||||
<div>
|
||||
<RatePanel :name="$t('dashboard.weekRate')" :standardValue="standardWeekInvokeNum"
|
||||
:compareValue="compareWeekInvokeNum"/>
|
||||
<RatePanel :name="$t('dashboard.dayRate')" :standardValue="standardDayInvokeNum"
|
||||
:compareValue="compareDayInvokeNum"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="lower">
|
||||
{{ $t('dashboard.yesterdayInvoke') }}:{{dashboard.invokeNum}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3 col-md-6 col-sm-12">
|
||||
<div class="text-block">
|
||||
<div class="upper">
|
||||
<div class="indicator">{{ $t('dashboard.totalUV') }}</div>
|
||||
<div class="amount">{{dashboard.totalUv}}</div>
|
||||
<div>
|
||||
<RatePanel :name="$t('dashboard.weekRate')" :standardValue="standardWeekUv"
|
||||
:compareValue="compareWeekUv"/>
|
||||
<RatePanel :name="$t('dashboard.dayRate')" :standardValue="standardDayUv" :compareValue="compareDayUv"/>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="lower">
|
||||
{{ $t('dashboard.yesterdayUV') }}:{{dashboard.uv}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3 col-md-6 col-sm-12">
|
||||
<div class="text-block">
|
||||
<div class="upper">
|
||||
<div class="indicator">{{ $t('dashboard.totalMatterNum') }}</div>
|
||||
<div class="amount">{{dashboard.totalMatterNum}}</div>
|
||||
<div>
|
||||
<RatePanel :name="$t('dashboard.weekRate')" :standardValue="standardWeekMatterNum"
|
||||
:compareValue="compareWeekMatterNum"/>
|
||||
<RatePanel :name="$t('dashboard.dayRate')" :standardValue="standardDayMatterNum"
|
||||
:compareValue="compareDayMatterNum"/>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="lower">
|
||||
{{ $t('dashboard.yesterdayMatterNum') }}:{{dashboard.matterNum}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3 col-md-6 col-sm-12">
|
||||
<div class="text-block">
|
||||
<div class="upper">
|
||||
<div class="indicator">{{ $t('dashboard.totalFileSize') }}</div>
|
||||
<div class="amount">{{dashboard.totalFileSize | humanFileSize}}</div>
|
||||
<div>
|
||||
<RatePanel :name="$t('dashboard.weekRate')" :standardValue="standardWeekSize"
|
||||
:compareValue="compareWeekSize"/>
|
||||
<RatePanel :name="$t('dashboard.dayRate')" :standardValue="standardDaySize"
|
||||
:compareValue="compareDaySize"/>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="lower">
|
||||
{{ $t('dashboard.yesterdayMatterSize') }}:{{dashboard.fileSize | humanFileSize}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-12 col-md-12 col-sm-12">
|
||||
<div class="figure-block">
|
||||
<div class="title">
|
||||
{{ $t('dashboard.recentDayInvokeUV',[days]) }}
|
||||
</div>
|
||||
<figure>
|
||||
<ECharts
|
||||
ref="invokeListChart"
|
||||
theme="ovilia-green"
|
||||
:autoResize="true"
|
||||
:initOptions="initOptions"
|
||||
:options="invokeListOption"/>
|
||||
</figure>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6 col-md-6 col-sm-12">
|
||||
<div class="figure-block">
|
||||
<div class="title">
|
||||
{{ $t('dashboard.downloadMatterTop10') }}
|
||||
</div>
|
||||
<div class="list-rank">
|
||||
<ul>
|
||||
<li v-for="(matter,index) in matterPager.data">
|
||||
<span class="rank" :class="{top3:index<3}">{{index+1}}</span>
|
||||
<router-link class="name" :to="'/matter/detail/'+matter.uuid">{{matter.name}}</router-link>
|
||||
<span class="info">{{matter.times}}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6 col-md-6 col-sm-12">
|
||||
<div class="figure-block">
|
||||
<div class="title">
|
||||
{{ $t('dashboard.activeIpTop10') }}
|
||||
</div>
|
||||
<div class="list-rank">
|
||||
<ul>
|
||||
<li v-for="(item,index) in activeIpTop10">
|
||||
<span class="rank" :class="{top3:index<3}">{{index+1}}</span>
|
||||
<span class="name" :to="'/'">{{item.ip}}</span>
|
||||
<span class="info">{{item.times}}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import ECharts from 'vue-echarts/components/ECharts'
|
||||
|
||||
import 'echarts/lib/chart/bar'
|
||||
import 'echarts/lib/chart/line'
|
||||
import 'echarts/lib/chart/pie'
|
||||
import 'echarts/lib/chart/map'
|
||||
import 'echarts/lib/chart/radar'
|
||||
import 'echarts/lib/chart/scatter'
|
||||
import 'echarts/lib/chart/effectScatter'
|
||||
import 'echarts/lib/component/tooltip'
|
||||
import 'echarts/lib/component/polar'
|
||||
import 'echarts/lib/component/geo'
|
||||
import 'echarts/lib/component/legend'
|
||||
import 'echarts/lib/component/title'
|
||||
import 'echarts/lib/component/visualMap'
|
||||
import 'echarts/lib/component/dataset'
|
||||
import 'echarts/map/js/world'
|
||||
import 'zrender/lib/svg/svg'
|
||||
|
||||
|
||||
import theme from "./theme"
|
||||
|
||||
import Dashboard from "../../common/model/dashboard/Dashboard";
|
||||
import Pager from "../../common/model/base/Pager";
|
||||
import {SortDirection} from "../../common/model/base/SortDirection";
|
||||
import {simpleDate} from "../../common/filter/time";
|
||||
import RatePanel from "./widget/RatePanel"
|
||||
import Matter from "../../common/model/matter/Matter";
|
||||
|
||||
//自定义主题
|
||||
ECharts.registerTheme('ovilia-green', theme)
|
||||
|
||||
export default {
|
||||
|
||||
data: function () {
|
||||
return {
|
||||
days: 15,
|
||||
//用来存放日期的,辅助x轴的生成
|
||||
dateStrings: [],
|
||||
//昨天的统计情况
|
||||
dashboard: new Dashboard(),
|
||||
//调用量周环比
|
||||
standardWeekInvokeNum: 0,
|
||||
compareWeekInvokeNum: 0,
|
||||
//调用量日环比
|
||||
standardDayInvokeNum: 0,
|
||||
compareDayInvokeNum: 0,
|
||||
//UV周环比
|
||||
standardWeekUv: 0,
|
||||
compareWeekUv: 0,
|
||||
//UV日环比
|
||||
standardDayUv: 0,
|
||||
compareDayUv: 0,
|
||||
//文件总数周环比
|
||||
standardWeekMatterNum: 0,
|
||||
compareWeekMatterNum: 0,
|
||||
//文件总数日环比
|
||||
standardDayMatterNum: 0,
|
||||
compareDayMatterNum: 0,
|
||||
//文件大小周环比
|
||||
standardWeekSize: 0,
|
||||
compareWeekSize: 0,
|
||||
//文件大小日环比
|
||||
standardDaySize: 0,
|
||||
compareDaySize: 0,
|
||||
|
||||
pager: new Pager(Dashboard, 15),
|
||||
matterPager: new Pager(Matter, 10),
|
||||
activeIpTop10: [],
|
||||
//图标加载中的样式
|
||||
loadingOption: {
|
||||
text: this.$t("dashboard.loading"),
|
||||
color: '#006699',
|
||||
maskColor: 'rgba(255, 255, 255, 0.4)'
|
||||
},
|
||||
initOptions: {
|
||||
renderer: 'canvas'
|
||||
},
|
||||
invokeListOption: {
|
||||
tooltip: {},
|
||||
legend: {
|
||||
data: ['PV', 'UV']
|
||||
},
|
||||
xAxis: {
|
||||
name: this.$t("dashboard.date"),
|
||||
data: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
|
||||
},
|
||||
yAxis: {
|
||||
name: this.$t("dashboard.num")
|
||||
},
|
||||
series: [{
|
||||
name: 'PV',
|
||||
type: 'bar',
|
||||
data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
}, {
|
||||
name: 'UV',
|
||||
type: 'line',
|
||||
data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
}]
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
ECharts,
|
||||
RatePanel
|
||||
},
|
||||
methods: {
|
||||
updateDateStrings() {
|
||||
let that = this;
|
||||
//更新横坐标 从昨天开始倒推
|
||||
let arr = []
|
||||
for (let d = that.days; d >= 1; d--) {
|
||||
let thenDate = new Date((new Date()).getTime() - d * 24 * 60 * 60 * 1000)
|
||||
arr.push(simpleDate(thenDate))
|
||||
}
|
||||
that.dateStrings = arr
|
||||
},
|
||||
//获取15日调用分时数据
|
||||
refreshDashboardPager() {
|
||||
let that = this;
|
||||
|
||||
this.pager.setFilterValue("orderDt", SortDirection.DESC)
|
||||
|
||||
that.$refs.invokeListChart.showLoading()
|
||||
this.pager.httpFastPage(function (response) {
|
||||
|
||||
let list = that.pager.data
|
||||
|
||||
if (list.length > 0) {
|
||||
that.dashboard.render(list[list.length - 1])
|
||||
}
|
||||
|
||||
//数据转换成map,方便检索
|
||||
let map = {}
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
map[list[i].dt] = list[i]
|
||||
}
|
||||
|
||||
let invokeNumData = []
|
||||
let uvData = []
|
||||
let matterNumData = []
|
||||
let fileSizeData = []
|
||||
for (let i = 0; i < that.days; i++) {
|
||||
invokeNumData.push(0)
|
||||
uvData.push(0)
|
||||
matterNumData.push(0)
|
||||
fileSizeData.push(0)
|
||||
}
|
||||
|
||||
//按照日期对应。
|
||||
for (let i = 0; i < that.dateStrings.length; i++) {
|
||||
let item = map[that.dateStrings[i]];
|
||||
if (item) {
|
||||
invokeNumData[i] = item.invokeNum
|
||||
uvData[i] = item.uv
|
||||
matterNumData[i] = item.matterNum
|
||||
fileSizeData[i] = item.fileSize
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//同环比
|
||||
that.standardWeekInvokeNum = 0
|
||||
that.compareWeekInvokeNum = 0
|
||||
//调用量日环比
|
||||
that.standardDayInvokeNum = 0
|
||||
that.compareDayInvokeNum = 0
|
||||
//UV周环比
|
||||
that.standardWeekUv = 0
|
||||
that.compareWeekUv = 0
|
||||
//UV日环比
|
||||
that.standardDayUv = 0
|
||||
that.compareDayUv = 0
|
||||
|
||||
//文件总数周环比
|
||||
that.standardWeekMatterNum = 0
|
||||
that.compareWeekMatterNum = 0
|
||||
//文件总数日环比
|
||||
that.standardDayMatterNum = 0
|
||||
that.compareDayMatterNum = 0
|
||||
//文件大小周环比
|
||||
that.standardWeekSize = 0
|
||||
that.compareWeekSize = 0
|
||||
//文件大小日环比
|
||||
that.standardDaySize = 0
|
||||
that.compareDaySize = 0
|
||||
|
||||
for (let i = 0; i < that.days; i++) {
|
||||
if (i >= 1 && i <= 7) {
|
||||
that.standardWeekInvokeNum += invokeNumData[i]
|
||||
that.standardWeekUv += uvData[i]
|
||||
that.standardWeekMatterNum += matterNumData[i]
|
||||
that.standardWeekSize += fileSizeData[i]
|
||||
|
||||
} else if (i >= 8 && i <= 14) {
|
||||
that.compareWeekInvokeNum += invokeNumData[i]
|
||||
that.compareWeekUv += uvData[i]
|
||||
that.compareWeekMatterNum += matterNumData[i]
|
||||
that.compareWeekSize += fileSizeData[i]
|
||||
}
|
||||
if (i === 13) {
|
||||
that.standardDayInvokeNum = invokeNumData[i]
|
||||
that.standardDayUv = uvData[i]
|
||||
that.standardDayMatterNum = matterNumData[i]
|
||||
that.standardDaySize = fileSizeData[i]
|
||||
|
||||
}
|
||||
if (i === 14) {
|
||||
that.compareDayInvokeNum = invokeNumData[i]
|
||||
that.compareDayUv = uvData[i]
|
||||
that.compareDayMatterNum = matterNumData[i]
|
||||
that.compareDaySize = fileSizeData[i]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
that.invokeListOption.xAxis.data = that.dateStrings.map((k) => k.substr(5))
|
||||
that.invokeListOption.series[0].data = invokeNumData
|
||||
that.invokeListOption.series[1].data = uvData
|
||||
|
||||
|
||||
that.$refs.invokeListChart.hideLoading()
|
||||
}, function () {
|
||||
|
||||
that.$refs.invokeListChart.hideLoading()
|
||||
})
|
||||
|
||||
},
|
||||
//获取下载前10的文件
|
||||
refreshMatterPager() {
|
||||
let that = this;
|
||||
that.matterPager.setFilterValue("orderTimes", SortDirection.DESC)
|
||||
that.matterPager.httpFastPage()
|
||||
},
|
||||
refreshActiveIpTop10() {
|
||||
let that = this
|
||||
that.dashboard.httpActiveIpTop10(function (response) {
|
||||
that.activeIpTop10 = response.data.data
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
let that = this;
|
||||
this.updateDateStrings()
|
||||
this.refreshDashboardPager()
|
||||
this.refreshMatterPager()
|
||||
this.refreshActiveIpTop10()
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" rel="stylesheet/less">
|
||||
@import "../../assets/css/global/variables";
|
||||
|
||||
.dashboard-index {
|
||||
|
||||
figure {
|
||||
.echarts {
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
}
|
||||
}
|
||||
|
||||
.text-block {
|
||||
background-color: white;
|
||||
box-shadow: 0 0 5px rgba(0, 0, 0, .2);
|
||||
border-radius: 5px;
|
||||
padding: 20px 15px 10px 15px;
|
||||
margin-bottom: 30px;
|
||||
|
||||
.upper {
|
||||
|
||||
.indicator {
|
||||
color: rgba(0, 0, 0, .45);
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
height: 22px;
|
||||
}
|
||||
|
||||
.amount {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
word-break: break-all;
|
||||
white-space: nowrap;
|
||||
color: rgba(0, 0, 0, .85);
|
||||
margin-top: 4px;
|
||||
margin-bottom: 20px;
|
||||
font-size: 30px;
|
||||
line-height: 38px;
|
||||
height: 38px;
|
||||
|
||||
}
|
||||
|
||||
.rate {
|
||||
margin-right: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.lower {
|
||||
margin-top: 10px;
|
||||
padding-top: 10px;
|
||||
border-top: 1px solid #eee;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.figure-block {
|
||||
background-color: white;
|
||||
box-shadow: 0 0 5px rgba(0, 0, 0, .2);
|
||||
border-radius: 5px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.title {
|
||||
font-size: 18px;
|
||||
padding: 15px 20px;
|
||||
color: black;
|
||||
margin-bottom: 10px;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.list-rank {
|
||||
padding: 0 20px 10px 20px;
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
|
||||
li {
|
||||
zoom: 1;
|
||||
margin-top: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.rank {
|
||||
border-radius: 20px;
|
||||
display: inline-block;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
margin-right: 16px;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
width: 20px;
|
||||
text-align: center;
|
||||
margin-top: 1.5px;
|
||||
|
||||
background-color: #f5f5f5;
|
||||
|
||||
&.top3 {
|
||||
background-color: #314659;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.name {
|
||||
|
||||
color: rgba(0, 0, 0, .65);
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
flex: 1 1;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
margin-right: 8px;
|
||||
|
||||
&:hover {
|
||||
color: @brand-primary;
|
||||
}
|
||||
}
|
||||
|
||||
.info {
|
||||
color: rgba(0, 0, 0, .65);
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,79 +0,0 @@
|
||||
<template>
|
||||
<span class="widget-rate-panel">
|
||||
<span class="name">{{name}}</span>
|
||||
|
||||
<span class="infinite" v-if="infinite">∞</span>
|
||||
<span class="no-data" v-else-if="noData"> - </span>
|
||||
<span v-else>{{value>0?'+':''}}{{value}}%</span>
|
||||
|
||||
<i class="fa fa-arrow-down text-success" v-if="!noData && value<0"></i>
|
||||
<i class="fa fa-arrow-up text-danger" v-if="!noData && (infinite || value>=0)"></i>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
data: function () {
|
||||
return {}
|
||||
},
|
||||
computed: {
|
||||
noData() {
|
||||
return this.standardValue === 0 && this.compareValue === 0
|
||||
},
|
||||
infinite() {
|
||||
return this.standardValue === 0 && this.compareValue > 0
|
||||
},
|
||||
value() {
|
||||
if (this.standardValue === 0) {
|
||||
if (this.compareValue === 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return 100;
|
||||
}
|
||||
} else {
|
||||
let v1 = this.compareValue - this.standardValue
|
||||
let v2 = v1 / this.standardValue
|
||||
return (v2 * 100).toFixed(0)
|
||||
}
|
||||
}
|
||||
},
|
||||
props: {
|
||||
name: {
|
||||
type: String,
|
||||
required: false,
|
||||
'default': ""
|
||||
},
|
||||
standardValue: {
|
||||
type: Number,
|
||||
required: true,
|
||||
'default': 0
|
||||
},
|
||||
compareValue: {
|
||||
type: Number,
|
||||
required: true,
|
||||
'default': 0
|
||||
}
|
||||
},
|
||||
components: {},
|
||||
methods: {},
|
||||
mounted() {
|
||||
let that = this;
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" rel="stylesheet/less">
|
||||
@import "../../../assets/css/global/variables";
|
||||
|
||||
.widget-rate-panel {
|
||||
margin-right: 5px;
|
||||
.infinite {
|
||||
|
||||
}
|
||||
.no-data {
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
@@ -1,167 +0,0 @@
|
||||
<template>
|
||||
<div class="widget-image-cache-list animated fadeIn">
|
||||
<div class="row">
|
||||
<div class="col-md-12 text-right pb10">
|
||||
<button class="btn btn-primary btn-sm mr5" v-if="selectedImageCaches.length" @click.stop.prevent="deleteBatch">
|
||||
<i class="fa fa-trash"></i>
|
||||
{{ $t('delete') }}
|
||||
</button>
|
||||
<button class="btn btn-primary btn-sm mr5" v-if="selectedImageCaches.length !== pager.data.length"
|
||||
@click.stop.prevent="checkAll">
|
||||
<i class="fa fa-check-square"></i>
|
||||
{{ $t('selectAll') }}
|
||||
</button>
|
||||
<button class="btn btn-primary btn-sm mr5"
|
||||
v-if="pager.data.length && selectedImageCaches.length === pager.data.length"
|
||||
@click.stop.prevent="checkNone">
|
||||
<i class="fa fa-square-o"></i>
|
||||
{{ $t('cancel') }}
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-md-12" v-for="(imageCache,index) in pager.data">
|
||||
<ImageCachePanel
|
||||
:imageCache="imageCache"
|
||||
@deleteSuccess="refresh"
|
||||
@checkImageCache="checkImageCache"
|
||||
@previewImageCache="previewImageCache"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12 mt20">
|
||||
<NbPager :pager="pager" :callback="refresh"></NbPager>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NbFilter from '../../../../common/widget/filter/NbFilter.vue'
|
||||
import NbPager from '../../../../common/widget/NbPager.vue'
|
||||
import Pager from '../../../../common/model/base/Pager'
|
||||
import ImageCache from "../../../../common/model/image/cache/ImageCache";
|
||||
import ImageCachePanel from "./ImageCachePanel"
|
||||
import {MessageBox, Message} from "element-ui"
|
||||
|
||||
export default {
|
||||
|
||||
data() {
|
||||
return {
|
||||
pager: new Pager(ImageCache, Pager.MAX_PAGE_SIZE),
|
||||
user: this.$store.state.user,
|
||||
selectedImageCaches: []
|
||||
}
|
||||
},
|
||||
props: {
|
||||
initFilter: {
|
||||
type: Object,
|
||||
required: false
|
||||
}
|
||||
},
|
||||
components: {
|
||||
NbFilter,
|
||||
NbPager,
|
||||
ImageCachePanel
|
||||
},
|
||||
methods: {
|
||||
search() {
|
||||
this.pager.page = 0
|
||||
this.refresh()
|
||||
},
|
||||
refresh() {
|
||||
|
||||
if (this.initFilter) {
|
||||
for (let key in this.initFilter) {
|
||||
if (this.initFilter.hasOwnProperty(key)) {
|
||||
this.pager.setFilterValue(key, this.initFilter[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.pager.httpFastPage()
|
||||
},
|
||||
checkImageCache(imageCache) {
|
||||
|
||||
let that = this
|
||||
//统计所有的勾选
|
||||
this.selectedImageCaches.splice(0, this.selectedImageCaches.length)
|
||||
this.pager.data.forEach(function (imageCache, index) {
|
||||
if (imageCache.check) {
|
||||
that.selectedImageCaches.push(imageCache)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
},
|
||||
//全选
|
||||
checkAll() {
|
||||
this.pager.data.forEach(function (i, index) {
|
||||
i.check = true
|
||||
})
|
||||
this.checkImageCache()
|
||||
},
|
||||
//取消全选
|
||||
checkNone() {
|
||||
this.pager.data.forEach(function (i, index) {
|
||||
i.check = false
|
||||
})
|
||||
|
||||
this.checkImageCache()
|
||||
},
|
||||
previewImageCache(imageCache) {
|
||||
|
||||
let that = this;
|
||||
|
||||
//从matter开始预览图片
|
||||
let imageArray = []
|
||||
let startIndex = -1;
|
||||
this.pager.data.forEach(function (item, index) {
|
||||
imageArray.push(item.getResizeUrl())
|
||||
if (item.uuid === imageCache.uuid) {
|
||||
startIndex = imageArray.length - 1
|
||||
}
|
||||
})
|
||||
|
||||
that.$photoSwipePlugin.showPhotos(imageArray, startIndex)
|
||||
|
||||
},
|
||||
deleteBatch() {
|
||||
let that = this
|
||||
MessageBox.confirm(that.$t("actionCanNotRevertConfirm"), that.$t("prompt"), {
|
||||
confirmButtonText: that.$t("confirm"),
|
||||
cancelButtonText: that.$t("cancel"),
|
||||
type: 'warning',
|
||||
callback: function (action, instance) {
|
||||
if (action === 'confirm') {
|
||||
let uuids = ""
|
||||
that.selectedImageCaches.forEach(function (item, index) {
|
||||
if (index === 0) {
|
||||
uuids = item.uuid
|
||||
} else {
|
||||
uuids = uuids + "," + item.uuid
|
||||
}
|
||||
})
|
||||
let imageCache = new ImageCache()
|
||||
imageCache.httpDeleteBatch(uuids, function (response) {
|
||||
Message.success(that.$t("operationSuccess"))
|
||||
that.refresh()
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.pager.enableHistory()
|
||||
this.refresh()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" rel="stylesheet/less">
|
||||
.widget-image-cache-list {
|
||||
|
||||
}
|
||||
</style>
|
||||
@@ -1,273 +0,0 @@
|
||||
<template>
|
||||
<div class="widget-image-cache-panel">
|
||||
|
||||
<div @click.stop.prevent="clickRow">
|
||||
|
||||
<div class="media">
|
||||
|
||||
<div class="pull-left">
|
||||
<div class="left-part">
|
||||
<span class="basic-span">
|
||||
<NbCheckbox v-model="imageCache.check"/>
|
||||
</span>
|
||||
<span class="basic-span">
|
||||
<img class="image-cache-icon" :src="handleImageUrl(imageCache.getOriginUrl(),false,100,100)"/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--在大屏下的操作栏-->
|
||||
<div class="pull-right hidden-sm hidden-xs">
|
||||
<div class="right-part" v-if="imageCache.uuid">
|
||||
|
||||
<span class="image-cache-operation">
|
||||
<i class="fa fa-trash btn-action text-danger" :title="$t('delete')" @click.stop.prevent="deleteImageCache"></i>
|
||||
</span>
|
||||
<span class="image-cache-size">
|
||||
{{imageCache.size | humanFileSize}}
|
||||
</span>
|
||||
|
||||
<span class="image-cache-date">
|
||||
{{imageCache.updateTime | simpleDateHourMinute}}
|
||||
</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--在小屏幕下的操作栏-->
|
||||
<div class="pull-right hidden-lg hidden-md">
|
||||
<span class="more-btn" @click.stop.prevent="showMore = !showMore">
|
||||
<i class="fa fa-ellipsis-h btn-action" :title="$t('showMore')"></i>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="media-body">
|
||||
|
||||
<div class="middle-part">
|
||||
|
||||
<span class="image-cache-name">
|
||||
{{imageCache.name}}
|
||||
</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<NbExpanding>
|
||||
<div class="hidden-lg hidden-md more-panel" v-if="showMore">
|
||||
<div class="cell-btn" style="border: none">
|
||||
<span>
|
||||
{{imageCache.updateTime | simpleDateHourMinute}}
|
||||
</span>
|
||||
|
||||
<span v-if="!imageCache.dir">
|
||||
{{imageCache.size | humanFileSize}}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="cell-btn text-danger" :title="$t('delete')" @click.stop.prevent="deleteImageCache">
|
||||
<i class="fa fa-trash"></i>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</NbExpanding>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
<script>
|
||||
import ImageCache from '../../../../common/model/image/cache/ImageCache'
|
||||
import NbCheckbox from '../../../../common/widget/NbCheckbox'
|
||||
import NbExpanding from '../../../../common/widget/NbExpanding'
|
||||
import {Message, MessageBox} from 'element-ui'
|
||||
import {handleImageUrl} from "../../../../common/util/ImageUtil";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
//正在向服务器提交rename的请求
|
||||
renamingLoading: false,
|
||||
showMore: false
|
||||
}
|
||||
},
|
||||
components: {
|
||||
NbExpanding,
|
||||
NbCheckbox
|
||||
},
|
||||
props: {
|
||||
imageCache: {
|
||||
type: ImageCache,
|
||||
required: true
|
||||
}
|
||||
|
||||
},
|
||||
watch: {
|
||||
'imageCache.check'(newVal, oldVal) {
|
||||
this.$emit('checkImageCache', this.imageCache)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleImageUrl,
|
||||
clickRow() {
|
||||
let that = this
|
||||
this.$emit('previewImageCache', this.imageCache)
|
||||
},
|
||||
deleteImageCache() {
|
||||
let that = this
|
||||
MessageBox.confirm(that.$t("actionCanNotRevertConfirm"), that.$t("prompt"), {
|
||||
confirmButtonText: that.$t("confirm"),
|
||||
cancelButtonText: that.$t("cancel"),
|
||||
type: 'warning',
|
||||
callback: function (action, instance) {
|
||||
if (action === 'confirm') {
|
||||
that.imageCache.httpDelete(function (response) {
|
||||
Message.success(that.$t("operationSuccess"))
|
||||
that.$emit('deleteSuccess', that.imageCache)
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
finishCreateDirectory() {
|
||||
let that = this
|
||||
that.imageCache.httpCreateDirectory(function () {
|
||||
that.director.createMode = false
|
||||
that.editMode = false
|
||||
|
||||
that.imageCache.render(new ImageCache())
|
||||
|
||||
that.$emit('createDirectorySuccess', that.imageCache)
|
||||
|
||||
}, function (errorMessage) {
|
||||
that.director.createMode = false
|
||||
that.editMode = false
|
||||
Message.error(errorMessage)
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
},
|
||||
mounted() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style lang="less" rel="stylesheet/less">
|
||||
|
||||
@import "../../../../assets/css/global/variables";
|
||||
|
||||
@base-height: 48px;
|
||||
@inner-cell-height: 36px;
|
||||
|
||||
.basic-span {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
line-height: @base-height;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.widget-image-cache-panel {
|
||||
|
||||
border-top: 1px solid #eee;
|
||||
background-color: white;
|
||||
|
||||
.media {
|
||||
> .pull-left {
|
||||
padding-right: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.image-cache-icon {
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
.left-part {
|
||||
margin-left: 10px;
|
||||
}
|
||||
.middle-part {
|
||||
|
||||
height: @base-height;
|
||||
overflow: hidden;
|
||||
|
||||
.image-cache-name-edit {
|
||||
.basic-span;
|
||||
|
||||
width: 90%;
|
||||
input {
|
||||
width: 100%;
|
||||
height: 26px;
|
||||
display: inline-block;
|
||||
padding: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
.image-cache-name {
|
||||
.basic-span;
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.right-part {
|
||||
|
||||
.image-cache-operation {
|
||||
.basic-span;
|
||||
display: none;
|
||||
i {
|
||||
font-size: 16px;
|
||||
margin-right: 5px;
|
||||
|
||||
&:hover {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
.image-cache-size {
|
||||
.basic-span;
|
||||
display: inline-block;
|
||||
width: 80px;
|
||||
text-align: left;
|
||||
margin-left: 20px;
|
||||
}
|
||||
.image-cache-date {
|
||||
.basic-span;
|
||||
}
|
||||
}
|
||||
|
||||
.more-btn {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
line-height: @base-height;
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: aliceblue;
|
||||
cursor: pointer;
|
||||
|
||||
.image-cache-operation {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.more-panel {
|
||||
border-top: 1px solid #eee;
|
||||
padding-left: 35px;
|
||||
.info {
|
||||
}
|
||||
.cell-btn {
|
||||
border-top: 1px solid #eee;
|
||||
line-height: @inner-cell-height;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,481 +0,0 @@
|
||||
<template>
|
||||
<div class="backyard-install">
|
||||
|
||||
<el-tabs v-model="activeName" @tab-click="handleClick">
|
||||
<el-tab-pane :label=" $t('install.configMysql')" name="first">
|
||||
<div class="install-block">
|
||||
|
||||
<div class="row" v-validator="install.validatorSchema.mysqlHost.error">
|
||||
<label class="col-md-2 control-label mt5 compulsory">MySQL Host</label>
|
||||
<div class="col-md-10 validate">
|
||||
<input type="text" class="form-control" v-model="install.mysqlHost">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt10" v-validator="install.validatorSchema.mysqlPort.error">
|
||||
<label class="col-md-2 control-label mt5 compulsory">MySQL {{ $t('install.port') }}</label>
|
||||
<div class="col-md-10 validate">
|
||||
<input type="number" class="form-control" v-model="install.mysqlPort">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt10" v-validator="install.validatorSchema.mysqlSchema.error">
|
||||
<label class="col-md-2 control-label mt5 compulsory">MySQL {{ $t('install.schema') }}</label>
|
||||
<div class="col-md-10 validate">
|
||||
<input type="text" class="form-control" v-model="install.mysqlSchema">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt10" v-validator="install.validatorSchema.mysqlUsername.error">
|
||||
<label class="col-md-2 control-label mt5 compulsory">MySQL {{ $t('username') }}</label>
|
||||
<div class="col-md-10 validate">
|
||||
<input type="text" class="form-control" v-model="install.mysqlUsername">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt10" v-validator="install.validatorSchema.mysqlPassword.error">
|
||||
<label class="col-md-2 control-label mt5 compulsory">MySQL {{ $t('password') }}</label>
|
||||
<div class="col-md-10 validate">
|
||||
<input type="password" class="form-control" :value="install.mysqlPassword" @input="mysqlPasswordChange">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt20">
|
||||
<div class="col-md-12">
|
||||
<div class="alert alert-info">
|
||||
<div><i class="fa fa-bullhorn"></i> {{ $t('install.notice') }}</div>
|
||||
<ol class="pl30 m0">
|
||||
<li>{{ $t('install.mysqlNotice1') }}</li>
|
||||
<li>{{ $t('install.mysqlNotice2') }}</li>
|
||||
</ol>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12 text-right">
|
||||
<button class="btn btn-success btn-sm mr5" v-if="install.verified">
|
||||
<i class="fa fa-link"></i>
|
||||
{{ $t('install.mysqlConnectionPass') }}
|
||||
</button>
|
||||
<button class="btn btn-info btn-sm mr5" @click.stop.prevent="verify" v-if="!install.verified">
|
||||
<i class="fa fa-unlink"></i>
|
||||
{{ $t('install.testMysqlConnection') }}
|
||||
</button>
|
||||
|
||||
<button class="btn btn-primary btn-sm mr5" @click.stop.prevent="goTo('second')">
|
||||
<i class="fa fa-arrow-right"></i>
|
||||
{{ $t('install.nextStep') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('install.createTable')" name="second" :disabled="!install.verified">
|
||||
<div class="install-block">
|
||||
|
||||
<div class="mb15 border-bottom" v-for="(tableInfo,index) in install.tableInfoList">
|
||||
<div class="f16">
|
||||
{{tableInfo.name}}
|
||||
|
||||
<span class="label label-success" v-if="tableInfo.tableExist && !tableInfo.missingFields.length">
|
||||
{{ $t('install.installed') }}
|
||||
</span>
|
||||
<span class="label label-danger" v-if="tableInfo.tableExist && tableInfo.missingFields.length">
|
||||
{{ $t('install.installedButMissing') }}
|
||||
</span>
|
||||
<span class="label label-warning" v-if="!tableInfo.tableExist">
|
||||
{{ $t('install.toBeInstalled') }}
|
||||
</span>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="mt10">
|
||||
{{ $t('install.allFields') }}: <span class="label label-default mr5 inline-block mb10"
|
||||
v-for="field in tableInfo.allFields">{{field.DBName}}</span>
|
||||
</div>
|
||||
<div class="mt10" v-if="tableInfo.tableExist && tableInfo.missingFields.length">
|
||||
{{ $t('install.missingFields') }}: <span class="label label-default mr5 inline-block mb10"
|
||||
v-for="field in tableInfo.missingFields">{{field.DBName}}</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="row mt20">
|
||||
<div class="col-md-12">
|
||||
<div class="alert alert-info">
|
||||
<div><i class="fa fa-bullhorn"></i>{{ $t('install.tableNotice') }}</div>
|
||||
<ol class="pl30 m0">
|
||||
<li>{{ $t('install.tableNotice1') }}</li>
|
||||
<li>{{ $t('install.tableNotice2') }}</li>
|
||||
<li>{{ $t('install.tableNotice3') }}</li>
|
||||
<li>{{ $t('install.tableNotice4') }}</li>
|
||||
</ol>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12 text-right">
|
||||
|
||||
<button class="btn btn-info btn-sm mr5" v-if="!install.tableCreated()" @click.stop.prevent="createTable()">
|
||||
<i class="fa fa-gavel"></i>
|
||||
{{ $t('install.oneKeyCreate') }}
|
||||
</button>
|
||||
|
||||
<button class="btn btn-success btn-sm mr5" v-if="install.tableCreated()">
|
||||
<i class="fa fa-check"></i>
|
||||
{{ $t('install.oneKeyCreate') }}
|
||||
</button>
|
||||
|
||||
<button class="btn btn-primary btn-sm mr5" @click.stop.prevent="goTo('first')">
|
||||
<i class="fa fa-arrow-left"></i>
|
||||
{{ $t('install.preStep') }}
|
||||
</button>
|
||||
|
||||
<button class="btn btn-primary btn-sm mr5" @click.stop.prevent="goTo('third')">
|
||||
<i class="fa fa-arrow-right"></i>
|
||||
{{ $t('install.nextStep') }}
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('install.setAdministrator')" name="third" :disabled="!install.tableCreated()">
|
||||
<div class="install-block">
|
||||
|
||||
<div class="text-center" v-show="phase===-1">
|
||||
<i class="fa fa-spinner fa-spin fa-3x fa-fw"></i>
|
||||
</div>
|
||||
|
||||
<NbExpanding>
|
||||
<div v-show="phase===0">
|
||||
<div>
|
||||
{{ $t('install.detectAdministrator') }}
|
||||
</div>
|
||||
<div class="mv10 bold" v-for="admin in install.adminList">
|
||||
{{admin.username}}
|
||||
</div>
|
||||
<div>
|
||||
{{ $t('install.useOrCreateAdministrator') }}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="text-right">
|
||||
|
||||
<button class="btn btn-primary btn-sm mr5" @click.stop.prevent="phase = 1">
|
||||
<i class="fa fa-user-o"></i>
|
||||
{{ $t('install.validateAdministrator') }}
|
||||
</button>
|
||||
|
||||
<button class="btn btn-primary btn-sm mr5" @click.stop.prevent="phase = 2">
|
||||
<i class="fa fa-user-plus"></i>
|
||||
{{ $t('install.createAdministrator') }}
|
||||
</button>
|
||||
|
||||
<button class="btn btn-primary btn-sm mr5" @click.stop.prevent="goTo('second')">
|
||||
<i class="fa fa-arrow-left"></i>
|
||||
{{ $t('install.preStep') }}
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</NbExpanding>
|
||||
|
||||
|
||||
<NbExpanding>
|
||||
<div v-show="phase===1">
|
||||
|
||||
|
||||
<div class="bold f20 text-center">
|
||||
{{ $t('install.validateAdministrator') }}
|
||||
</div>
|
||||
|
||||
<div class="row mt10" v-validator="install.adminValidatorSchema.adminUsername.error">
|
||||
<label class="col-md-2 control-label mt5 compulsory">{{ $t('install.administratorUsername') }}</label>
|
||||
<div class="col-md-10 validate">
|
||||
<input type="text" class="form-control" v-model="install.adminUsername">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt10" v-validator="install.adminValidatorSchema.adminPassword.error">
|
||||
<label class="col-md-2 control-label mt5 compulsory">{{ $t('install.administratorPassword') }}</label>
|
||||
<div class="col-md-10 validate">
|
||||
<input type="password" class="form-control" v-model="install.adminPassword">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt10">
|
||||
<div class="col-md-12 text-right">
|
||||
|
||||
<button class="btn btn-primary btn-sm mr5" @click.stop.prevent="phase = 0">
|
||||
<i class="fa fa-arrow-left"></i>
|
||||
{{ $t('install.preStep') }}
|
||||
</button>
|
||||
|
||||
|
||||
<button class="btn btn-primary btn-sm mr5" @click.stop.prevent="validateAdmin()">
|
||||
<i class="fa fa-send"></i>
|
||||
{{ $t('submit') }}
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</NbExpanding>
|
||||
|
||||
|
||||
<NbExpanding>
|
||||
<div v-show="phase===2">
|
||||
|
||||
<div class="bold f20 text-center">
|
||||
{{ $t('install.createAdministrator') }}
|
||||
</div>
|
||||
|
||||
<div class="row mt10" v-validator="install.adminValidatorSchema.adminUsername.error">
|
||||
<label class="col-md-2 control-label mt5 compulsory">{{ $t('install.administratorUsername') }}</label>
|
||||
<div class="col-md-10 validate">
|
||||
<input type="text" class="form-control" v-model="install.adminUsername">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt10" v-validator="install.adminValidatorSchema.adminPassword.error">
|
||||
<label class="col-md-2 control-label mt5 compulsory">{{ $t('install.administratorPassword') }}</label>
|
||||
<div class="col-md-10 validate">
|
||||
<input type="password" class="form-control" v-model="install.adminPassword">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt10" v-validator="install.adminValidatorSchema.adminRepassword.error">
|
||||
<label class="col-md-2 control-label mt5 compulsory">{{ $t('install.administratorRePassword') }}</label>
|
||||
<div class="col-md-10 validate">
|
||||
<input type="password" class="form-control" v-model="install.adminRepassword">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row mt20">
|
||||
<div class="col-md-12">
|
||||
<div class="alert alert-info">
|
||||
<div><i class="fa fa-bullhorn"></i> {{ $t('install.notice') }}</div>
|
||||
<ol class="pl30 m0">
|
||||
<li>{{ $t('install.usernameRule') }}</li>
|
||||
</ol>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12 text-right">
|
||||
|
||||
<button class="btn btn-primary btn-sm mr5" @click.stop.prevent="preStep">
|
||||
<i class="fa fa-arrow-left"></i>
|
||||
{{ $t('install.preStep') }}
|
||||
</button>
|
||||
|
||||
<button class="btn btn-primary btn-sm mr5" @click.stop.prevent="createAdmin()">
|
||||
<i class="fa fa-send"></i>
|
||||
{{ $t('submit') }}
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</NbExpanding>
|
||||
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('finish') " name="forth" :disabled="!install.adminConfigured">
|
||||
<div class="install-block">
|
||||
|
||||
<div class="text-center">
|
||||
<img src="../../assets/img/success.svg" class="w50"/>
|
||||
</div>
|
||||
<div class="text-center mt10">
|
||||
{{ $t('install.congratulationInstall') }}
|
||||
</div>
|
||||
<div class="text-center mv20">
|
||||
<button class="btn btn-primary btn-sm mr5" @click.stop.prevent="finish">
|
||||
<i class="fa fa-home">
|
||||
{{ $t('install.enterHome') }}
|
||||
</i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
|
||||
</el-tabs>
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Install from "../../common/model/install/Install";
|
||||
import NbExpanding from "../../common/widget/NbExpanding";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
|
||||
//用来决定该如何验证管理员
|
||||
phase: -1,
|
||||
activeName: 'first',
|
||||
install: new Install()
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
mysqlUrl() {
|
||||
return this.install.mysqlUsername + ":" + this.install.mysqlPassword + "@tcp(" + this.install.mysqlHost + ":" + this.install.mysqlPort + ")/" + this.install.mysqlSchema + "?charset=utf8&parseTime=True&loc=Local"
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
mysqlUrl(newVal, oldVal) {
|
||||
this.install.verified = false
|
||||
}
|
||||
},
|
||||
components: {
|
||||
NbExpanding
|
||||
},
|
||||
methods: {
|
||||
mysqlPasswordChange(e) {
|
||||
//这么做主要是为了防止浏览器自动填充
|
||||
//只有在第一个tab的时候才能变化
|
||||
if (this.activeName === "first") {
|
||||
this.install.mysqlPassword = e.target.value
|
||||
}
|
||||
},
|
||||
verify() {
|
||||
let that = this;
|
||||
this.install.httpVerify(function () {
|
||||
that.install.verified = true
|
||||
that.$message.success(that.$t("install.mysqlConnectionPass"))
|
||||
})
|
||||
},
|
||||
fetchTableInfoList() {
|
||||
let that = this;
|
||||
this.install.httpTableInfoList()
|
||||
},
|
||||
|
||||
handleClick(tab, event) {
|
||||
|
||||
let paneName = tab.paneName;
|
||||
|
||||
},
|
||||
createTable() {
|
||||
//开始建表
|
||||
let that = this;
|
||||
this.install.httpCreateTable(function (response) {
|
||||
that.$message.success(that.$t("install.createTableSuccess"))
|
||||
|
||||
})
|
||||
},
|
||||
goTo(tabName) {
|
||||
let that = this
|
||||
if (tabName === "second") {
|
||||
|
||||
if (!this.install.verified) {
|
||||
this.$message.error(that.$t("install.validateMysqlFirst"))
|
||||
return
|
||||
}
|
||||
|
||||
this.fetchTableInfoList();
|
||||
|
||||
} else if (tabName === "third") {
|
||||
if (!this.install.tableCreated()) {
|
||||
this.$message.error(that.$t("install.crateTableFirst"))
|
||||
return
|
||||
}
|
||||
|
||||
//获取管理员列表
|
||||
this.adminList()
|
||||
|
||||
} else if (tabName === "forth") {
|
||||
if (!this.install.adminConfigured) {
|
||||
this.$message.error(that.$t("install.configAdminFirst"))
|
||||
return
|
||||
}
|
||||
}
|
||||
this.activeName = tabName
|
||||
},
|
||||
adminList() {
|
||||
//开始创建管理员
|
||||
let that = this;
|
||||
this.install.httpAdminList(function (response) {
|
||||
if (that.install.adminList.length) {
|
||||
that.phase = 0
|
||||
} else {
|
||||
that.phase = 2
|
||||
}
|
||||
})
|
||||
},
|
||||
createAdmin() {
|
||||
//开始创建管理员
|
||||
let that = this;
|
||||
this.install.httpCreateAdmin(function (response) {
|
||||
that.$message.success(that.$t("install.createAdminSuccess"))
|
||||
that.goTo("forth")
|
||||
})
|
||||
},
|
||||
validateAdmin() {
|
||||
//开始创建管理员
|
||||
let that = this;
|
||||
this.install.httpValidateAdmin(function (response) {
|
||||
that.$message.success(that.$t("install.validateAdminSuccess"))
|
||||
|
||||
that.goTo("forth")
|
||||
})
|
||||
},
|
||||
//创建管理员时的上一步
|
||||
preStep() {
|
||||
let that = this
|
||||
if (that.install.adminList.length) {
|
||||
that.phase = 0
|
||||
} else {
|
||||
that.goTo("second")
|
||||
}
|
||||
|
||||
},
|
||||
finish() {
|
||||
let that = this;
|
||||
|
||||
that.install.httpFinish(function (response) {
|
||||
|
||||
that.$store.state.installed = true
|
||||
that.$store.state.preference.httpFetch(function () {
|
||||
that.$router.push("/")
|
||||
})
|
||||
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
},
|
||||
mounted() {
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" rel="stylesheet/less">
|
||||
.backyard-install {
|
||||
|
||||
.install-block {
|
||||
background-color: white;
|
||||
box-shadow: 0 0 5px rgba(0, 0, 0, .2);
|
||||
border-radius: 5px;
|
||||
padding: 20px 15px 10px 15px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,108 +0,0 @@
|
||||
<template>
|
||||
<div class="bottom-navigation text-center">
|
||||
<span class="item">
|
||||
<span v-html="preference.copyright"></span>
|
||||
</span>
|
||||
<span class="item">
|
||||
<span v-html="preference.record"></span>
|
||||
</span>
|
||||
<span class="item">
|
||||
<a href="javascript:void(0)" @click.stop.prevent="changeLang">
|
||||
{{Vue.store.state.lang==='zh'?'English':'中文'}}
|
||||
</a>
|
||||
</span>
|
||||
<!-- 版本号:cn.eyeblue.tank:3.0.0 -->
|
||||
<!-- 开源不易,请不要移除掉这里的代码,蓝眼云盘谢谢您 ^_^ -->
|
||||
<span class="brand">
|
||||
Powered by <a target="_blank" href="https://github.com/eyebluecn/tank">
|
||||
<img class="w30" src="../../assets/img/logo.png"/>
|
||||
{{ Vue.i18n.t("eyeblueTank") }}</a>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Cookies from "js-cookie"
|
||||
import Vue from "vue"
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
Vue,
|
||||
preference: Vue.store.state.preference
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
changeLang() {
|
||||
if (Vue.store.state.lang === 'zh') {
|
||||
Vue.store.state.lang = 'en'
|
||||
} else {
|
||||
Vue.store.state.lang = 'zh'
|
||||
}
|
||||
|
||||
Cookies.set('_lang', Vue.store.state.lang);
|
||||
Vue.i18n.locale = Vue.store.state.lang
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" rel="stylesheet/less">
|
||||
@import "../../assets/css/global/variables";
|
||||
|
||||
.bottom-navigation {
|
||||
|
||||
//大屏幕
|
||||
@media (min-width: @screen-sm-min) {
|
||||
|
||||
position: fixed;
|
||||
height: @power-footer-height;
|
||||
line-height: @power-footer-height;
|
||||
background-color: white;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: @sidebar-width;
|
||||
padding: 0 20px;
|
||||
border-top: 1px solid #eee;
|
||||
.item {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
}
|
||||
//小屏幕
|
||||
@media (max-width: @screen-xs-max) {
|
||||
.item {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
&.show-drawer {
|
||||
//大屏幕
|
||||
@media (min-width: @screen-sm-min) {
|
||||
position: fixed;
|
||||
height: @power-footer-height;
|
||||
line-height: @power-footer-height;
|
||||
background-color: white;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: @sidebar-width;
|
||||
padding: 0 20px;
|
||||
border-top: 1px solid #eee;
|
||||
|
||||
.item {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
//小屏幕
|
||||
@media (max-width: @screen-xs-max) {
|
||||
.item {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.brand {
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,28 +0,0 @@
|
||||
<template>
|
||||
<div class="not-found">
|
||||
{{ $t('notFound') }}
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
computed: {},
|
||||
watch: {},
|
||||
components: {},
|
||||
methods: {}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="less" rel="stylesheet/less">
|
||||
|
||||
@import "../../assets/css/global/variables";
|
||||
|
||||
.not-found {
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,310 +0,0 @@
|
||||
<template>
|
||||
<nav ref="menuNav" class="side-navigation" :class="{'show-drawer':showDrawer}" @click.stop.prevent="eatClick">
|
||||
<div class="sidebar-collapse">
|
||||
|
||||
<div class="menu-header" @click="goToProfile" v-if="$store.state.installed">
|
||||
<div class="logo-area">
|
||||
<img alt="image" class="img-circle w80"
|
||||
:src="user.getAvatarUrl()"/>
|
||||
</div>
|
||||
<div class="text-area">
|
||||
<div class="nickname">
|
||||
{{user.role === 'GUEST' ? '请登录' : user.username}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul class="nav mt20" v-if="$store.state.installed">
|
||||
|
||||
<li v-if="user.role === UserRole.GUEST">
|
||||
<router-link to="/user/login">
|
||||
<i class="w14 fa fa-user-circle-o"></i>
|
||||
<span>{{ $t('login') }}</span>
|
||||
</router-link>
|
||||
</li>
|
||||
|
||||
<li v-if="user.role !== UserRole.GUEST">
|
||||
<router-link to="/" :class="{'custom-active':isCustomActive('/')}">
|
||||
<i class="w14 fa fa fa-th"></i>
|
||||
<span>{{ $t('layout.allFiles') }}</span>
|
||||
</router-link>
|
||||
</li>
|
||||
|
||||
|
||||
<li v-if="user.role !== UserRole.GUEST">
|
||||
<router-link to="/share/list" :class="{'custom-active':isCustomActive('/share/list')}">
|
||||
<i class="w14 fa fa fa-share-alt"></i>
|
||||
<span>{{ $t('layout.myShare') }}</span>
|
||||
</router-link>
|
||||
</li>
|
||||
|
||||
<li v-if="user.role === UserRole.ADMINISTRATOR">
|
||||
<router-link to="/preference" :class="{'custom-active':isCustomActive('/preference')}">
|
||||
<i class="w14 fa fa-cog"></i>
|
||||
<span>{{ $t('layout.setting') }}</span>
|
||||
</router-link>
|
||||
</li>
|
||||
|
||||
<li v-if="user.role === UserRole.ADMINISTRATOR">
|
||||
<router-link to="/dashboard/index" :class="{'custom-active':isCustomActive('/dashboard/index')}">
|
||||
<i class="w14 fa fa-dashboard"></i>
|
||||
<span>{{ $t('layout.dashboard') }}</span>
|
||||
</router-link>
|
||||
</li>
|
||||
|
||||
<li v-if="user.role === UserRole.ADMINISTRATOR">
|
||||
<router-link to="/user/list" :class="{'custom-active':isCustomActive('/user/list')}">
|
||||
<i class="w14 fa fa-user"></i>
|
||||
<span>{{ $t('layout.users') }}</span>
|
||||
</router-link>
|
||||
</li>
|
||||
|
||||
<li v-if="user.role !== UserRole.GUEST">
|
||||
<router-link to="/user/login" :class="{'custom-active':isCustomActive('/user/login')}">
|
||||
<i class="w14 fa fa-power-off"></i>
|
||||
<span>{{ $t('layout.logout') }}</span>
|
||||
</router-link>
|
||||
</li>
|
||||
|
||||
<li class="about-menu">
|
||||
<a href="javascript:void(0)" @click.stop.prevent="showAbout($createElement)">
|
||||
<i class="w14 fa fa-info-circle"></i>
|
||||
<span>{{ $t('layout.about') }}</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="menu-header" v-if="!$store.state.installed">
|
||||
<div class="logo-area">
|
||||
<img alt="image" class="img-circle w80" src="../../assets/img/logo.png"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul class="nav mt20" v-if="!$store.state.installed">
|
||||
<li>
|
||||
<router-link to="/install/index" :class="{'custom-active':isCustomActive('/install/index')}">
|
||||
<i class="w14 fa fa-cogs"></i>
|
||||
<span>{{ $t('layout.install') }}</span>
|
||||
</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</nav>
|
||||
</template>
|
||||
<script>
|
||||
import {MessageBox} from 'element-ui'
|
||||
import {UserRole} from "../../common/model/user/UserRole";
|
||||
import {handleImageUrl} from "../../common/util/ImageUtil";
|
||||
import BottomNavigation from "./BottomNavigation";
|
||||
|
||||
let logoPath = require("../../assets/img/logo.png")
|
||||
|
||||
export default {
|
||||
|
||||
data() {
|
||||
return {
|
||||
UserRole,
|
||||
user: this.$store.state.user,
|
||||
preference: this.$store.state.preference
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
showDrawer() {
|
||||
return this.$store.state.config.showDrawer;
|
||||
},
|
||||
mobile() {
|
||||
return this.$store.state.config.mobile;
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
components: {},
|
||||
methods: {
|
||||
handleImageUrl,
|
||||
isCustomActive(path) {
|
||||
return this.$route.path === path
|
||||
},
|
||||
goToProfile() {
|
||||
|
||||
if (this.user.role === UserRole.GUEST) {
|
||||
this.$router.push("/user/login");
|
||||
} else {
|
||||
this.$router.push("/user/detail/" + this.user.uuid);
|
||||
}
|
||||
|
||||
},
|
||||
eatClick() {
|
||||
|
||||
},
|
||||
showAbout(createElement) {
|
||||
|
||||
|
||||
let that = this
|
||||
|
||||
let targetMatterUuid = null
|
||||
let dom = createElement(BottomNavigation, {
|
||||
props: {
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
MessageBox({
|
||||
title: that.$t('layout.about'),
|
||||
message: dom,
|
||||
confirmButtonText: that.$t("confirm"),
|
||||
showCancelButton: false,
|
||||
callback: (action, instance) => {
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
},
|
||||
watch: {},
|
||||
mounted() {
|
||||
let that = this;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" rel="stylesheet/less">
|
||||
|
||||
@import "../../assets/css/global/variables";
|
||||
|
||||
@nav-bg: #3A3F51;
|
||||
@nav-text-color: white;
|
||||
@font-highlight-color: #ddd;
|
||||
@left-border-color: @brand-primary;
|
||||
|
||||
//手机屏幕
|
||||
@media (max-width: @screen-xs-max) {
|
||||
|
||||
}
|
||||
|
||||
//左侧菜单block.
|
||||
.side-navigation {
|
||||
|
||||
//overflow: auto;
|
||||
|
||||
-webkit-transition: all 0.4s;
|
||||
-moz-transition: all 0.4s;
|
||||
-o-transition: all 0.4s;
|
||||
transition: all 0.4s;
|
||||
|
||||
position: fixed;
|
||||
width: @sidebar-width;
|
||||
|
||||
left: -@sidebar-width;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
z-index: 1000;
|
||||
|
||||
background: darken(@nav-bg, 3%);
|
||||
|
||||
&.show-drawer {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.sidebar-collapse {
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
|
||||
.app-name-box {
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
display: table-cell;
|
||||
width: @sidebar-width;
|
||||
background-color: @brand-primary;
|
||||
height: @top-navigation-height;
|
||||
|
||||
a {
|
||||
font-size: 16px;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
//放头像和用户名的地方。
|
||||
.menu-header {
|
||||
cursor: pointer;
|
||||
|
||||
.logo-area {
|
||||
|
||||
text-align: center;
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
.text-area {
|
||||
.nickname {
|
||||
text-align: center;
|
||||
color: @nav-text-color;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.role {
|
||||
text-align: center;
|
||||
color: @nav-text-color;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//分割线
|
||||
.separate-line {
|
||||
margin-top: 20px;
|
||||
padding-bottom: 5px;
|
||||
border-bottom: 1px solid #666666;
|
||||
|
||||
span {
|
||||
margin-left: 20px;
|
||||
color: #777;
|
||||
}
|
||||
}
|
||||
|
||||
.nav {
|
||||
li {
|
||||
|
||||
a {
|
||||
|
||||
color: @nav-text-color;
|
||||
|
||||
padding: 12px 20px;
|
||||
|
||||
&:hover, &:focus {
|
||||
color: @font-highlight-color;
|
||||
background-color: transparent;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
i {
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
//为什么要用custom-active? 因为 is-link-exact-active 不能匹配 /user/list 和 /user/list?page=0
|
||||
// is-link-active 会将 / 和 /preference 进行匹配。
|
||||
//所以用 is-link-exact-active 的话就会出现刷新列表页面时不高亮
|
||||
//用 is-link-active 时会两个高亮。
|
||||
&.custom-active {
|
||||
background-color: black;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.about-menu {
|
||||
//大屏幕
|
||||
@media (min-width: @screen-sm-min) {
|
||||
display: none;
|
||||
}
|
||||
//手机屏幕
|
||||
@media (max-width: @screen-xs-max) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
@@ -1,177 +0,0 @@
|
||||
<template>
|
||||
<div class="top-navigation-bar">
|
||||
<nav class="navbar">
|
||||
|
||||
<div class="navbar-title">
|
||||
|
||||
<router-link to="/">
|
||||
<img class="logo" :src="logoUrl"/>
|
||||
<span class="title">{{preference.name?preference.name: $t('eyeblueTank') }}</span>
|
||||
</router-link>
|
||||
|
||||
</div>
|
||||
|
||||
<button class="drawer-trigger btn btn-primary btn-sm mr5"
|
||||
@click.stop.prevent="$store.state.config.showDrawer=!$store.state.config.showDrawer">
|
||||
<i class="fa fa-bars"></i>
|
||||
</button>
|
||||
|
||||
|
||||
</nav>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
let defaultLogoPath = require("../../assets/img/logo.png");
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
preference: this.$store.state.preference,
|
||||
user: this.$store.state.user
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
//logo可以使用自定义的。
|
||||
logoUrl() {
|
||||
if (this.preference.logoUrl) {
|
||||
return this.preference.logoUrl + "?ir=fill_" + 200 + "_" + 200
|
||||
} else {
|
||||
return defaultLogoPath
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {},
|
||||
methods: {}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="less" rel="stylesheet/less">
|
||||
|
||||
@import "../../assets/css/global/variables";
|
||||
|
||||
//上方的导航栏
|
||||
.top-navigation-bar {
|
||||
|
||||
height: @top-navigation-height;
|
||||
background-color: white;
|
||||
border-bottom: 1px solid #eeeeee;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 100;
|
||||
padding-left: @sidebar-width;
|
||||
|
||||
.navbar {
|
||||
border: none;
|
||||
}
|
||||
|
||||
//手机屏幕
|
||||
@media (max-width: @screen-xs-max) {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.navbar-title {
|
||||
float: left;
|
||||
cursor: pointer;
|
||||
margin-left: 10px;
|
||||
|
||||
.logo {
|
||||
height: @top-navigation-height;
|
||||
|
||||
}
|
||||
|
||||
.title {
|
||||
margin-left: 10px;
|
||||
font-size: 18px;
|
||||
color: black;
|
||||
font-weight: bold;
|
||||
display: inline-block;
|
||||
line-height: @top-navigation-height;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.login-trigger {
|
||||
float: right;
|
||||
margin-right: 10px;
|
||||
|
||||
.login-span, .register-span {
|
||||
color: #888;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
line-height: 40px;
|
||||
|
||||
&:hover {
|
||||
color: black;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.drawer-trigger {
|
||||
float: right;
|
||||
margin-top: 5px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.navbar-right {
|
||||
|
||||
> li {
|
||||
display: inline-block;
|
||||
|
||||
&:last-child {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #999c9e;
|
||||
font-size: 14px;
|
||||
padding: 6px 12px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
float: right !important;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.message-info {
|
||||
position: relative;
|
||||
|
||||
.label {
|
||||
|
||||
line-height: 12px;
|
||||
padding: 2px 5px;
|
||||
position: absolute;
|
||||
left: 10%;
|
||||
bottom: 50%;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//小屏幕
|
||||
@media (min-width: @screen-sm-min) {
|
||||
.drawer-trigger {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
//手机屏幕
|
||||
@media (max-width: @screen-xs-max) {
|
||||
|
||||
.navbar-right {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
@@ -1,204 +0,0 @@
|
||||
<template>
|
||||
<div class="matter-detail">
|
||||
<div class="matter-block">
|
||||
<div class="title">
|
||||
{{$t('matter.fileInfo')}}
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12 form-info">
|
||||
<span>{{$t('matter.fileInfo')}}: </span>
|
||||
<span class="bold">{{matter.name}}</span>
|
||||
</div>
|
||||
<div class="col-md-12 form-info">
|
||||
<span>{{$t('matter.path')}}: </span>
|
||||
<span class="matter-breadcrumb">
|
||||
<span v-for="m in parentList">
|
||||
<span>/</span>
|
||||
<router-link v-if="m.dir" :to="'/?puuid='+m.uuid">
|
||||
{{m.name}}
|
||||
</router-link>
|
||||
<span v-else>
|
||||
{{m.name}}
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<a class="mr15" :title="$t('matter.path')"
|
||||
@click.stop.prevent="copyPath">
|
||||
<i class="fa fa-copy"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-md-12 form-info" v-if="!matter.dir">
|
||||
<span>{{$t('matter.size')}}: </span>
|
||||
<span class="bold">{{matter.size | humanFileSize}}</span>
|
||||
</div>
|
||||
<div class="col-md-12 form-info">
|
||||
<span>{{$t('matter.createTime')}}: </span>
|
||||
<span class="bold">{{matter.createTime | simpleDateTime}}</span>
|
||||
</div>
|
||||
<div class="col-md-12 form-info">
|
||||
<span>{{$t('matter.updateTime')}}: </span>
|
||||
<span class="bold">{{matter.updateTime | simpleDateTime}}</span>
|
||||
</div>
|
||||
<div class="col-md-12 form-info" v-if="!matter.dir">
|
||||
<span>{{$t('matter.publicOrPrivate')}}: </span>
|
||||
<span>{{matter.privacy?$t('matter.privateInfo'):$t('matter.publicInfo')}}</span>
|
||||
</div>
|
||||
<div class="col-md-12 form-info" v-if="!matter.dir">
|
||||
<span>{{$t('matter.downloadTimes')}}: </span>
|
||||
<span>{{matter.times}}</span>
|
||||
</div>
|
||||
<div class="col-md-12 form-info" v-if="!matter.dir">
|
||||
<span>{{$t('matter.operations')}}: </span>
|
||||
<span>
|
||||
<a class="mr15" :title="$t('matter.download')" @click.stop.prevent="matter.download()" v-if="!matter.dir">
|
||||
<i class="fa fa-download"></i>
|
||||
{{$t('matter.download')}}
|
||||
</a>
|
||||
<a class="mr15" :title="$t('matter.preview')" @click.stop.prevent="matter.preview()" v-if="!matter.dir">
|
||||
<i class="fa fa-eye"></i>
|
||||
{{$t('matter.preview')}}
|
||||
</a>
|
||||
<a class="mr15" :title="$t('matter.oneTimeLinkInfo')"
|
||||
@click.stop.prevent="copyLink" v-if="!matter.dir && matter.privacy">
|
||||
<i class="fa fa-link"></i>
|
||||
{{$t('matter.oneTimeLink')}}
|
||||
</a>
|
||||
<a class="mr15" :title="$t('matter.publicInfo')"
|
||||
@click.stop.prevent="copyLink" v-if="!matter.dir && !matter.privacy">
|
||||
<i class="fa fa-link"></i>
|
||||
{{$t('matter.copyLink')}}
|
||||
</a>
|
||||
|
||||
</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="matter-block" v-if="!matter.dir && matter.uuid && matter.isImage()">
|
||||
<div class="title">
|
||||
{{$t('matter.imageCache')}}
|
||||
</div>
|
||||
<div class="ph5">
|
||||
<ImageCacheList :initFilter="{matterUuid:matter.uuid}"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Matter from "../../common/model/matter/Matter";
|
||||
import ImageCacheList from "../image/cache/widget/ImageCacheList"
|
||||
import DownloadToken from "../../common/model/download/token/DownloadToken";
|
||||
import {Message} from "element-ui"
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
matter: new Matter(),
|
||||
//复制只能是同步进行,因此提前获取downloadToken
|
||||
downloadToken: new DownloadToken(),
|
||||
preference: this.$store.state.preference
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
parentList() {
|
||||
let that = this
|
||||
let arr = []
|
||||
let item = that.matter;
|
||||
while (item) {
|
||||
arr.unshift(item)
|
||||
item = item.parent
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
copyLink() {
|
||||
let that = this;
|
||||
|
||||
if (that.matter.privacy) {
|
||||
|
||||
let textToCopy = that.matter.getDownloadUrl(that.downloadToken.uuid);
|
||||
|
||||
that.$copyPlguin.copy(textToCopy, function () {
|
||||
Message.success({
|
||||
message: that.$t('operationSuccess'),
|
||||
center: true
|
||||
})
|
||||
})
|
||||
} else {
|
||||
let textToCopy = that.matter.getDownloadUrl();
|
||||
|
||||
that.$copyPlguin.copy(textToCopy, function () {
|
||||
Message.success({
|
||||
message: that.$t('operationSuccess'),
|
||||
center: true
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
copyPath() {
|
||||
let that = this;
|
||||
|
||||
let textToCopy = that.matter.path;
|
||||
|
||||
that.$copyPlguin.copy(textToCopy, function () {
|
||||
Message.success({
|
||||
message: that.$t('operationSuccess'),
|
||||
center: true
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
components: {
|
||||
ImageCacheList
|
||||
},
|
||||
mounted() {
|
||||
let that = this;
|
||||
this.matter.uuid = this.$store.state.route.params.uuid
|
||||
if (this.matter.uuid) {
|
||||
this.matter.httpDetail(function () {
|
||||
|
||||
if (!that.matter.dir) {
|
||||
that.downloadToken.httpFetchDownloadToken(that.matter.uuid)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" rel="stylesheet/less">
|
||||
.matter-detail {
|
||||
|
||||
.matter-block {
|
||||
background-color: white;
|
||||
box-shadow: 0 0 5px rgba(0, 0, 0, .2);
|
||||
border-radius: 5px;
|
||||
padding: 20px 15px 10px 15px;
|
||||
margin-bottom: 30px;
|
||||
|
||||
.title {
|
||||
font-size: 16px;
|
||||
padding: 0 0 15px 0;
|
||||
color: black;
|
||||
margin-bottom: 10px;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.matter-breadcrumb {
|
||||
a {
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
@@ -1,544 +0,0 @@
|
||||
<template>
|
||||
<div class="backyard-matter-list">
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-8 mb10">
|
||||
<button class="btn btn-primary btn-sm mr5 mb5" v-if="selectedMatters.length !== pager.data.length"
|
||||
@click.stop.prevent="checkAll">
|
||||
<i class="fa fa-check-square"></i>
|
||||
{{ $t("selectAll") }}
|
||||
</button>
|
||||
|
||||
<button class="btn btn-primary btn-sm mr5 mb5"
|
||||
v-if="pager.data.length && selectedMatters.length === pager.data.length"
|
||||
@click.stop.prevent="checkNone">
|
||||
<i class="fa fa-square-o"></i>
|
||||
{{ $t("cancel") }}
|
||||
</button>
|
||||
|
||||
<button class="btn btn-primary btn-sm mr5 mb5" v-if="selectedMatters.length" @click.stop.prevent="deleteBatch">
|
||||
<i class="fa fa-trash"></i>
|
||||
{{ $t("delete") }}
|
||||
</button>
|
||||
|
||||
<button class="btn btn-primary btn-sm mr5 mb5" v-if="selectedMatters.length" @click.stop.prevent="downloadZip">
|
||||
<i class="fa fa-download"></i>
|
||||
{{ $t("matter.download") }}
|
||||
</button>
|
||||
|
||||
<button class="btn btn-primary btn-sm mr5 mb5" v-if="selectedMatters.length"
|
||||
@click.stop.prevent="moveBatch($createElement)">
|
||||
<i class="fa fa-arrows"></i>
|
||||
{{ $t("matter.move") }}
|
||||
</button>
|
||||
|
||||
<button class="btn btn-primary btn-sm mr5 mb5" v-if="selectedMatters.length"
|
||||
@click.stop.prevent="shareDialogVisible = !shareDialogVisible">
|
||||
<i class="fa fa-share-alt"></i>
|
||||
{{ $t("matter.share") }}
|
||||
</button>
|
||||
|
||||
<el-dialog
|
||||
:title="$t('matter.share')"
|
||||
:visible.sync="shareDialogVisible"
|
||||
:append-to-body="true">
|
||||
|
||||
<SharePanel :matters="selectedMatters"
|
||||
@close="shareDialogVisible = false"/>
|
||||
|
||||
</el-dialog>
|
||||
|
||||
|
||||
<span class="btn btn-primary btn-sm btn-file mr5 mb5">
|
||||
<slot name="button">
|
||||
<i class="fa fa-cloud-upload"></i>
|
||||
<span> {{ $t("matter.upload") }} </span>
|
||||
</slot>
|
||||
<input ref="refFile" type="file" multiple="multiple" @change.prevent.stop="triggerUpload"/>
|
||||
</span>
|
||||
|
||||
<button class="btn btn-sm btn-primary mr5 mb5" @click.stop.prevent="createDirectory">
|
||||
<i class="fa fa-folder"></i>
|
||||
{{ $t("matter.create") }}
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-md-4 mb10">
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" v-model="searchText" @keyup.enter="searchFile"
|
||||
:placeholder="$t('matter.searchFile')">
|
||||
<span class="input-group-btn">
|
||||
<button type="button" class="btn btn-primary" @click.prevent.stop="searchFile">
|
||||
<i class="fa fa-search"></i>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12">
|
||||
|
||||
|
||||
<div v-for="m in uploadMatters">
|
||||
<UploadMatterPanel :matter="m"/>
|
||||
</div>
|
||||
|
||||
<div v-if="director.createMode">
|
||||
<MatterPanel ref="newMatterPanel" @createDirectorySuccess="refresh()"
|
||||
:matter="newMatter"
|
||||
:director="director"/>
|
||||
</div>
|
||||
<div v-for="matter in pager.data">
|
||||
<MatterPanel :key="matter.uuid"
|
||||
@goToDirectory="goToDirectory"
|
||||
@deleteSuccess="refresh()"
|
||||
:matter="matter"
|
||||
:director="director"
|
||||
@checkMatter="checkMatter"
|
||||
@previewImage="previewImage"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<NbPager :pager="pager" :callback="refresh" :emptyHint="$t('matter.noContentYet')"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import MatterPanel from './widget/MatterPanel'
|
||||
import UploadMatterPanel from './widget/UploadMatterPanel'
|
||||
import MoveBatchPanel from './widget/MoveBatchPanel'
|
||||
import SharePanel from './widget/ShareOperationPanel'
|
||||
import NbSlidePanel from '../../common/widget/NbSlidePanel.vue'
|
||||
import NbExpanding from '../../common/widget/NbExpanding.vue'
|
||||
import NbCheckbox from '../../common/widget/NbCheckbox.vue'
|
||||
import NbFilter from '../../common/widget/filter/NbFilter'
|
||||
import NbPager from '../../common/widget/NbPager'
|
||||
import Matter from '../../common/model/matter/Matter'
|
||||
import Pager from '../../common/model/base/Pager'
|
||||
import Director from './widget/Director'
|
||||
import {Message, MessageBox} from 'element-ui'
|
||||
import {UserRole} from "../../common/model/user/UserRole";
|
||||
import {SortDirection} from "../../common/model/base/SortDirection";
|
||||
import {humanFileSize} from "../../common/filter/str";
|
||||
import Share from "../../common/model/share/Share";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
//当前文件夹信息。
|
||||
matter: new Matter(),
|
||||
//准备新建的文件。
|
||||
newMatter: new Matter(),
|
||||
//准备上传的一系列文件
|
||||
uploadMatters: this.$store.state.uploadMatters,
|
||||
//当前选中的文件
|
||||
selectedMatters: [],
|
||||
//搜索的文字
|
||||
searchText: null,
|
||||
pager: new Pager(Matter, 50),
|
||||
//移动的目标文件夹
|
||||
targetMatterUuid: null,
|
||||
user: this.$store.state.user,
|
||||
preference: this.$store.state.preference,
|
||||
breadcrumbs: this.$store.state.breadcrumbs,
|
||||
director: new Director(),
|
||||
|
||||
share: new Share(),
|
||||
//分享的弹框
|
||||
shareDialogVisible: false
|
||||
|
||||
}
|
||||
},
|
||||
components: {
|
||||
MatterPanel,
|
||||
UploadMatterPanel,
|
||||
MoveBatchPanel,
|
||||
SharePanel,
|
||||
NbCheckbox,
|
||||
NbFilter,
|
||||
NbPager,
|
||||
NbSlidePanel,
|
||||
NbExpanding
|
||||
},
|
||||
methods: {
|
||||
reset() {
|
||||
this.pager.page = 0
|
||||
this.pager.resetFilter()
|
||||
this.pager.enableHistory()
|
||||
},
|
||||
search() {
|
||||
this.pager.page = 0
|
||||
this.refresh()
|
||||
},
|
||||
refresh() {
|
||||
|
||||
|
||||
let puuid = this.$route.query.puuid
|
||||
if (puuid) {
|
||||
this.pager.setFilterValue('puuid', puuid)
|
||||
} else {
|
||||
this.pager.setFilterValue('puuid', 'root')
|
||||
}
|
||||
|
||||
//如果所有的排序都没有设置,那么默认以时间降序。
|
||||
this.pager.setFilterValue('orderCreateTime', SortDirection.DESC)
|
||||
this.pager.setFilterValue("orderDir", SortDirection.DESC)
|
||||
|
||||
//如果没有设置用户的话,那么默认显示当前登录用户的资料
|
||||
if (!this.pager.getFilterValue('userUuid')) {
|
||||
this.pager.setFilterValue('userUuid', this.user.uuid)
|
||||
}
|
||||
|
||||
this.pager.setFilterValue("name", null)
|
||||
|
||||
|
||||
//刷新面包屑
|
||||
this.refreshBreadcrumbs()
|
||||
|
||||
this.pager.httpFastPage()
|
||||
},
|
||||
goToDirectory(uuid) {
|
||||
this.pager.setFilterValue('puuid', uuid)
|
||||
this.pager.page = 0
|
||||
let query = this.pager.getParams()
|
||||
|
||||
//采用router去管理路由,否则浏览器的回退按钮出现意想不到的问题。
|
||||
this.$router.push({
|
||||
path: '/',
|
||||
query: query
|
||||
})
|
||||
|
||||
},
|
||||
refreshBreadcrumbs() {
|
||||
|
||||
let that = this
|
||||
|
||||
//清空暂存区
|
||||
this.selectedMatters.splice(0, this.selectedMatters.length)
|
||||
|
||||
let uuid = that.pager.getFilterValue('puuid')
|
||||
|
||||
//根目录简单处理即可。
|
||||
if (!uuid || uuid === 'root') {
|
||||
|
||||
this.matter.uuid = 'root'
|
||||
that.breadcrumbs.splice(0, that.breadcrumbs.length)
|
||||
that.breadcrumbs.push({
|
||||
title: 'matter.allFiles'
|
||||
})
|
||||
|
||||
} else {
|
||||
|
||||
this.matter.uuid = uuid
|
||||
this.matter.httpDetail(function () {
|
||||
|
||||
let arr = []
|
||||
let cur = that.matter.parent
|
||||
while (cur) {
|
||||
arr.push(cur)
|
||||
cur = cur.parent
|
||||
}
|
||||
|
||||
that.breadcrumbs.splice(0, that.breadcrumbs.length)
|
||||
let query = that.pager.getParams()
|
||||
query['puuid'] = 'root'
|
||||
//添加一个随机数,防止watch $route失败
|
||||
query['_t'] = new Date().getTime()
|
||||
that.breadcrumbs.push({
|
||||
title: 'matter.allFiles',
|
||||
path: '/',
|
||||
query: query
|
||||
})
|
||||
|
||||
for (let i = arr.length - 1; i >= 0; i--) {
|
||||
let m = arr[i]
|
||||
let query = that.pager.getParams()
|
||||
query['puuid'] = m.uuid
|
||||
query['_t'] = new Date().getTime()
|
||||
that.breadcrumbs.push({
|
||||
title: m.name,
|
||||
displayDirect: true,
|
||||
path: '/',
|
||||
query: query
|
||||
})
|
||||
}
|
||||
//第一个文件
|
||||
that.breadcrumbs.push({
|
||||
title: that.matter.name,
|
||||
displayDirect: true,
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
createDirectory() {
|
||||
let that = this
|
||||
that.newMatter.name = 'matter.allFiles'
|
||||
that.newMatter.dir = true
|
||||
that.newMatter.editMode = true
|
||||
that.newMatter.puuid = that.matter.uuid
|
||||
if (!that.newMatter.puuid) {
|
||||
that.newMatter.puuid = 'root'
|
||||
}
|
||||
|
||||
|
||||
//指定为当前选择的用户。
|
||||
//如果没有设置用户的话,那么默认显示当前登录用户的资料
|
||||
if (!that.pager.getFilterValue('userUuid')) {
|
||||
that.newMatter.userUuid = that.user.uuid
|
||||
} else {
|
||||
that.newMatter.userUuid = that.pager.getFilterValue('userUuid')
|
||||
}
|
||||
|
||||
that.director.createMode = true
|
||||
|
||||
setTimeout(function () {
|
||||
that.$refs.newMatterPanel.highLight()
|
||||
}, 100)
|
||||
},
|
||||
triggerUpload() {
|
||||
let that = this
|
||||
|
||||
let domFiles = that.$refs['refFile'].files;
|
||||
if (!domFiles || !domFiles.length) {
|
||||
that.$message.error(that.$t('matter.allFiles'))
|
||||
return;
|
||||
}
|
||||
|
||||
if (domFiles.length > 1000) {
|
||||
that.$message.error(that.$t('matter.exceed1000'))
|
||||
return;
|
||||
}
|
||||
|
||||
for (let i = 0; i < domFiles.length; i++) {
|
||||
let domFile = domFiles[i];
|
||||
let m = new Matter()
|
||||
m.dir = false
|
||||
m.puuid = that.matter.uuid
|
||||
|
||||
//指定为当前选择的用户。
|
||||
//如果没有设置用户的话,那么默认显示当前登录用户的资料
|
||||
if (!that.pager.getFilterValue('userUuid')) {
|
||||
m.userUuid = that.user.uuid
|
||||
} else {
|
||||
m.userUuid = that.pager.getFilterValue('userUuid')
|
||||
}
|
||||
|
||||
//判断文件大小。
|
||||
if (that.user.sizeLimit >= 0) {
|
||||
if (domFile.size > that.user.sizeLimit) {
|
||||
that.$message.error(that.$t('matter.sizeExceedLimit', humanFileSize(domFile.size), humanFileSize(that.user.sizeLimit)))
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
m.file = domFile
|
||||
|
||||
m.httpUpload(function () {
|
||||
that.$store.state.uploadListInstance.refresh()
|
||||
})
|
||||
|
||||
that.uploadMatters.push(m)
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
|
||||
previewImage(matter) {
|
||||
let that = this;
|
||||
|
||||
//从matter开始预览图片
|
||||
let imageArray = []
|
||||
let startIndex = -1;
|
||||
this.pager.data.forEach(function (item, index) {
|
||||
if (item.isImage()) {
|
||||
imageArray.push(item.getPreviewUrl())
|
||||
if (item.uuid === matter.uuid) {
|
||||
startIndex = imageArray.length - 1
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
that.$photoSwipePlugin.showPhotos(imageArray, startIndex)
|
||||
|
||||
},
|
||||
//全选
|
||||
checkAll() {
|
||||
this.pager.data.forEach(function (i, index) {
|
||||
i.check = true
|
||||
})
|
||||
this.checkMatter()
|
||||
},
|
||||
//取消全选
|
||||
checkNone() {
|
||||
this.pager.data.forEach(function (i, index) {
|
||||
i.check = false
|
||||
})
|
||||
this.checkMatter()
|
||||
},
|
||||
//选择文件时放入暂存区等待操作
|
||||
checkMatter(matter) {
|
||||
let that = this
|
||||
//统计所有的勾选
|
||||
this.selectedMatters.splice(0, this.selectedMatters.length)
|
||||
this.pager.data.forEach(function (matter, index) {
|
||||
if (matter.check) {
|
||||
that.selectedMatters.push(matter)
|
||||
}
|
||||
})
|
||||
|
||||
},
|
||||
|
||||
//批量删除
|
||||
downloadZip() {
|
||||
let that = this
|
||||
let uuids = []
|
||||
|
||||
that.selectedMatters.forEach(function (item, index) {
|
||||
uuids.push(item.uuid)
|
||||
})
|
||||
|
||||
that.matter.downloadZip(uuids.toString())
|
||||
},
|
||||
//批量删除
|
||||
deleteBatch() {
|
||||
let that = this
|
||||
MessageBox.confirm(that.$t("actionCanNotRevertConfirm"), that.$t("prompt"), {
|
||||
confirmButtonText: that.$t("confirm"),
|
||||
cancelButtonText: that.$t("cancel"),
|
||||
type: 'warning',
|
||||
callback: function (action, instance) {
|
||||
if (action === 'confirm') {
|
||||
let uuids = ""
|
||||
that.selectedMatters.forEach(function (item, index) {
|
||||
if (index === 0) {
|
||||
uuids = item.uuid
|
||||
} else {
|
||||
uuids = uuids + "," + item.uuid
|
||||
}
|
||||
})
|
||||
that.matter.httpDeleteBatch(uuids, function (response) {
|
||||
Message.success(that.$t("operationSuccess"))
|
||||
that.refresh()
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
//批量移动
|
||||
moveBatch(createElement) {
|
||||
let that = this
|
||||
|
||||
|
||||
let dom = createElement(MoveBatchPanel, {
|
||||
props: {
|
||||
version: (new Date()).getTime(),
|
||||
userUuid: that.selectedMatters[0].userUuid,
|
||||
callback: function (matter) {
|
||||
if (matter.uuid) {
|
||||
that.targetMatterUuid = matter.uuid
|
||||
} else {
|
||||
that.targetMatterUuid = "root"
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
MessageBox({
|
||||
title: '移动到',
|
||||
message: dom,
|
||||
customClass: 'wp50',
|
||||
confirmButtonText: that.$t("confirm"),
|
||||
showCancelButton: true,
|
||||
cancelButtonText: '关闭',
|
||||
callback: (action, instance) => {
|
||||
if (action === 'confirm') {
|
||||
let uuids = ""
|
||||
that.selectedMatters.forEach(function (item, index) {
|
||||
if (index === 0) {
|
||||
uuids = item.uuid
|
||||
} else {
|
||||
uuids = uuids + "," + item.uuid
|
||||
}
|
||||
})
|
||||
|
||||
that.matter.httpMove(uuids, that.targetMatterUuid, function (response) {
|
||||
Message.success('移动成功!')
|
||||
that.refresh()
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
searchFile() {
|
||||
|
||||
let that = this;
|
||||
if (that.searchText) {
|
||||
|
||||
//刷新面包屑
|
||||
that.refreshBreadcrumbs()
|
||||
|
||||
|
||||
that.pager.resetFilter()
|
||||
that.pager.setFilterValue('puuid', null)
|
||||
that.pager.setFilterValue("orderCreateTime", SortDirection.DESC)
|
||||
that.pager.setFilterValue("name", that.searchText)
|
||||
|
||||
that.pager.httpFastPage()
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
|
||||
that.refresh()
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'$route'(newVal, oldVal) {
|
||||
|
||||
this.refresh()
|
||||
|
||||
},
|
||||
'searchText'(newVal, oldVal) {
|
||||
if (oldVal && !newVal) {
|
||||
this.refresh()
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
created() {
|
||||
/*初始化inputSelection*/
|
||||
if (this.user.role === UserRole.ADMINISTRATOR) {
|
||||
this.pager.getFilter('userUuid').visible = true
|
||||
} else {
|
||||
this.pager.setFilterValue('userUuid', this.user.uuid)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
let that = this
|
||||
this.pager.enableHistory()
|
||||
//更新vuex中List实例,主要解决大文件上传持有的功能。
|
||||
this.$store.state.uploadListInstance = this
|
||||
|
||||
this.refresh()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="less" rel="stylesheet/less">
|
||||
@import "../../assets/css/global/variables";
|
||||
|
||||
.backyard-matter-list {
|
||||
|
||||
}
|
||||
</style>
|
||||
@@ -1,140 +0,0 @@
|
||||
<template>
|
||||
<div class="folder-tree">
|
||||
<div class="h50 cursor folder-block" :class="{'bg-silver-white': targetMatter.uuid === matter.uuid}"
|
||||
@click.stop.prevent="clickItem">
|
||||
<span class="fa fa-chevron-down mr5 w14" v-if="pager.data.length && showSubFolder"></span>
|
||||
<span class="fa fa-chevron-right mr5 w14" v-if="pager.data.length && !showSubFolder"></span>
|
||||
<span :class="{ 'ml23': !pager.data.length }">
|
||||
<span v-if="matter.uuid">
|
||||
<img :src="matter.getIcon()" class="mr5" :alt="Vue.i18n.t('matter.directory')" width="22"/>
|
||||
<span>{{matter.name}}</span>
|
||||
</span>
|
||||
<span v-else>
|
||||
<span>{{Vue.i18n.t('matter.root')}}</span>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
<NbExpanding>
|
||||
<div v-if="pager.data.length && showSubFolder" class="pl20">
|
||||
<div v-for="(child, index) in pager.data">
|
||||
<FolderTree :matter="child" :targetMatter="targetMatter" :userUuid="userUuid" :version="version"
|
||||
:callback="callback" :showSubFolderInit="false"/>
|
||||
</div>
|
||||
</div>
|
||||
</NbExpanding>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NbExpanding from '../../../common/widget/NbExpanding'
|
||||
import Pager from '../../../common/model/base/Pager'
|
||||
import Matter from '../../../common/model/matter/Matter'
|
||||
import Vue from "vue"
|
||||
|
||||
export default {
|
||||
|
||||
name: "FolderTree",
|
||||
data() {
|
||||
return {
|
||||
Vue,
|
||||
showSubFolder: false,
|
||||
pager: new Pager(Matter)
|
||||
}
|
||||
},
|
||||
props: {
|
||||
targetMatter: {
|
||||
type: Matter,
|
||||
required: true
|
||||
},
|
||||
matter: {
|
||||
type: Matter,
|
||||
required: true
|
||||
},
|
||||
showSubFolderInit: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
userUuid: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
//为了让Tree在每次点开的时候都更新
|
||||
version: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
//选择了一个文件夹后回掉,参数matter
|
||||
callback: {
|
||||
type: Function,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
//有可能外面世界的userUuid发生了变化
|
||||
'userUuid'(newVal, oldVal) {
|
||||
this.refresh()
|
||||
},
|
||||
//有可能外面世界的version发生了变化
|
||||
'version'(newVal, oldVal) {
|
||||
this.refresh()
|
||||
}
|
||||
|
||||
},
|
||||
methods: {
|
||||
clickItem() {
|
||||
this.showSubFolder = !this.showSubFolder
|
||||
if (this.targetMatter.uuid !== this.matter.uuid) {
|
||||
this.targetMatter.render(this.matter)
|
||||
|
||||
if (typeof this.callback === "function") {
|
||||
this.callback(this.targetMatter)
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
refresh() {
|
||||
|
||||
this.showSubFolder = this.showSubFolderInit
|
||||
|
||||
if (!this.matter.uuid) {
|
||||
this.pager.setFilterValue('puuid', 'root')
|
||||
} else {
|
||||
this.pager.setFilterValue('puuid', this.matter.uuid)
|
||||
}
|
||||
|
||||
//限制选择的范围。文件和目标文件夹必须是同一主人
|
||||
this.pager.setFilterValue('userUuid', this.userUuid)
|
||||
|
||||
this.pager.setFilterValue('dir', true)
|
||||
this.pager.httpFastPage()
|
||||
|
||||
}
|
||||
},
|
||||
components: {
|
||||
NbExpanding
|
||||
},
|
||||
mounted() {
|
||||
this.refresh()
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" rel="stylesheet/less">
|
||||
.folder-tree {
|
||||
.folder-block {
|
||||
padding: 5px 10px;
|
||||
line-height: 40px;
|
||||
&:hover {
|
||||
background: #eee;
|
||||
}
|
||||
}
|
||||
.ml23 {
|
||||
margin-left: 23px;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,145 +0,0 @@
|
||||
<template>
|
||||
<div class="nb-matter-image">
|
||||
|
||||
<div class="tiny-block">
|
||||
<div class="p10 mb10 bg-white br5 border" :style="'width:'+previewWidth+'px'" v-show="preview && value">
|
||||
<img class="wp100 cursor" :src="value" @click="$photoSwipePlugin.showPhoto(value)"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="input-group">
|
||||
<input type="text"
|
||||
class="form-control input-sm"
|
||||
v-model="value"
|
||||
v-if="manual"
|
||||
:placeholder="$t('matter.fillInPicLink')">
|
||||
|
||||
<span class="form-control input-sm btn-file text-center pt3 pb0" v-show="!manual">
|
||||
<slot name="button">
|
||||
<i class="fa fa-cloud-upload"></i>
|
||||
<span>{{value?$t('matter.rePick'):$t('matter.chooseImage')}}</span>
|
||||
</slot>
|
||||
<input ref="refFile" type="file" @change.prevent.stop="triggerUpload"/>
|
||||
</span>
|
||||
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-primary btn-sm mr5" @click.stop.prevent="manual = !manual">
|
||||
<i class="fa fa-pencil" v-if="!manual"></i>
|
||||
<i class="fa fa-cloud-upload" v-if="manual"></i>
|
||||
<span>{{manual?$t('matter.uploadMode'):$t('matter.fillMode')}}</span>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="italic" v-if="uploadHint">
|
||||
{{uploadHint}}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<UploadMatterPanel :matter="matter"/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import Matter from '../../../common/model/matter/Matter'
|
||||
import UploadMatterPanel from "./UploadMatterPanel"
|
||||
import {humanFileSize} from "../../../common/filter/str";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
manual: false,
|
||||
user: this.$store.state.user,
|
||||
matter: new Matter()
|
||||
}
|
||||
},
|
||||
components: {
|
||||
UploadMatterPanel
|
||||
},
|
||||
props: {
|
||||
preview: {
|
||||
//上传的照片是否需要预览
|
||||
type: Boolean,
|
||||
required: false,
|
||||
'default': true
|
||||
},
|
||||
previewWidth: {
|
||||
type: Number,
|
||||
required: false,
|
||||
'default': 200
|
||||
},
|
||||
//图片的url.
|
||||
value: {
|
||||
type: String | null,
|
||||
required: true
|
||||
},
|
||||
//filter.
|
||||
filter: {
|
||||
type: String,
|
||||
required: false,
|
||||
"default": "image"
|
||||
},
|
||||
uploadHint: {
|
||||
type: String,
|
||||
required: false,
|
||||
"default": ""
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
del() {
|
||||
let that = this
|
||||
that.matter.clear()
|
||||
},
|
||||
triggerUpload() {
|
||||
let that = this
|
||||
|
||||
let matter = that.matter;
|
||||
matter.puuid = "root"
|
||||
matter.uploadHint = that.uploadHint
|
||||
matter.filter = that.filter
|
||||
matter.privacy = false
|
||||
|
||||
matter.dir = false
|
||||
matter.alien = true
|
||||
matter.userUuid = that.user.uuid
|
||||
|
||||
let value = that.$refs['refFile'].value
|
||||
if (!value) {
|
||||
return
|
||||
}
|
||||
matter.file = that.$refs['refFile'].files[0]
|
||||
|
||||
|
||||
//判断文件大小。
|
||||
if (that.user.sizeLimit >= 0) {
|
||||
if (matter.file.size > that.user.sizeLimit) {
|
||||
that.$message.error(this.$t('matter.sizeExceedLimit', humanFileSize(matter.file.size), humanFileSize(that.user.sizeLimit)))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
matter.httpUpload(function () {
|
||||
|
||||
that.$emit("input", matter.getPreviewUrl())
|
||||
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
},
|
||||
created() {
|
||||
},
|
||||
mounted() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style lang="less" rel="stylesheet/less">
|
||||
.nb-matter-image {
|
||||
|
||||
}
|
||||
</style>
|
||||
@@ -1,449 +0,0 @@
|
||||
<template>
|
||||
<div class="widget-matter-panel">
|
||||
|
||||
<div @click.stop.prevent="clickRow">
|
||||
|
||||
<div class="media">
|
||||
|
||||
<div class="pull-left">
|
||||
<div class="left-part">
|
||||
<span class="basic-span">
|
||||
<NbCheckbox v-model="matter.check"/>
|
||||
</span>
|
||||
<span class="basic-span">
|
||||
<img class="matter-icon" :src="matter.getIcon()"/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--在大屏下的操作栏-->
|
||||
<div class="pull-right hidden-sm hidden-xs">
|
||||
<div class="right-part" v-if="matter.uuid">
|
||||
|
||||
<span class="matter-operation">
|
||||
|
||||
<i class="fa fa-lock btn-action text-primary" v-if="!matter.dir && matter.privacy"
|
||||
:title="$t('matter.setPublic')"
|
||||
@click.stop.prevent="matter.httpChangePrivacy(false)"></i>
|
||||
<i class="fa fa-unlock btn-action text-primary" v-if="!matter.dir && !matter.privacy"
|
||||
:title="$t('matter.setPrivate')"
|
||||
@click.stop.prevent="matter.httpChangePrivacy(true)"></i>
|
||||
|
||||
<i class="fa fa-info-circle btn-action text-primary" :title="$t('matter.file')"
|
||||
@click.stop.prevent="$router.push('/matter/detail/'+matter.uuid)"></i>
|
||||
|
||||
<i class="fa fa-font btn-action text-primary" :title="$t('matter.rename')"
|
||||
@click.stop.prevent="prepareRename"></i>
|
||||
<i class="fa fa-link btn-action text-primary" :title="$t('matter.copyLink')" v-if="!matter.dir"
|
||||
@click.stop.prevent="clipboard"></i>
|
||||
<i class="fa fa-download btn-action text-primary" :title="$t('matter.download')"
|
||||
@click.stop.prevent="matter.download()"></i>
|
||||
|
||||
<i class="fa fa-trash btn-action text-danger" :title="$t('matter.delete')"
|
||||
@click.stop.prevent="deleteMatter"></i>
|
||||
</span>
|
||||
<span class="matter-size">
|
||||
{{matter.size | humanFileSize}}
|
||||
</span>
|
||||
|
||||
<span class="matter-date">
|
||||
{{matter.updateTime | simpleDateHourMinute}}
|
||||
</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--在小屏幕下的操作栏-->
|
||||
<div class="pull-right hidden-lg hidden-md">
|
||||
<span class="more-btn" @click.stop.prevent="showMore = !showMore">
|
||||
<i class="fa fa-ellipsis-h btn-action" :title="$t('matter.more')"></i>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="media-body">
|
||||
|
||||
<div class="middle-part">
|
||||
|
||||
<span class="matter-name-edit" v-if="matter.editMode">
|
||||
<input ref="editInput" class="form-control"
|
||||
:class="matter.uuid"
|
||||
v-model="renameMatterName"
|
||||
:placeholder="$t('matter.enterName')"
|
||||
@blur="blurTrigger()"
|
||||
v-on:keyup.13="enterTrigger()"/>
|
||||
</span>
|
||||
<span class="matter-name"
|
||||
:title="matter.name" v-else>
|
||||
{{matter.name}} <i class="fa fa-unlock" v-if="!matter.dir && !matter.privacy"
|
||||
:title="$t('matter.publicFileEveryoneCanVisit')"></i>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<NbExpanding>
|
||||
<div class="hidden-lg hidden-md more-panel" v-if="showMore">
|
||||
<div class="cell-btn" style="border: none">
|
||||
<span>
|
||||
{{matter.updateTime | simpleDateHourMinute}}
|
||||
</span>
|
||||
|
||||
<span v-if="!matter.dir">
|
||||
{{matter.size | humanFileSize}}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="cell-btn" v-if="!matter.dir && matter.privacy" :title="$t('matter.setPublic')"
|
||||
@click.stop.prevent="matter.httpChangePrivacy(false)">
|
||||
<i class="fa fa-lock"></i>
|
||||
{{$t('matter.setPublic')}}
|
||||
</div>
|
||||
|
||||
<div class="cell-btn" v-if="!matter.dir && !matter.privacy" :title="$t('matter.setPrivate')"
|
||||
@click.stop.prevent="matter.httpChangePrivacy(true)">
|
||||
<i class="fa fa-unlock"></i>
|
||||
{{$t('matter.setPrivate')}}
|
||||
</div>
|
||||
|
||||
<div class="cell-btn" :title="$t('matter.fileDetail')"
|
||||
@click.stop.prevent="$router.push('/matter/detail/'+matter.uuid)">
|
||||
<i class="fa fa-info-circle"></i>
|
||||
{{$t('matter.fileDetail')}}
|
||||
</div>
|
||||
|
||||
<div class="cell-btn" :title="$t('matter.rename')" @click.stop.prevent="prepareRename">
|
||||
<i class="fa fa-pencil"></i>
|
||||
{{$t('matter.rename')}}
|
||||
</div>
|
||||
|
||||
<div class="cell-btn" :title="$t('matter.copyLink')"
|
||||
@click.stop.prevent="clipboard">
|
||||
<i class="fa fa-link"></i>
|
||||
|
||||
{{$t('matter.copyLink')}}
|
||||
</div>
|
||||
|
||||
<div class="cell-btn" :title="$t('matter.download')"
|
||||
@click.stop.prevent="matter.download()">
|
||||
<i class="fa fa-download"></i>
|
||||
{{$t('matter.download')}}
|
||||
</div>
|
||||
|
||||
<div class="cell-btn text-danger" :title="$t('matter.delete')" @click.stop.prevent="deleteMatter">
|
||||
<i class="fa fa-trash"></i>
|
||||
{{$t('matter.delete')}}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</NbExpanding>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
<script>
|
||||
import Matter from '../../../common/model/matter/Matter'
|
||||
import NbCheckbox from '../../../common/widget/NbCheckbox'
|
||||
import NbExpanding from '../../../common/widget/NbExpanding'
|
||||
import $ from 'jquery'
|
||||
import Director from './Director'
|
||||
import {Message, MessageBox} from 'element-ui'
|
||||
import {currentHost, setInputSelection} from '../../../common/util/Utils'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
//正在向服务器提交rename的请求
|
||||
renamingLoading: false,
|
||||
showMore: false,
|
||||
//正在重命名的临时字段
|
||||
renameMatterName: null
|
||||
}
|
||||
},
|
||||
components: {
|
||||
NbExpanding,
|
||||
NbCheckbox
|
||||
},
|
||||
props: {
|
||||
matter: {
|
||||
type: Matter,
|
||||
required: true
|
||||
},
|
||||
director: {
|
||||
type: Director,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'matter.check'(newVal, oldVal) {
|
||||
this.$emit('checkMatter', this.matter)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
clickRow() {
|
||||
let that = this
|
||||
|
||||
if (this.director.isEditing()) {
|
||||
console.error('导演正忙着,不予执行')
|
||||
return
|
||||
}
|
||||
|
||||
if (this.matter.dir) {
|
||||
this.$emit('goToDirectory', that.matter.uuid)
|
||||
} else {
|
||||
//图片进行预览操作
|
||||
if (that.matter.isImage()) {
|
||||
|
||||
this.$emit("previewImage", that.matter)
|
||||
|
||||
} else {
|
||||
that.matter.preview()
|
||||
}
|
||||
}
|
||||
},
|
||||
deleteMatter() {
|
||||
let that = this
|
||||
MessageBox.confirm(that.$t('actionCanNotRevertConfirm'), that.$t('prompt'), {
|
||||
confirmButtonText: that.$t("confirm"),
|
||||
cancelButtonText: that.$t("cancel"),
|
||||
type: 'warning',
|
||||
callback: function (action, instance) {
|
||||
if (action === 'confirm') {
|
||||
that.matter.httpDelete(function (response) {
|
||||
Message.success(that.$t('operationSuccess'))
|
||||
that.$emit('deleteSuccess', that.matter)
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
},
|
||||
prepareRename() {
|
||||
let that = this
|
||||
|
||||
if (this.director.isEditing()) {
|
||||
console.error('导演正忙着,不予执行')
|
||||
return
|
||||
}
|
||||
//告诉导演,自己正在编辑
|
||||
this.director.renameMode = true
|
||||
this.matter.editMode = true
|
||||
this.renameMatterName = this.matter.name
|
||||
|
||||
//稍作延迟,vue的组件才能加载出来
|
||||
setTimeout(function () {
|
||||
|
||||
//如果是文件夹,全选中
|
||||
let dotIndex = that.matter.name.lastIndexOf('.')
|
||||
if (dotIndex === -1) {
|
||||
setInputSelection(that.$refs.editInput, 0, that.renameMatterName.length)
|
||||
} else {
|
||||
setInputSelection(that.$refs.editInput, 0, dotIndex)
|
||||
}
|
||||
|
||||
}, 100)
|
||||
|
||||
},
|
||||
finishRename() {
|
||||
let that = this
|
||||
//有可能按enter的时候和blur同时了。
|
||||
if (that.renamingLoading) {
|
||||
return
|
||||
}
|
||||
|
||||
that.renamingLoading = true
|
||||
this.matter.httpRename(that.renameMatterName, function () {
|
||||
that.renamingLoading = false
|
||||
Message.success(that.$t('operationSuccess'))
|
||||
//告诉导演,自己编辑完毕
|
||||
that.director.renameMode = false
|
||||
that.matter.editMode = false
|
||||
|
||||
}, function (errorMessage) {
|
||||
that.renamingLoading = false
|
||||
Message.error(errorMessage)
|
||||
//告诉导演,自己编辑完毕
|
||||
that.director.renameMode = false
|
||||
that.matter.editMode = false
|
||||
|
||||
})
|
||||
|
||||
},
|
||||
finishCreateDirectory() {
|
||||
let that = this
|
||||
that.matter.name = that.renameMatterName
|
||||
that.matter.httpCreateDirectory(function () {
|
||||
that.director.createMode = false
|
||||
that.editMode = false
|
||||
|
||||
that.matter.render(new Matter())
|
||||
|
||||
that.$emit('createDirectorySuccess', that.matter)
|
||||
|
||||
}, function (errorMessage) {
|
||||
that.director.createMode = false
|
||||
that.editMode = false
|
||||
Message.error(errorMessage)
|
||||
})
|
||||
},
|
||||
blurTrigger() {
|
||||
let that = this
|
||||
if (that.matter.editMode) {
|
||||
if (that.director.createMode) {
|
||||
that.finishCreateDirectory()
|
||||
} else if (that.director.renameMode) {
|
||||
that.finishRename()
|
||||
}
|
||||
}
|
||||
},
|
||||
enterTrigger() {
|
||||
$(this.$refs.editInput).blur()
|
||||
},
|
||||
highLight() {
|
||||
$(this.$refs.editInput).select()
|
||||
},
|
||||
clipboard() {
|
||||
let that = this
|
||||
|
||||
let textToCopy = this.matter.getDownloadUrl();
|
||||
this.$copyPlguin.copy(textToCopy, function () {
|
||||
Message.success({
|
||||
message: that.$t('operationSuccess'),
|
||||
center: true
|
||||
})
|
||||
})
|
||||
|
||||
}
|
||||
},
|
||||
created() {
|
||||
},
|
||||
mounted() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style lang="less" rel="stylesheet/less">
|
||||
|
||||
@import "../../../assets/css/global/variables";
|
||||
|
||||
@base-height: 48px;
|
||||
@inner-cell-height: 36px;
|
||||
|
||||
.basic-span {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
line-height: @base-height;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.widget-matter-panel {
|
||||
|
||||
border-top: 1px solid #eee;
|
||||
background-color: white;
|
||||
|
||||
.media {
|
||||
> .pull-left {
|
||||
padding-right: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.matter-icon {
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
.left-part {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.middle-part {
|
||||
|
||||
height: @base-height;
|
||||
overflow: hidden;
|
||||
|
||||
.matter-name-edit {
|
||||
.basic-span;
|
||||
|
||||
width: 90%;
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
height: 26px;
|
||||
display: inline-block;
|
||||
padding: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
.matter-name {
|
||||
.basic-span;
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.right-part {
|
||||
|
||||
.matter-operation {
|
||||
.basic-span;
|
||||
display: none;
|
||||
|
||||
i {
|
||||
font-size: 16px;
|
||||
margin-right: 5px;
|
||||
|
||||
&:hover {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.matter-size {
|
||||
.basic-span;
|
||||
display: inline-block;
|
||||
width: 80px;
|
||||
text-align: left;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.matter-date {
|
||||
.basic-span;
|
||||
}
|
||||
}
|
||||
|
||||
.more-btn {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
line-height: @base-height;
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: aliceblue;
|
||||
cursor: pointer;
|
||||
|
||||
.matter-operation {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.more-panel {
|
||||
border-top: 1px solid #eee;
|
||||
padding-left: 35px;
|
||||
|
||||
.info {
|
||||
}
|
||||
|
||||
.cell-btn {
|
||||
border-top: 1px solid #eee;
|
||||
line-height: @inner-cell-height;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,53 +0,0 @@
|
||||
<template>
|
||||
<div class="move-batch-panel h300">
|
||||
<FolderTree ref="folderTree" :matter="matter" :targetMatter="targetMatter" :userUuid="userUuid" :version="version"
|
||||
:callback="callback"
|
||||
:showSubFolderInit="true"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FolderTree from '../widget/FolderTree'
|
||||
import Matter from '../../../common/model/matter/Matter'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
//当前matter,这一级为 root.
|
||||
matter: new Matter(),
|
||||
//最终选择的那个matter
|
||||
targetMatter: new Matter()
|
||||
}
|
||||
},
|
||||
watch: {},
|
||||
props: {
|
||||
//寻找该用户的合适文件夹
|
||||
userUuid: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
//为了让Tree在每次点开的时候都更新
|
||||
version: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
//选择了一个文件夹后回掉,参数matter
|
||||
callback: {
|
||||
type: Function,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
components: {
|
||||
FolderTree
|
||||
},
|
||||
mounted() {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" rel="stylesheet/less">
|
||||
.move-batch-panel {
|
||||
overflow-y: scroll;
|
||||
}
|
||||
</style>
|
||||
@@ -1,120 +0,0 @@
|
||||
<template>
|
||||
<div class="widget-share-panel">
|
||||
|
||||
<div class="row" v-if="!share.uuid">
|
||||
<label class="col-md-4 control-label mt5">{{$t('matter.expire')}}</label>
|
||||
<div class="col-md-8">
|
||||
<select class="form-control" v-model="share.expireOption">
|
||||
<option v-for="item in ShareExpireOptionList" :value="item.value">{{$t(item.name)}}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="share.uuid">
|
||||
<ShareDialogPanel :share="share" :showSuccessHint="true"/>
|
||||
</div>
|
||||
|
||||
<div class="text-right mt10">
|
||||
|
||||
<button class="btn btn-primary btn-sm mr5" @click.stop.prevent="share.copyLinkAndCode()" v-if="share.uuid">
|
||||
{{$t('matter.copyLinkAndCode')}}
|
||||
</button>
|
||||
<button class="btn btn-primary btn-sm mr5" @click.stop.prevent="submit" v-if="!share.uuid">
|
||||
{{$t('matter.share')}}
|
||||
</button>
|
||||
|
||||
<button class="btn btn-default btn-sm mr5" @click.stop.prevent="close">
|
||||
{{$t('matter.close')}}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {ShareExpireOptionList} from "../../../common/model/share/ShareExpireOption";
|
||||
import Share from "../../../common/model/share/Share";
|
||||
import {currentHost} from "../../../common/util/Utils";
|
||||
import ShareDialogPanel from "../../share/widget/ShareDialogPanel"
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
ShareExpireOptionList,
|
||||
share: new Share()
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
matters(newVal, oldVal) {
|
||||
this.share.render(new Share())
|
||||
}
|
||||
},
|
||||
props: {
|
||||
matters: {
|
||||
type: Array,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
components: {
|
||||
ShareDialogPanel
|
||||
},
|
||||
methods: {
|
||||
|
||||
currentHost,
|
||||
submit() {
|
||||
|
||||
let that = this
|
||||
|
||||
let uuids = []
|
||||
|
||||
that.matters.forEach(function (item, index) {
|
||||
uuids.push(item.uuid)
|
||||
})
|
||||
|
||||
that.share.httpCreate(uuids, function (response) {
|
||||
|
||||
}, function (errorMessage, response) {
|
||||
that.$message.error(errorMessage)
|
||||
})
|
||||
|
||||
},
|
||||
copyText(text) {
|
||||
let that = this;
|
||||
that.$copyPlguin.copy(text, function () {
|
||||
that.$message.success({
|
||||
message: that.$t('operationSuccess'),
|
||||
center: true
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
close() {
|
||||
this.$emit("close")
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" rel="stylesheet/less">
|
||||
.widget-share-panel {
|
||||
|
||||
.share-block {
|
||||
|
||||
.share-icon {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.name {
|
||||
font-size: 18px;
|
||||
margin-left: 10px;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
@@ -1,90 +0,0 @@
|
||||
<template>
|
||||
<div class="upload-matter-panel">
|
||||
<NbExpanding>
|
||||
<div class="huge-block clearfix"
|
||||
v-if="matter.loading">
|
||||
<div class="media">
|
||||
<div class="pull-right">
|
||||
<i class="btn-action f16 fa fa-trash text-danger" v-if="false" @click.stop.prevent="del()"></i>
|
||||
</div>
|
||||
<div class="media-body">{{matter.file.name}}</div>
|
||||
</div>
|
||||
<div class="progress" :class="{'progress-striped active' : matter.loading}">
|
||||
<div :style="'width: '+(matter.progress*100)+'%'" class="progress-bar progress-bar-primary">
|
||||
<span>{{$t('matter.uploaded')}} {{(matter.progress * 100).toFixed(1)}}%</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
{{$t('matter.uploaded')}}:{{ (matter.file.size * matter.progress).toFixed(0) | humanFileSize }}/{{ matter.file.size |
|
||||
humanFileSize}}
|
||||
{{$t('matter.speed')}}:{{matter.speed | humanFileSize}}/s
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</NbExpanding>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import Matter from '../../../common/model/matter/Matter'
|
||||
import NbExpanding from "../../../common/widget/NbExpanding"
|
||||
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
components: {
|
||||
|
||||
NbExpanding
|
||||
},
|
||||
props: {
|
||||
matter: {
|
||||
type: Matter,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
del() {
|
||||
let that = this
|
||||
that.matter.clear()
|
||||
}
|
||||
},
|
||||
created() {
|
||||
},
|
||||
mounted() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style lang="less" rel="stylesheet/less">
|
||||
.upload-matter-panel {
|
||||
|
||||
.huge-block {
|
||||
background-color: white;
|
||||
border-radius: 5px;
|
||||
padding: 10px;
|
||||
border: 1px solid #eeeeee;
|
||||
margin-bottom: 10px;
|
||||
|
||||
.progress {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.media {
|
||||
margin-bottom: 5px;
|
||||
.media-body {
|
||||
cursor: pointer;
|
||||
color: #555;
|
||||
font-size: 15px;
|
||||
font-weight: bold;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
@@ -1,157 +0,0 @@
|
||||
<template>
|
||||
<div class="backyard-preference-edit animated fadeIn">
|
||||
|
||||
<div class="tank-box bg-white br4 p20 mt10">
|
||||
<div class="row" v-validator="preference.validatorSchema.name.error">
|
||||
<label class="col-md-2 control-label mt5 compulsory">
|
||||
{{$t('preference.websiteName')}}
|
||||
</label>
|
||||
<div class="col-md-10 validate">
|
||||
<input type="text" class="form-control" v-model="preference.name">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt10">
|
||||
<label class="col-md-2 control-label mt5">
|
||||
{{$t('preference.logo')}}
|
||||
</label>
|
||||
<div class="col-md-10">
|
||||
<MatterImage v-model="preference.logoUrl" :uploadHint="$t('preference.logoSquare')"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt10">
|
||||
<label class="col-md-2 control-label mt5">favicon</label>
|
||||
<div class="col-md-10">
|
||||
<MatterImage v-model="preference.faviconUrl" filter=".ico"
|
||||
:uploadHint="$t('preference.onlyAllowIco')"
|
||||
:previewWidth="60"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt10">
|
||||
<label class="col-md-2 control-label mt5">{{$t('preference.copyright')}}</label>
|
||||
<div class="col-md-10">
|
||||
<input type="text" class="form-control" v-model="preference.copyright">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt10">
|
||||
<label class="col-md-2 control-label mt5">{{$t('preference.extraInfo')}}</label>
|
||||
<div class="col-md-10">
|
||||
<input type="text" class="form-control" v-model="preference.record">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row mt10">
|
||||
<label class="col-md-2 control-label mt5">{{$t('preference.zipMaxNumLimit')}}</label>
|
||||
<div class="col-md-10">
|
||||
<input type="text" class="form-control" v-model="preference.downloadDirMaxNum">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row mt10">
|
||||
<label class="col-md-2 control-label mt5">{{$t('preference.zipMaxSizeLimit')}} </label>
|
||||
<div class="col-md-10">
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
<input type="number" class="form-control" v-model="preference.downloadDirMaxSize">
|
||||
</div>
|
||||
<div class="col-xs-6" style="line-height:30px;">
|
||||
{{$t('preference.current')}}:
|
||||
<span v-if="preference.downloadDirMaxSize < 0">{{$t('preference.noLimit')}}</span>
|
||||
<span v-else>{{preference.downloadDirMaxSize | humanFileSize}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="row mt10">
|
||||
<label class="col-md-2 control-label mt5">{{$t('preference.userDefaultSizeLimit')}}</label>
|
||||
<div class="col-md-10">
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
<input type="number" class="form-control" v-model="preference.defaultTotalSizeLimit">
|
||||
</div>
|
||||
<div class="col-xs-6" style="line-height:30px;">
|
||||
{{$t('preference.current')}}:
|
||||
<span v-if="preference.defaultTotalSizeLimit < 0">{{$t('preference.noLimit')}}</span>
|
||||
<span v-else>{{preference.defaultTotalSizeLimit | humanFileSize}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="row mt10">
|
||||
<label class="col-md-2 control-label mt5">{{$t('preference.allowRegister')}}</label>
|
||||
<div class="col-md-10">
|
||||
<NbSwitcher v-model="preference.allowRegister"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="row mt10">
|
||||
<div class="col-md-12">
|
||||
<div>
|
||||
<CreateSaveButton :entity="preference" :callback="save"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CreateSaveButton from '../widget/CreateSaveButton'
|
||||
import MatterImage from '../matter/widget/MatterImage'
|
||||
import Preference from '../../common/model/preference/Preference'
|
||||
import NbSwitcher from "../../common/widget/NbSwitcher"
|
||||
|
||||
export default {
|
||||
name: 'edit',
|
||||
data() {
|
||||
return {
|
||||
globalPreference: this.$store.state.preference,
|
||||
preference: new Preference()
|
||||
}
|
||||
},
|
||||
components: {
|
||||
MatterImage,
|
||||
CreateSaveButton,
|
||||
NbSwitcher
|
||||
},
|
||||
methods: {
|
||||
save() {
|
||||
let that = this;
|
||||
this.preference.httpSave(function (response) {
|
||||
|
||||
that.$message.success({
|
||||
message: that.$t('operationSuccess')
|
||||
});
|
||||
|
||||
that.globalPreference.render(response.data.data);
|
||||
|
||||
that.preference.updateTitleAndFavicon();
|
||||
|
||||
that.$router.go(-1);
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
let that = this;
|
||||
//为了让按钮的文字显示为“保存”
|
||||
this.preference.editMode = true
|
||||
this.preference.httpFetch()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" rel="stylesheet/less">
|
||||
|
||||
</style>
|
||||
@@ -1,150 +0,0 @@
|
||||
<template>
|
||||
<div class="backyard-preference">
|
||||
|
||||
<div class="preference-block tank-box">
|
||||
<div class="row">
|
||||
<div class="col-md-12 form-info">
|
||||
<span>{{$t('preference.websiteName')}}: </span>
|
||||
<span class="bold">{{preference.name}}</span>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12 form-info">
|
||||
<span>{{$t('preference.logo')}}: </span>
|
||||
<span>
|
||||
<img v-if="preference.logoUrl" :src="preference.logoUrl" alt="logo" class="max-height-100">
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12 form-info">
|
||||
<span>favicon: </span>
|
||||
<span>
|
||||
<img v-if="preference.faviconUrl" :src="preference.faviconUrl" alt="favicon" class="max-height-100">
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12 form-info">
|
||||
<span>{{$t('preference.copyright')}}: </span>
|
||||
<span v-html="preference.copyright"></span>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12 form-info">
|
||||
<span>{{$t('preference.extraInfo')}}: </span>
|
||||
<span v-html="preference.record"></span>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12 form-info">
|
||||
<span>{{$t('preference.zipMaxNumLimit')}}: </span>
|
||||
<span v-html="preference.downloadDirMaxNum"></span>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12 form-info">
|
||||
<span>{{$t('preference.allowRegister')}}: </span>
|
||||
<span>{{preference.allowRegister?$t('yes'):$t('no')}}</span>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12 form-info">
|
||||
<span>{{$t('preference.zipMaxSizeLimit')}}: </span>
|
||||
<span>
|
||||
<span class="mr10">
|
||||
<span v-if="preference.downloadDirMaxSize >= 0">
|
||||
{{preference.downloadDirMaxSize | humanFileSize}}
|
||||
</span>
|
||||
<span v-else>
|
||||
{{$t('preference.noLimit')}}
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12 form-info">
|
||||
<span>{{$t('preference.userDefaultSizeLimit')}}: </span>
|
||||
<span>
|
||||
<span class="mr10">
|
||||
<span v-if="preference.defaultTotalSizeLimit >= 0">
|
||||
{{preference.defaultTotalSizeLimit | humanFileSize}}
|
||||
</span>
|
||||
<span v-else>
|
||||
{{$t('preference.noLimit')}}
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12 form-info">
|
||||
<span>{{$t('preference.docLink')}}: </span>
|
||||
<span>
|
||||
<a :href="$t('preference.tankDocLink')" target="_blank">{{$t('preference.tankDocLink')}}</a>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="text-right">
|
||||
<button class="btn btn-sm btn-danger mr5"
|
||||
@click.stop.prevent="systemCleanup"
|
||||
:title="$t('preference.systemCleanupDescription')">
|
||||
<i class="fa fa-warning"></i>
|
||||
{{$t('preference.systemCleanup')}}
|
||||
</button>
|
||||
<router-link class="btn btn-sm btn-primary mr5" to="/preference/edit">
|
||||
<i class="fa fa-pencil"></i>
|
||||
{{$t('edit')}}
|
||||
</router-link>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NbSwitcher from "../../common/widget/NbSwitcher"
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
preference: this.$store.state.preference
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
systemCleanup() {
|
||||
|
||||
let that = this
|
||||
let preference = this.preference
|
||||
|
||||
this.$prompt(that.$t("preference.systemCleanupPrompt"), that.$t("prompt"), {
|
||||
inputValue: null,
|
||||
confirmButtonText: that.$t("confirm"),
|
||||
cancelButtonText: that.$t("cancel"),
|
||||
inputPattern: /^.{1,45}$/,
|
||||
inputErrorMessage: that.$t("required")
|
||||
}).then(({value}) => {
|
||||
|
||||
preference.httpSystemCleanup(value, function () {
|
||||
that.$message.success(that.$t("operationSuccess"));
|
||||
})
|
||||
}).catch(() => {
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
},
|
||||
components: {
|
||||
NbSwitcher
|
||||
},
|
||||
mounted() {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" rel="stylesheet/less">
|
||||
.backyard-preference {
|
||||
.max-height-100 {
|
||||
max-height: 100px;
|
||||
}
|
||||
|
||||
.preference-block {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||