Merge branch 'dev'

This commit is contained in:
zicla
2018-01-01 18:42:53 +08:00
58 changed files with 1402 additions and 12332 deletions
+21
View File
@@ -0,0 +1,21 @@
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.
+36 -4
View File
@@ -1,15 +1,47 @@
# 蓝眼云盘前端项目
![蓝眼云盘logo](https://raw.githubusercontent.com/eyebluecn/tank/dev/build/doc/logo.png)
### [配套后端`tank`](https://github.com/eyebluecn/tank)
# 蓝眼云盘前端
##### [在线Demo](http://tank.eyeblue.cn) (体验账号: demo@tank.eyeblue.cn 密码:123456)
##### [配套后端tank](https://github.com/eyebluecn/tank)
### [在线体验](http://tank.zicpo.cn)
### 简介
蓝眼云盘是 [蓝眼系列开源软件](https://github.com/eyebluecn) 中的第一个
- 主要用于快速搭建私人云盘,可以简单理解为部署在自己服务器上的[百度云盘](https://pan.baidu.com/)。
- 蓝眼云盘提供了编程接口,可以使用接口上传文件,作为其他网站、系统、app的资源存储器,可以当作单机版的[七牛云](https://www.qiniu.com)或[阿里云OSS](https://www.aliyun.com/product/oss)使用。
蓝眼云盘可以作为团队内部或个人私有的云盘使用,亦可当作专门处理图片,音频,视频等二进制文件的第三方编程辅助工具。
如果您觉得蓝眼云盘对您有帮助,请不要吝惜您的star :smile:
### 运行
```
npm install
> 详细文档正在撰写中,敬请期待...
npm run dev
```
如果你有自己的tank后端,也可以在`config/index.js``proxyTable.target`修改为自己tank所在地址
### 打包
```
npm run build
```
打包的结果在`dist`文件夹下,将该文件夹下的内容放置在[后端tank](https://github.com/eyebluecn/tank)的`build/html`文件夹下即可。
#### 更多详细配置请参考[后端说明](https://github.com/eyebluecn/tank)
### Contribution
感谢所有蓝眼云盘的贡献者 [@zicla](https://github.com/zicla)[@seaheart](https://github.com/seaheart)@heying[@hxsherry](https://github.com/hxsherry)
如果您也想参与进来,请尽情的fork, star, post issue, pull requests
### License
[MIT](http://opensource.org/licenses/MIT)
Copyright (c) 2017-present, eyeblue.cn
+2 -1
View File
@@ -33,7 +33,8 @@ module.exports = {
assetsPublicPath: '/',
proxyTable: {
'/api': {
target: 'http://tank.zicpo.cn',
target: 'http://tank.eyeblue.cn',
//target: 'http://localhost:6010',
changeOrigin: true,
pathRewrite: {
'^/api': '/api'
+54 -56
View File
@@ -1,18 +1,17 @@
<template>
<div class="nb-app">
<div class="nb-app">
<NprogressContainer/>
<router-view/>
<NprogressContainer/>
<router-view/>
</div>
</div>
</template>
<script>
import NprogressContainer from 'vue-nprogress/src/NprogressContainer'
export default {
data() {
data () {
return {
preference: this.$store.state.preference
}
@@ -21,12 +20,11 @@
components: {
NprogressContainer
},
mounted() {
mounted () {
let that = this;
let that = this
this.preference.httpFetch()
}
}
</script>
@@ -34,61 +32,61 @@
<style lang="less" rel="stylesheet/less">
@import "~font-awesome/css/font-awesome.css";
@import "./assets/css/app.less";
@import "~font-awesome/css/font-awesome.css";
@import "./assets/css/app.less";
.nb-app {
.nb-app {
height: 100%;
height: 100%;
.nprogress-container {
position: fixed !important;
width: 100%;
height: 150px;
z-index: 2048;
pointer-events: none;
.nprogress-container {
position: fixed !important;
width: 100%;
height: 150px;
z-index: 2048;
pointer-events: none;
#nprogress {
//@color: #48e79a;
@color: #1ab394;
#nprogress {
//@color: #48e79a;
@color: #1ab394;
.bar {
background: @color;
}
.peg {
box-shadow: 0 0 10px @color, 0 0 5px @color;
}
.bar {
background: @color;
}
.peg {
box-shadow: 0 0 10px @color, 0 0 5px @color;
}
.spinner-icon {
border-top-color: @color;
border-left-color: @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
}
//所有的滚动条样式
::-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>
+343 -86
View File
@@ -1,102 +1,359 @@
@import "../inspinia/variables.less";
@import "./variables.less";
.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-primary {
background-color: @brand-primary;
color: white;
}
.bg-success {
background-color: @brand-success;
color: white;
}
.text-primary{ color:@brand-primary; }
.bg-info {
background-color: @brand-info;
color: white;
}
.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-black { background-color: #111111;}
.bg-warning {
background-color: @brand-warning;
color: white;
}
.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-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;
}
.bg-silver-white {
background-color: #EEEEEE;
}
.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
}
/* Colors */
.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;}
.navy {
color: #001F3F;
}
.blue {
color: #0074D9;
}
.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}
.aqua {
color: #7FDBFF;
}
.teal {
color: #39CCCC;
}
.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;}
.olive {
color: #3D9970;
}
.color-light-active{ color: #ffc60c;}
.color-light-inactive{ color:#ccc;}
.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;
}
.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;
}
+3
View File
@@ -8,4 +8,7 @@
//上方导航栏高度
@frame-header-height: 80px;
//下方蓝眼博客高度
@power-footer-height: 40px;
+6
View File
@@ -1197,6 +1197,12 @@ table.table-mail tr td {
height: 96px;
}
.img-blg {
width: 150px;
height: 150px;
}
// BORDER RADIUS
.b-r-xs {
+5 -3
View File
@@ -32,7 +32,7 @@
<TopNavigation/>
</div>
<BottomNavigation />
</div>
</div>
@@ -43,6 +43,7 @@
import {Notification} from 'element-ui'
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 {
@@ -58,7 +59,8 @@
},
components: {
SideNavigation,
TopNavigation
TopNavigation,
BottomNavigation
},
methods: {
blankClick() {
@@ -101,7 +103,7 @@
left: @sidebar-width;
top: @top-navigation-height;
right: 0;
bottom: 0;
bottom: @power-footer-height;
overflow-y: auto;
overflow-x: hidden;
+61
View File
@@ -0,0 +1,61 @@
<template>
<div class="bottom-navigation text-center">
<span class="mr10">
<span v-html="preference.footerLine1"></span>
</span>
<span class="mr10">
<span v-html="preference.footerLine2"></span>
</span>
<!-- 版本号cn.eyeblue.tank:1.0.0 -->
<!-- 开源不易请不要移除掉这里的代码蓝眼云盘谢谢您 ^_^ -->
<span>
Powered by <a target="_blank" href="https://github.com/eyebluecn/tank"><img class="w30" src="../../assets/img/logo.png"/> 蓝眼云盘</a>
</span>
</div>
</template>
<script>
export default {
name: 'bottom-navigation',
data(){
return{
preference: this.$store.state.preference
}
}
}
</script>
<style lang="less" rel="stylesheet/less">
@import "../../assets/css/global/variables";
.bottom-navigation{
position: fixed;
height: @power-footer-height;
line-height: @power-footer-height;
bottom: 0;
right: 0;
left: @sidebar-width;
padding: 0 20px;
border-top: 1px solid #eee;
//大屏幕
@media (min-width: @screen-sm-min) {
left: @sidebar-width;
}
//小屏幕
@media (max-width: @screen-xs-max) {
left: 0;
}
&.show-drawer {
//大屏幕
@media (min-width: @screen-sm-min) {
left: @sidebar-width;
}
//小屏幕
@media (max-width: @screen-xs-max) {
left: 0;
}
}
}
</style>
+2 -3
View File
@@ -5,7 +5,7 @@
<div class="menu-header" @click="goToProfile">
<div class="logo-area">
<img alt="image" class="img-circle w80" :src="user.getAvatarUrl()"/>
<img alt="image" class="img-circle w80" :src="user.avatarUrl ? user.getAvatarUrl() + '?imageProcess=resize&imageResizeM=fill&imageResizeW=100&imageResizeH=100' : user.getAvatarUrl()"/>
</div>
<div class="text-area">
<div class="nickname">
@@ -54,7 +54,7 @@
if (this.user.role === 'GUEST') {
this.$router.push("/user/login");
} else {
this.$router.push("/user/profile/" + this.user.uuid);
this.$router.push("/user/detail/" + this.user.uuid);
}
@@ -79,7 +79,6 @@
},
mounted() {
let that = this;
this.updateBody();
}
}
+5 -3
View File
@@ -26,8 +26,6 @@
let defaultLogoPath = require("../../assets/img/logo.png");
console.log("defaultLogoPath:")
console.log(defaultLogoPath)
export default {
data() {
return {
@@ -39,7 +37,7 @@
//logo可以使用自定义的。
logoUrl() {
if (this.preference.logoUrl) {
return this.preference.logoUrl
return this.preference.logoUrl + '?imageProcess=resize&imageResizeM=fill&imageResizeW=100&imageResizeH=100'
} else {
return defaultLogoPath
}
@@ -68,6 +66,10 @@
z-index: 10;
padding-left: @sidebar-width;
.navbar {
border: none;
}
//手机屏幕
@media (max-width: @screen-xs-max) {
padding-left: 0;
+61 -10
View File
@@ -7,11 +7,14 @@
<div>
<NbFilter :pager="pager" :callback="search">
<button class="btn btn-primary btn-sm" v-if="temporaryMatterUuids.length !== pager.data.length" @click.stop.prevent="checkAll">
<button class="btn btn-primary btn-sm" v-if="temporaryMatterUuids.length !== pager.data.length"
@click.stop.prevent="checkAll">
<i class="fa fa-check-square"></i>
全选
</button>
<button class="btn btn-primary btn-sm" v-if="pager.data.length && temporaryMatterUuids.length === pager.data.length" @click.stop.prevent="checkNone">
<button class="btn btn-primary btn-sm"
v-if="pager.data.length && temporaryMatterUuids.length === pager.data.length"
@click.stop.prevent="checkNone">
<i class="fa fa-square-o"></i>
取消全选
</button>
@@ -19,6 +22,11 @@
<i class="fa fa-trash"></i>
删除
</button>
<button class="btn btn-primary btn-sm" v-if="temporaryMatterUuids.length"
@click.stop.prevent="moveBatch($createElement)">
<i class="fa fa-arrows"></i>
移动
</button>
<span class="btn btn-primary btn-sm btn-file">
<slot name="button">
@@ -62,7 +70,7 @@
<script>
import MatterPanel from './widget/MatterPanel'
import UploadMatterPanel from './widget/UploadMatterPanel'
import MoveBatchPanel from './widget/MoveBatchPanel'
import NbSlidePanel from '../../common/widget/NbSlidePanel.vue'
import NbExpanding from '../../common/widget/NbExpanding.vue'
import NbCheckbox from '../../common/widget/NbCheckbox.vue'
@@ -80,6 +88,8 @@
matter: new Matter(),
//准备新建的文件。
newMatter: new Matter(),
//目标文件夹,用于移动操作
targetMatter: new Matter(),
//准备上传的一系列文件
uploadMatters: [],
//临时暂存区,用于文件的相关操作
@@ -88,12 +98,14 @@
user: this.$store.state.user,
breadcrumbs: this.$store.state.breadcrumbs,
director: new Director()
}
},
components: {
NbCheckbox,
MatterPanel,
UploadMatterPanel,
MoveBatchPanel,
NbCheckbox,
NbFilter,
NbPager,
NbSlidePanel,
@@ -125,8 +137,8 @@
let that = this
//清空暂存区
this.temporaryMatterUuids.splice(0,this.temporaryMatterUuids.length)
//清空暂存区
this.temporaryMatterUuids.splice(0, this.temporaryMatterUuids.length)
let uuid = that.pager.getFilterValue('puuid')
@@ -240,8 +252,8 @@
}
return true
},
//批量删除
deleteBatch(){
//批量删除
deleteBatch () {
let that = this
MessageBox.confirm('此操作将永久删除这些文件, 是否继续?', '提示', {
confirmButtonText: '确定',
@@ -250,7 +262,7 @@
callback: function (action, instance) {
if (action === 'confirm') {
let uuids = that.temporaryMatterUuids.join(',')
that.matter.httpDeleteBatch(uuids,function (response) {
that.matter.httpDeleteBatch(uuids, function (response) {
Message.success('删除成功!')
that.refresh()
})
@@ -258,7 +270,35 @@
}
})
},
//批量移动
moveBatch (createElement) {
let that = this
let newMatter = new Matter()
let dom = createElement(MoveBatchPanel, {
props: {
targetMatter: this.targetMatter
}
})
MessageBox({
title: '移动到',
message: dom,
customClass: 'wp50',
confirmButtonText: '确定',
showCancelButton: true,
cancelButtonText: '关闭',
callback: (action, instance) => {
if (action === 'confirm') {
let uuids = that.temporaryMatterUuids.join(',')
that.matter.httpMove(uuids, this.targetMatter.uuid, function (response) {
Message.success('移动成功!')
that.targetMatter.render(new Matter())
that.refresh()
})
}
}
})
}
},
watch: {
@@ -277,7 +317,12 @@
},
created () {
/*初始化inputSelection*/
if (this.user.role === 'ADMINISTRATOR') {
this.pager.getFilter('userUuid').visible = true
} else {
this.pager.setFilterValue('userUuid', this.user.uuid)
}
},
mounted () {
@@ -291,11 +336,17 @@
this.pager.setFilterValue('puuid', 'root')
}
//如果所有的排序都没有设置,那么默认以时间降序。
if (!this.pager.getFilterValue('orderDir') && !this.pager.getFilterValue('orderCreateTime') && !this.pager.getFilterValue('orderSize') && !this.pager.getFilterValue('orderName')) {
this.pager.setFilterValue('orderCreateTime', 'DESC')
}
//如果没有设置用户的话,那么默认显示当前登录用户的资料
if (!this.pager.getFilterValue('userUuid')) {
this.pager.setFilterValue('userUuid', this.user.uuid)
}
this.refresh()
}
+102
View File
@@ -0,0 +1,102 @@
<template>
<div class="folder-tree">
<div class="h50 cursor folder-block" :class="{'bg-silver-white': targetMatter.uuid === matter.uuid}" @click.stop.prevent="deepFolderToggle">
<span class="fa fa-chevron-down mr5 w14" v-if="pager.data.length && deepFolder"></span>
<span class="fa fa-chevron-right mr5 w14" v-if="pager.data.length && !deepFolder"></span>
<span :class="{ 'ml23': !pager.data.length }">
<span v-if="matter.uuid">
<img :src="matter.getIcon()" class="mr5" alt="文件夹" width="22" />
<span>{{matter.name}}</span>
</span>
<span v-else>
<span>全部文件</span>
</span>
</span>
</div>
<NbExpanding>
<div v-if="pager.data.length && deepFolder" class="pl20">
<div v-for="(child, index) in pager.data">
<FolderTree :matter="child" :targetMatter="targetMatter"></FolderTree>
</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'
export default {
name: 'FolderTree',
data(){
return{
deepFolder: false,
pager: new Pager(Matter)
}
},
props:{
targetMatter: {
type: Matter,
required: true
},
matter: {
type: Matter,
required: true
},
deepFolderInit:{
type: Boolean,
required: false,
default: false
}
},
methods:{
deepFolderToggle () {
this.deepFolder = !this.deepFolder
if(this.targetMatter.uuid !== this.matter.uuid){
this.targetMatter.render(this.matter)
}
}
},
components:{
NbExpanding
},
mounted() {
if (!this.matter.uuid) {
this.pager.setFilterValue('puuid', 'root')
} else {
this.pager.setFilterValue('puuid', this.matter.uuid)
}
if(this.deepFolderInit){
this.deepFolder = true
}
this.pager.setFilterValue('dir', true)
this.pager.httpFastPage()
}
}
</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>
+127
View File
@@ -0,0 +1,127 @@
<template>
<div class="nb-matter-image">
<div class="tiny-block">
<div class="w200 p10 mb10 bg-white br5 border" v-show="preview && value">
<img class="wp100" :src="value"/>
</div>
</div>
<div>
<span class="btn btn-primary btn-sm btn-file">
<slot name="button">
<i class="fa fa-cloud-upload"></i>
<span>{{value?'重新上传':'上传图片'}}</span>
</slot>
<input ref="refFile" type="file" @change.prevent.stop="triggerUpload"/>
</span>
<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 NbExpanding from "../../../common/widget/NbExpanding"
import UploadMatterPanel from "./UploadMatterPanel"
import Vue from "vue"
import $ from "jquery"
import Director from "./Director";
import {Message, MessageBox, Notification} from 'element-ui'
import {setInputSelection} from "../../../common/util/Utils";
export default {
data() {
return {
user: this.$store.state.user,
matter: new Matter()
}
},
components: {
UploadMatterPanel,
NbExpanding
},
props: {
preview: {
//上传的照片是否需要预览
type: Boolean,
required: false,
'default': true
},
//图片的url.
value: {
type: String | null,
required: true
},
//filter.
filter: {
type: String,
required: false,
"default": "image"
},
maxSize: {
type: Number,
required: false,
"default": 1024 * 1024
},
uploadHint: {
type: String,
required: false,
"default": "图片最大不超过1M"
}
},
methods: {
del() {
let that = this
that.matter.clear()
},
triggerUpload() {
let that = this
let matter = that.matter;
matter.maxSize = that.maxSize
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]
matter.httpUpload(function () {
that.$emit("input", matter.getDownloadUrl())
})
}
},
created() {
},
mounted() {
}
}
</script>
<style lang="less" rel="stylesheet/less">
.nb-matter-image {
}
</style>
+98 -87
View File
@@ -1,13 +1,13 @@
<template>
<div class="widget-matter-panel clearfix" @click.stop.prevent="clickRow">
<div class="left-part">
<div class="widget-matter-panel clearfix" @click.stop.prevent="clickRow">
<div class="left-part">
<span>
<NbCheckbox v-model="matter.check"/>
</span>
<span>
<span>
<img class="matter-icon" :src="matter.getIcon()"/>
</span>
<span class="matter-name-edit" v-if="matter.editMode">
<span class="matter-name-edit" v-if="matter.editMode">
<input ref="editInput" class="form-control"
:class="matter.uuid"
@@ -16,34 +16,38 @@
@blur="blurTrigger()"
v-on:keyup.13="enterTrigger()"/>
</span>
<span class="matter-name" v-else>
{{matter.name}}
<span class="matter-name" :class="{'alien':matter.alien}" v-else>
{{matter.name}} <i class="fa fa-unlock" v-if="!matter.dir && !matter.privacy" title="公有文件,任何人可以访问"></i>
</span>
</div>
<div class="right-part" v-if="matter.uuid">
</div>
<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="设置为公有文件" @click.stop.prevent="matter.httpChangePrivacy(false)"></i>
<i class="fa fa-unlock btn-action text-primary" v-if="!matter.dir && !matter.privacy" title="设置为私有文件" @click.stop.prevent="matter.httpChangePrivacy(true)"></i>
<i class="fa fa-pencil btn-action text-primary" title="重命名" @click.stop.prevent="prepareRename"></i>
<i class="fa fa-download btn-action text-primary" title="下载" v-if="!matter.dir"
@click.stop.prevent="download"></i>
<i class="fa fa-trash btn-action text-danger" title="删除" @click.stop.prevent="deleteMatter"></i>
</span>
<span class="matter-size" v-if="matter.dir">
<span class="matter-size" v-if="matter.dir">
-
</span>
<span class="matter-size" v-else>
<span class="matter-size" v-else>
{{matter.size | humanFileSize}}
</span>
<span class="matter-date">
<span class="matter-date">
{{matter.modifyTime | simpleDateHourMinute}}
</span>
</div>
</div>
</div>
</div>
</template>
<script>
import Matter from '../../../common/model/matter/Matter'
@@ -51,11 +55,11 @@
import Vue from 'vue'
import $ from 'jquery'
import Director from './Director'
import { Message, MessageBox, Notification } from 'element-ui'
import { setInputSelection } from '../../../common/util/Utils'
import {Message, MessageBox, Notification} from 'element-ui'
import {setInputSelection} from '../../../common/util/Utils'
export default {
data () {
data() {
return {
//正在向服务器提交rename的请求
renamingLoading: false
@@ -76,12 +80,12 @@
},
watch: {
'matter.check' (newVal, oldVal) {
'matter.check'(newVal, oldVal) {
this.$emit('checkMatter', {matterUuid: this.matter.uuid, checkStatus: newVal})
}
},
methods: {
clickRow () {
clickRow() {
let that = this
if (this.director.isEditing()) {
@@ -96,15 +100,15 @@
}
},
download () {
download() {
if (this.director.isEditing()) {
console.log('导演正忙着,不予执行')
return
}
window.open(Vue.http.options.root + '/alien/download/' + this.matter.uuid + '/' + this.matter.name)
window.open(this.matter.getDownloadUrl())
},
deleteMatter () {
deleteMatter() {
let that = this
MessageBox.confirm('此操作将永久删除该文件, 是否继续?', '提示', {
confirmButtonText: '确定',
@@ -121,7 +125,7 @@
}
})
},
prepareRename () {
prepareRename() {
let that = this
if (this.director.isEditing()) {
@@ -144,7 +148,7 @@
}, 100)
},
finishRename () {
finishRename() {
let that = this
//有可能按enter的时候和blur同时了。
if (that.renamingLoading) {
@@ -168,7 +172,7 @@
})
},
finishCreateDirectory () {
finishCreateDirectory() {
let that = this
that.matter.httpCreateDirectory(function () {
that.director.createMode = false
@@ -182,7 +186,7 @@
Message.error(response.data.msg)
})
},
blurTrigger () {
blurTrigger() {
let that = this
if (that.matter.editMode) {
if (that.director.createMode) {
@@ -192,91 +196,98 @@
}
}
},
enterTrigger () {
enterTrigger() {
$(this.$refs.editInput).blur()
},
highLight () {
highLight() {
$(this.$refs.editInput).select()
}
},
created () {
created() {
},
mounted () {
mounted() {
}
}
</script>
<style lang="less" rel="stylesheet/less">
.widget-matter-panel {
border-top: 1px solid #eee;
background-color: white;
@import "../../../assets/css/global/variables";
@base-height: 48px;
padding-left: 10px;
.widget-matter-panel {
.left-part, .right-part {
height: @base-height;
display: inline-block;
> span {
display: inline-block;
vertical-align: middle;
line-height: @base-height;
margin-right: 10px;
}
}
border-top: 1px solid #eee;
background-color: white;
.left-part {
@base-height: 48px;
padding-left: 10px;
.matter-icon {
width: 24px;
}
.matter-name-edit {
input {
width: 200px;
height: 26px;
display: inline-block;
padding: 6px;
}
}
.matter-name {
}
}
.right-part {
float: right;
.left-part, .right-part {
height: @base-height;
display: inline-block;
> span {
display: inline-block;
vertical-align: middle;
line-height: @base-height;
margin-right: 10px;
}
}
.matter-operation {
visibility: hidden;
i {
font-size: 16px;
margin-right: 5px;
.left-part {
&:hover {
.matter-icon {
width: 24px;
}
.matter-name-edit {
input {
width: 200px;
height: 26px;
display: inline-block;
padding: 6px;
}
}
.matter-name {
}
}
}
&.alien {
color: @brand-primary;
}
}
}
.right-part {
float: right;
.matter-size {
display: inline-block;
width: 80px;
text-align: left;
margin-left: 20px;
}
.matter-date {
.matter-operation {
visibility: hidden;
i {
font-size: 16px;
margin-right: 5px;
}
}
&:hover {
&:hover {
background-color: aliceblue;
cursor: pointer;
}
}
}
.matter-operation {
visibility: visible;
}
}
.matter-size {
display: inline-block;
width: 80px;
text-align: left;
margin-left: 20px;
}
.matter-date {
}
}
}
&:hover {
background-color: aliceblue;
cursor: pointer;
.matter-operation {
visibility: visible;
}
}
}
</style>
@@ -0,0 +1,38 @@
<template>
<div class="move-batch-panel h300">
<FolderTree :matter="matter" :targetMatter="targetMatter" :deepFolderInit="true"/>
</div>
</template>
<script>
import FolderTree from '../widget/FolderTree'
import Matter from '../../../common/model/matter/Matter'
export default {
name: 'move-batch-panel',
data(){
return{
//当前matter
matter: new Matter()
}
},
props:{
targetMatter:{
type: Matter,
required: true
}
},
components:{
FolderTree
},
mounted(){
}
}
</script>
<style lang="less" rel="stylesheet/less">
.move-batch-panel{
overflow-y: scroll;
}
</style>
-27
View File
@@ -1,27 +0,0 @@
<template>
<div class="matter-all-word">
<TypeMatterComponent :matterType="matterType"></TypeMatterComponent>
</div>
</template>
<script>
import TypeMatterComponent from '../components/TypeMatterComponent.vue'
export default {
data(){
return{
matterType:'WORD'
}
},
components:{
TypeMatterComponent
},
mounted(){
}
}
</script>
<style lang="less" rel="stylesheet/less">
.matter-all-word{
}
</style>
+74 -51
View File
@@ -1,80 +1,103 @@
<template>
<div class="backyard-preference-edit animated fadeIn">
<div class="row">
<div class="col-md-12">
<div class="pedia-navigation">
<div class="backyard-preference-edit animated fadeIn">
<div class="row">
<div class="col-md-12">
<div class="pedia-navigation">
<span class="item active">
偏好设置
</span>
</div>
</div>
</div>
<div class="bg-white br4 p20 mt10">
<div class="row" v-validator="preference.validatorSchema.name.error">
<label class="col-md-2 control-label mt5 compulsory">名称</label>
<div class="col-md-10 validate">
<input type="text" class="form-control" v-model="preference.name">
</div>
</div>
</div>
</div>
</div>
<div class="bg-white br4 p20 mt10">
<div class="row" v-validator="preference.validatorSchema.name.error">
<label class="col-md-2 control-label mt5 compulsory">名称</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">logo</label>
<div class="col-md-10">
<NbTank :tank="preference.logoTank"/>
</div>
</div>
<div class="row mt10">
<label class="col-md-2 control-label mt5">云盘logo</label>
<div class="col-md-10">
<MatterImage v-model="preference.logoUrl" uploadHint="logo请使用正方形图片,否则在显示时会裁剪成正方形"/>
</div>
</div>
<div class="row mt10" v-if="preference.faviconTank">
<label class="col-md-2 control-label mt5">favicon</label>
<div class="col-md-10">
<NbTank :tank="preference.faviconTank"/>
</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="只允许上传.ico图标"/>
</div>
</div>
<div class="row mt10">
<div class="col-md-12">
<div>
<CreateSaveButton :entity="preference" :callback="save"/>
</div>
</div>
</div>
<div class="row mt10">
<label class="col-md-2 control-label mt5">底部第一行文字(可使用html)</label>
<div class="col-md-10">
<input type="text" class="form-control" v-model="preference.footerLine1">
</div>
</div>
</div>
</div>
<div class="row mt10">
<label class="col-md-2 control-label mt5">底部第二行文字(可使用html)</label>
<div class="col-md-10">
<input type="text" class="form-control" v-model="preference.footerLine2">
</div>
</div>
<div class="row mt10">
<div class="col-md-12">
<div>
<CreateSaveButton :entity="preference" :callback="save"/>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import NbTank from '../../common/widget/NbTank'
import CreateSaveButton from '../widget/CreateSaveButton'
import MatterImage from '../matter/widget/MatterImage'
import Preference from '../../common/model/preference/Preference'
import { Notification } from 'element-ui'
import {Notification} from 'element-ui'
export default {
name: 'edit',
data(){
return{
preference: this.$store.state.preference
data() {
return {
currentPreference: this.$store.state.preference,
preference: new Preference()
}
},
components:{
NbTank,
},
components: {
MatterImage,
CreateSaveButton
},
methods:{
save(){
},
methods: {
save() {
let that = this
this.preference.httpSave(function (response) {
this.preference.httpSave(function (response) {
Notification.success({
message: '修改偏好成功!'
})
that.currentPreference.render(response.data.data)
that.preference.updateTitleAndFavicon()
that.$router.go(-1)
})
}
},
mounted(){
}
},
mounted() {
let that = this
this.preference.httpFetch(function () {
that.preference.editMode = true
})
}
}
</script>
+24 -6
View File
@@ -15,7 +15,7 @@
</div>
<div class="mt10 bg-white br4 border">
<div class="row p10 border-bottom">
<div class="col-md-2 col-sm-2 col-xs-4">
<div class="col-md-2 col-sm-2 col-xs-4 bold">
网站名称
</div>
<div class="col-md-10 col-sm-10 col-xs-8">
@@ -24,20 +24,38 @@
</div>
<div class="row p10 border-bottom">
<div class="col-md-2 col-sm-2 col-xs-4">
<div class="col-md-2 col-sm-2 col-xs-4 bold">
logo
</div>
<div class="col-md-10 col-sm-10 col-xs-8">
<img :src="preference.logoUrl" alt="logo" class="tankImg">
<img v-if="preference.logoUrl" :src="preference.logoUrl" alt="logo" class="tankImg">
</div>
</div>
<div class="row p10 border-bottom">
<div class="col-md-2 col-sm-2 col-xs-4">
<div class="col-md-2 col-sm-2 col-xs-4 bold">
favicon
</div>
<div class="col-md-10 col-sm-10 col-xs-8">
<img :src="preference.faviconUrl" alt="favicon" class="tankImg">
<img v-if="preference.faviconUrl" :src="preference.faviconUrl" alt="favicon" class="tankImg">
</div>
</div>
<div class="row p10 border-bottom">
<div class="col-md-2 col-sm-2 col-xs-4 bold">
底部第一行文字
</div>
<div class="col-md-10 col-sm-10 col-xs-8">
{{preference.footerLine1}}
</div>
</div>
<div class="row p10 border-bottom">
<div class="col-md-2 col-sm-2 col-xs-4 bold">
底部第二行文字
</div>
<div class="col-md-10 col-sm-10 col-xs-8">
<span v-html="preference.footerLine2"></span>
</div>
</div>
@@ -66,7 +84,7 @@
<style lang="less" rel="stylesheet/less">
.backyard-preference{
.tankImg{
max-height: 100px
max-height: 100px;
}
}
</style>
-87
View File
@@ -1,87 +0,0 @@
<template>
<div class="animated fadeIn">
<div class="row">
<div class="col-md-12">
<div class="pedia-navigation">
<span class="item active">
<span v-show="!tag.editMode">新建标签</span>
<span v-show="tag.editMode">编辑标签</span>
</span>
</div>
</div>
</div>
<div class="bg-white br4 p20 mt10">
<div class="row" v-validator="tag.validatorSchema.name.error">
<label class="col-md-2 control-label mt5 compulsory">标签名称</label>
<div class="col-md-10 validate">
<input type="text" class="form-control" v-model="tag.name">
</div>
</div>
<div class="row mt10">
<label class="col-md-2 control-label mt5">标签logo</label>
<div class="col-md-10">
<NbTank :tank="tag.logoTank"/>
</div>
</div>
<div class="row mt10">
<div class="col-md-12">
<div>
<CreateSaveButton :entity="tag" :callback="save"/>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { Notification, MessageBox, DatePicker } from 'element-ui'
import Tag from '../../common/model/tag/Tag'
import NbTank from '../../common/widget/NbTank'
import CreateSaveButton from '../widget/CreateSaveButton'
export default {
name: 'create',
data () {
return {
user: this.$store.state.user,
tag: new Tag()
}
},
components: {
NbTank,
CreateSaveButton
},
methods: {
save () {
let that = this
this.tag.errorMessage = null
this.tag.httpSave(function (response) {
Notification.success({
message: that.tag.editMode ? '修改标签成功!' : '创建标签成功!'
})
that.$router.go(-1)
})
}
},
mounted () {
let that = this
this.tag.uuid = this.$store.state.route.params.uuid
if (this.tag.uuid) {
this.tag.editMode = true
this.tag.httpDetail()
}
}
}
</script>
<style>
</style>
-104
View File
@@ -1,104 +0,0 @@
<template>
<div class="animated fadeIn">
<div class="row">
<div class="col-md-12">
<div class="pedia-navigation">
<span class="item active">标签列表</span>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<NbFilter :pager="pager" :callback="search">
<router-link class="btn btn-primary btn-sm" to="/tag/create">
<i class="fa fa-plus"></i>
创建标签
</router-link>
</NbFilter>
</div>
<div class="col-md-6" v-for="(tag,index) in pager.data">
<div class="bg-white border br4 p10 mb10">
<div class="media">
<div class="pull-left">
<span v-if="tag.logoUrl">
<img class="img-circle img-md" :src="tag.logoUrl" alt="">
</span>
<span v-else>
<img class="img-circle img-md" src="../../assets/img/tag.png" alt="">
</span>
</div>
<div class="media-body">
<div class="cell-title cursor">
<span class="ln64 ml10">{{tag.name}}</span>
</div>
</div>
<div>
<span class="pull-right action-buttons">
<router-link :to="'/tag/edit/'+tag.uuid">
<i class="fa fa-pencil text-info f18"></i>
</router-link>
<a href="javascript:void(0)" title="删除" @click.stop.prevent="tag.confirmDel(refresh)">
<i class="fa fa-trash text-danger f18"></i>
</a>
</span>
</div>
</div>
</div>
</div>
<div class="col-md-12 mt20">
<NbPager :pager="pager" :callback="refresh"/>
</div>
</div>
</div>
</template>
<script>
import NbFilter from '../../common/widget/filter/NbFilter.vue'
import NbPager from '../../common/widget/NbPager.vue'
import { MessageBox, Notification } from 'element-ui'
import Pager from '../../common/model/base/Pager'
import Tag from '../../common/model/tag/Tag'
export default {
name: 'list',
data () {
return {
pager: new Pager(Tag),
user: this.$store.state.user
}
},
components: {
NbFilter,
NbPager
},
methods: {
search () {
this.pager.page = 0
this.refresh()
},
refresh () {
this.pager.httpFastPage()
}
},
mounted () {
this.pager.enableHistory()
this.refresh()
}
}
</script>
<style>
</style>
+62 -28
View File
@@ -5,8 +5,8 @@
<div class="col-md-12">
<div class="pedia-navigation">
<span class="item active">
<span v-show="!user.editMode">创建用户</span>
<span v-show="user.editMode">编辑用户</span>
<span v-show="!currentUser.editMode">创建用户</span>
<span v-show="currentUser.editMode">编辑用户</span>
</span>
</div>
</div>
@@ -14,28 +14,37 @@
<div class="col-md-12">
<div class="bg-white br4 border p10">
<div>
<div class="row mt10" v-if="!user.editMode" v-validator="user.validatorSchema.email.error">
<div class="row mt10">
<label class="col-md-2 control-label mt5 compulsory">头像</label>
<div class="col-md-10">
<MatterImage v-model="currentUser.avatarUrl"/>
</div>
</div>
<div class="row mt10" v-if="!currentUser.editMode" v-validator="currentUser.validatorSchema.email.error">
<label class="col-md-2 control-label mt5 compulsory">邮箱</label>
<div class="col-md-10 validate">
<input type="text" class="form-control" v-model="user.email">
<input type="text" class="form-control" v-model="currentUser.email">
</div>
</div>
<div class="row mt10" v-validator="user.validatorSchema.username.error">
<div class="row mt10" v-validator="currentUser.validatorSchema.username.error">
<label class="col-md-2 control-label mt5 compulsory">用户名</label>
<div class="col-md-10 validate">
<input type="text" class="form-control" v-model="user.username">
<input type="text" class="form-control" v-model="currentUser.username">
</div>
</div>
<div class="row mt10" v-if="!user.editMode" v-validator="user.validatorSchema.password.error">
<div class="row mt10" v-if="!currentUser.editMode" v-validator="currentUser.validatorSchema.password.error">
<label class="col-md-2 control-label mt5 compulsory">密码</label>
<div class="col-md-10 validate">
<input type="password" class="form-control" v-model="user.password">
<input type="password" class="form-control" v-model="currentUser.password">
</div>
</div>
<div class="row mt10" v-if="!user.editMode">
<div class="row mt10" v-if="!currentUser.editMode">
<label class="col-md-2 control-label mt5 compulsory">确认密码</label>
<div class="col-md-10">
<input type="password" class="form-control" v-model="rePassword">
@@ -43,20 +52,28 @@
</div>
<div class="row mt10">
<label class="col-md-2 control-label mt5">手机号</label>
<label class="col-md-2 control-label mt5">单文件限制(单位byte负数表示无限制) 当前大小{{currentUser.sizeLimit | humanFileSize}} </label>
<div class="col-md-10">
<input type="text" class="form-control" v-model="user.phone">
<input type="number" class="form-control" v-model="currentUser.sizeLimit">
</div>
</div>
<div class="row mt10">
<label class="col-md-2 control-label mt5">手机号</label>
<div class="col-md-10">
<input type="text" class="form-control" v-model="currentUser.phone">
</div>
</div>
<div class="row mt10">
<label class="col-md-2 control-label mt5">性别</label>
<div class="col-md-10">
<span v-for="gender in user.getGenderList()" class="mr10">
<NbRadio v-model="user.gender" :val="gender.value" name="gender"></NbRadio>
<label>{{gender.name}}</label>
</span>
<span v-for="gender in currentUser.getGenderList()" class="mr10">
<NbRadio v-model="currentUser.gender" :val="gender.value" name="gender"></NbRadio>
<label>{{gender.name}}</label>
</span>
</div>
</div>
@@ -64,7 +81,7 @@
<div class="row mt10">
<label class="col-md-2 control-label mt5">城市</label>
<div class="col-md-10">
<input type="text" class="form-control" v-model="user.city">
<input type="text" class="form-control" v-model="currentUser.city">
</div>
</div>
</div>
@@ -77,7 +94,7 @@
<span class="fa fa-reply"></span>
返回
</button>
<CreateSaveButton :entity="user" :callback="save"></CreateSaveButton>
<CreateSaveButton :entity="currentUser" :callback="save"></CreateSaveButton>
</div>
</div>
@@ -90,7 +107,7 @@
import { Notification } from 'element-ui'
import { FeatureType } from '../../common/model/feature/FeatureType'
import NbRadio from '../../common/widget/NbRadio.vue'
import NbTank from '../../common/widget/NbTank.vue'
import MatterImage from '../matter/widget/MatterImage'
import CreateSaveButton from '../widget/CreateSaveButton'
import User from '../../common/model/user/User'
@@ -100,37 +117,54 @@
return {
FeatureType,
rePassword: null,
currentUser: this.$store.state.user,
user: new User()
user: this.$store.state.user,
currentUser: new User(),
breadcrumbs: this.$store.state.breadcrumbs
}
},
components: {
NbRadio,
NbTank,
MatterImage,
CreateSaveButton
},
methods: {
save () {
let that = this
if (!this.user.editMode && this.user.password !== this.rePassword) {
if (!this.currentUser.editMode && this.currentUser.password !== this.rePassword) {
Notification.error('两次密码输入不一致')
return
}
this.user.httpSave(function (response) {
this.currentUser.httpSave(function (response) {
Notification.success({
message: that.user.editMode ? '修改用户成功!' : '创建用户成功!'
message: that.currentUser.editMode ? '修改用户成功!' : '创建用户成功!'
})
if (that.user.uuid === that.currentUser.uuid) {
that.user.innerLogin(response)
}
that.$router.go(-1)
})
}
},
created () {
if(this.user.role !== 'ADMINISTRATOR'){
this.breadcrumbs.splice(0, this.breadcrumbs.length)
this.breadcrumbs.push({
title: '个人详情',
path: '/user/detail/' + this.user.uuid
},{
title: '编辑资料'
})
}
},
mounted () {
let that = this
this.user.errorMessage = null
this.user.uuid = this.$store.state.route.params.uuid
if (this.user.uuid) {
this.user.httpDetail()
this.currentUser.errorMessage = null
this.currentUser.uuid = this.$store.state.route.params.uuid
if (this.currentUser.uuid) {
this.currentUser.httpDetail()
}
}
}
+61 -51
View File
@@ -39,71 +39,74 @@
</div>
<div class="mt5 col-md-12">
<NbExpanding>
<div class="row" v-show="userDetailDown">
<div class="col-md-12">
<div>
<span class="bold">手机号</span>{{currentUser.phone}}
</div>
</div>
<div class="mt5 col-md-12">
<div>
<span class="bold">性别</span>{{currentUser.getGenderName()}}
</div>
</div>
<div class="mt5 col-md-12" v-if="currentUser.city">
<div>
<span class="bold">城市</span>{{currentUser.city}}
</div>
</div>
<div class="mt5 col-md-12">
<div>
<span class="bold">状态</span>{{currentUser.getStatusName()}}
</div>
</div>
<div class="mt5 col-md-12" v-if="currentUser.lastIp">
<div>
<span class="bold">上次登录IP</span>{{currentUser.lastIp}}
</div>
</div>
<div class="mt5 col-md-12" v-if="currentUser.lastTime">
<div>
<span class="bold">上次登录时间</span>{{currentUser.lastTime | simpleDateTime}}
</div>
<div class="row">
<div class="col-md-12">
<div>
<span class="bold">手机号</span>{{currentUser.phone}}
</div>
</div>
</NbExpanding>
<div class="mt5 col-md-12">
<div>
<span class="bold">性别</span>{{currentUser.getGenderName()}}
</div>
</div>
<div class="mt5 col-md-12" v-if="currentUser.city">
<div>
<span class="bold">城市</span>{{currentUser.city}}
</div>
</div>
<div class="mt5 col-md-12">
<div>
<span class="bold">单文件限制</span>
<span v-if="currentUser.sizeLimit >= 0">
{{currentUser.sizeLimit | humanFileSize}}
</span>
<span v-else>
无限制
</span>
</div>
</div>
<div class="mt5 col-md-12">
<div>
<span class="bold">状态</span>{{currentUser.getStatusName()}}
</div>
</div>
<div class="mt5 col-md-12" v-if="currentUser.lastIp">
<div>
<span class="bold">上次登录IP</span>{{currentUser.lastIp}}
</div>
</div>
<div class="mt5 col-md-12" v-if="currentUser.lastTime">
<div>
<span class="bold">上次登录时间</span>{{currentUser.lastTime | simpleDateTime}}
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 f14" style="line-height: 36px;">
<span class="cursor" @click.stop.prevent="userDetailDown = !userDetailDown">
<span class="fa"
:class="{'fa-angle-down': !userDetailDown, 'fa-angle-up': userDetailDown}"></span>
<span>{{userDetailDown ? '收起详细资料' : '查看详细资料'}}</span>
</span>
</div>
<div class="col-md-12 text-right">
<button class="btn btn-sm btn-primary mb5" v-if="currentUser.uuid !== user.uuid"
@click.stop.prevent="$router.push('/user/profile')">
返回管理员账户
</button>
<button class="btn btn-sm btn-primary mb5" v-if="user.role === 'ADMINISTRATOR'"
@click.stop.prevent="resetPassword">
@click.stop.prevent="resetPassword">
重置密码
</button>
<button class="btn btn-sm btn-primary mb5" v-if="currentUser.uuid === user.uuid"
@click.stop.prevent="changePassword">
@click.stop.prevent="changePassword">
修改密码
</button>
<button class="btn btn-sm btn-primary mb5"
@click.stop.prevent="$router.push('/matter/list/root?userUuid=' + currentUser.uuid)">
@click.stop.prevent="$router.push('/?userUuid=' + currentUser.uuid)">
{{currentUser.uuid === user.uuid ? '我的文件' : '他的文件'}}
</button>
<button class="btn btn-sm btn-primary mb5"
@click.stop.prevent="$router.push('/user/edit/' + currentUser.uuid)">
@click.stop.prevent="$router.push('/user/edit/' + currentUser.uuid)">
{{currentUser.uuid === user.uuid ? '编辑个人资料' : '编辑他的资料'}}
</button>
</div>
@@ -115,7 +118,7 @@
</div>
</div>
</div>
</div>
@@ -130,10 +133,9 @@
export default {
data() {
return {
userDetailDown: false,
user: this.$store.state.user,
currentUser: new User()
currentUser: new User(),
breadcrumbs: this.$store.state.breadcrumbs
}
},
components: {
@@ -174,6 +176,14 @@
this.currentUserUpdate(newVal)
}
},
created() {
if (this.user.role !== 'ADMINISTRATOR') {
this.breadcrumbs.splice(0, this.breadcrumbs.length)
this.breadcrumbs.push({
title: '个人详情'
})
}
},
mounted() {
this.currentUserUpdate(this.$store.state.route.params.uuid)
+17 -17
View File
@@ -17,48 +17,48 @@
</NbFilter>
</div>
<div class="col-md-12" v-for="(user,index) in pager.data">
<div class="col-md-12" v-for="(userItem,index) in pager.data">
<div class="bg-white border br4 p10 mb10">
<div class="media">
<div class="pull-left">
<router-link :to="'/user/detail/'+user.uuid">
<img class="img-circle img-md" :src="user.getAvatarUrl()">
<router-link :to="'/user/detail/'+userItem.uuid">
<img class="img-circle img-md" :src="userItem.getAvatarUrl()">
</router-link>
</div>
<div class="media-body">
<div>
<span class="f16">
<router-link class="black" :to="'/user/detail/'+user.uuid">
{{user.username}}
<span v-if="user.uuid === currentUser.uuid"
<router-link class="black" :to="'/user/detail/'+userItem.uuid">
{{userItem.username}}
<span v-if="userItem.uuid === user.uuid"
class="text-danger">(It's you)</span>
</router-link>
</span>
</div>
<div>
<div class="mt5">
{{user.getRoleName()}}
{{userItem.getRoleName()}}
</div>
<div class="mt5">
<i class="fa fa-envelope text-success" v-if="user.email"></i>
{{user.email}}
<i class="fa fa-envelope text-success" v-if="userItem.email"></i>
{{userItem.email}}
<i class="fa fa-phone text-info" v-if="user.phone"></i>
{{user.phone}}
<i class="fa fa-phone text-info" v-if="userItem.phone"></i>
{{userItem.phone}}
</div>
</div>
<div class="mv5 text-muted one-line">
{{user.description}}
{{userItem.description}}
</div>
<div>
<span class="mr10">上次登录: {{user.lastTime | humanTime}}</span>
<span class="mr10">上次IP: {{user.lastIp}}</span>
<span class="mr10">上次登录: {{userItem.lastTime | humanTime}}</span>
<span class="mr10">上次IP: {{userItem.lastIp}}</span>
<span class="pull-right action-buttons">
<router-link :to="'/user/edit/'+user.uuid">
<router-link :to="'/user/edit/'+userItem.uuid">
<i class="fa fa-pencil text-info f18"></i>
</router-link>
<a href="javascript:void(0)" title="删除" @click.stop.prevent="user.confirmDel(refresh)">
<a href="javascript:void(0)" title="删除" @click.stop.prevent="userItem.confirmDel(refresh)">
<i class="fa fa-trash text-danger f18"></i>
</a>
</span>
@@ -88,7 +88,7 @@
data () {
return {
pager: new Pager(User),
currentUser: this.$store.state.user
user: this.$store.state.user
}
},
components: {
+43 -46
View File
@@ -1,56 +1,53 @@
<template>
<div class="row">
<div class="row">
<div class="col-lg-4 col-lg-offset-4 col-md-6 col-md-offset-3 mt100">
<div class="text-primary f25 text-center mb20">欢迎登录</div>
<!--输入框开始-->
<div class="input-group mb15">
<span class="input-group-addon"><i class="fa fa-user w14"></i></span>
<input type="email" class="form-control" placeholder="邮箱" v-model="user.email"
@keyup.enter="login">
</div>
<div class="input-group mb15">
<span class="input-group-addon"><i class="fa fa-unlock-alt w14"></i></span>
<input type="password" class="form-control" placeholder="密码" v-model="user.localPassword"
@keyup.enter="login">
</div>
<div class="col-lg-4 col-lg-offset-4 col-md-6 col-md-offset-3 mt100">
<div class="text-primary f25 text-center mb20">欢迎登录</div>
<!--输入框开始-->
<div class="input-group mb15">
<span class="input-group-addon"><i class="fa fa-user w14"></i></span>
<input type="email" class="form-control" placeholder="邮箱" v-model="user.email"
@keyup.enter="login">
</div>
<div class="input-group mb15">
<span class="input-group-addon"><i class="fa fa-unlock-alt w14"></i></span>
<input type="password" class="form-control" placeholder="密码" v-model="user.localPassword"
@keyup.enter="login">
</div>
<div class="mv10">
体验账号 lish516@126.com 密码123456
</div>
<div class="mb15">
<button class="btn btn-primary button full-width" @click.prevent.stop="login" :disabled="user.loading">
<div class="mb15">
<button class="btn btn-primary button full-width" @click.prevent.stop="login" :disabled="user.loading">
<span v-if="user.loading">
<i class="fa fa-spinner fa-spin"></i>
正在登录...
</span>
<span v-else>
<span v-else>
<i class="fa fa-user-circle-o"></i>
登录
</span>
</button>
</button>
</div>
</div>
<div class="mb15" v-show="user.errorMessage">
<div class="alert alert-danger">
{{user.errorMessage}}
</div>
</div>
<div class="mb15" v-show="user.errorMessage">
<div class="alert alert-danger">
{{user.errorMessage}}
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import {startWith} from "../../common/filter/str";
import { startWith } from '../../common/filter/str'
import { Notification } from 'element-ui'
export default {
data() {
data () {
return {
user: this.$store.state.user,
captchaValue: null,
@@ -62,7 +59,7 @@
computed: {},
components: {},
methods: {
login() {
login () {
let that = this
this.user.httpLogin(function () {
@@ -70,44 +67,44 @@
//自动跳转到之前的页面中去。
if (that.redirect) {
if (startWith(that.redirect, "/")) {
that.$router.push(that.redirect);
if (startWith(that.redirect, '/')) {
that.$router.push(that.redirect)
} else {
location.href = that.redirect;
location.href = that.redirect
}
} else {
//自动进入到首页。
that.$router.push("/")
that.$router.push('/')
}
//登录成功啦。
}, function (err) {
console.log(err)
Notification.error({
title: '错误',
message: err.data.msg
})
})
},
logout() {
logout () {
if (this.user.role !== "GUEST") {
if (this.user.role !== 'GUEST') {
this.user.httpLogout(function () {
console.info("退出成功!")
}, function () {
console.error("退出失败!")
console.error('退出失败!')
})
}
}
},
mounted() {
mounted () {
//到登录页面了需要先做一次退出操作。因为退出就是直接跳转到登录页面的。
this.logout()
}
}
</script>
-68
View File
@@ -1,68 +0,0 @@
<template>
<div class="animated fadeIn">
<div class="row">
<div class="col-md-12">
<div class="pedia-navigation">
<span class="item active">用户详情</span>
</div>
</div>
</div>
<!--编辑权限设置-->
<div class="text-right mb10">
<router-link class="btn btn-primary btn-sm" :to="'/user/edit/'+ user.uuid">
<i class="fa fa-pencil"></i>
编辑用户
</router-link>
</div>
<div class="row">
<div class="col-md-12">
<LoadingFrame :loading="user.detailLoading">
<div class="row">
<div class="col-md-12">
用户名{{user.username}}
邮箱{{user.email}}
</div>
</div>
</LoadingFrame>
</div>
</div>
</div>
</template>
<script>
import {MessageBox, Notification as NotificationBox} from 'element-ui'
import User from '../../common/model/user/User'
import NbSlidePanel from '../../common/widget/NbSlidePanel.vue'
import NbExpanding from '../../common/widget/NbExpanding.vue'
import NbBtnDropdown from "../../common/widget/NbBtnDropdown.vue";
import LoadingFrame from "../widget/LoadingFrame";
import CreateSaveButton from "../widget/CreateSaveButton.vue"
export default {
data() {
return {
user: new User()
}
},
components: {},
computed: {},
methods: {
fetchDetail() {
let that = this;
this.user.uuid = this.$store.state.route.params.uuid;
if (this.user.uuid) {
this.user.httpDetail();
}
}
},
mounted() {
this.fetchDetail();
}
}
</script>
+59 -66
View File
@@ -1,32 +1,35 @@
<template>
<div>
<div>
<div>
<Multiselect v-model="selectedOptions"
tag-placeholder="选择用户"
placeholder="搜索或选择用户"
selectedLabel="已选"
deselectLabel="点击移除"
selectLabel="点击选择"
label="username"
track-by="uuid"
@search-change="inputChange"
@select="select"
:loading="pager.loading"
:internal-search="false"
:hide-selected="true"
:options="options"
:multiple="true"
:max="1"
>
<div v-if="!pager.loading">
<Multiselect v-model="innerTags"
tag-placeholder="选择用户"
placeholder="搜索或选择用户"
selectedLabel="已选"
deselectLabel="点击移除"
selectLabel="点击选择"
label="username"
track-by="uuid"
:options="options"
:multiple="true"
:max="1"
>
<span class="italic" slot="maxElements">
最多只能选择1项
</span>
<span class="italic" slot="noResult">
<span class="italic" slot="noResult">
没有符合条件的条目
</span>
</Multiselect>
</div>
<div v-if="pager.loading">
<i class="fa fa-spinner fa-spin fa-fw"></i>
</div>
</Multiselect>
</div>
</div>
</div>
</template>
<script>
import Multiselect from 'vue-multiselect'
@@ -35,9 +38,9 @@
import User from '../../../common/model/user/User'
export default {
data () {
data() {
return {
innerTags: [],
selectedOptions: [],
options: [],
pager: new Pager(User, 20)
}
@@ -45,7 +48,7 @@
props: {
activeItem: {
type: User,
required: true
required: true
},
initFilter: {
type: Object,
@@ -53,82 +56,72 @@
}
},
watch: {
"innerTags"(newVal, oldVal){
console.log(newVal)
if (this.innerTags) {
/*console.log(this.innerTags[0])*/
if (this.innerTags.length > 0) {
"selectedOptions"(newVal, oldVal) {
if (this.selectedOptions) {
if (this.selectedOptions.length > 0) {
for (let i = 0; i < this.options.length; i++) {
if (this.options[i].uuid === this.selectedOptions[0].uuid) {
this.activeItem.render(this.options[i])
}
}
this.activeItem.render(this.innerTags[0])
/*console.log(this.activeItem)*/
} else {
this.activeItem.render(new User())
}
}
},
"activeItem.uuid"(newVal, oldVal) {
let that = this
if (newVal) {
if (this.activeItem.username) {
//inner change
} else {
//outer change.
this.activeItem.httpDetail(function () {
that.selectedOptions.push(that.activeItem)
})
}
}
}
},
methods: {
refresh(){
refresh() {
let that = this;
this.pager.httpFastPage(function () {
let list = that.pager.getList();
if (list && list.length > 0) {
that.options.splice(0, that.options.length);
list.forEach(item => {
that.options.push(item);
})
}
});
},
//用tags的元素去装填innerTags
fillInnerTags(){
if (this.innerTags[0] && this.innerTags[0].uuid === this.activeItem.uuid) {
//Event from inner.
} else {
//Event from outer
//清空innerTags
this.innerTags.splice(0, this.innerTags.length);
//把tags中所有的item追加过来
if (this.activeItem.uuid) {
this.innerTags.push(this.activeItem)
}
}
inputChange(value, id) {
this.pager.setFilterValue("username", value);
this.refresh();
},
asyncFind (value) {
let that = this
this.isLoading = true
this.pager.setFilterValue('username', value)
this.pager.httpFastPage(function (response) {
that.isLoading = false
})
select(selectedOption, id) {
}
},
components: {
Multiselect
},
created () {
created() {
},
mounted () {
/*this.fillInnerTags();*/
mounted() {
if (this.initFilter) {
for (let key in this.initFilter) {
this.pager.setFilterValue(key, this.initFilter[key]);
}
}
this.refresh();
}
}
-31
View File
@@ -9,53 +9,22 @@
</div>
</div>
<div class="row mt10">
<div class="col-md-12">
<h3>
NbTank演示
</h3>
</div>
<div class="col-md-12 mt15">
<p>
1.私有文件演示
</p>
</div>
<div class="col-md-12">
<NbTank :tank="tank1"/>
</div>
<div class="col-md-12 mt15">
<p>
2.公有文件演示
</p>
</div>
<div class="col-md-12">
<NbTank :tank="tank2"/>
</div>
</div>
</div>
</template>
<script>
import NbTank from "../../common/widget/NbTank.vue"
import Tank from "../../common/model/tank/Tank";
export default {
data() {
return {
tank1: new Tank("image", true, 1024 * 1024, "请上传1M以内的图片"),
tank2: new Tank("image", false, 1024 * 1024, "请上传1M以内的图片")
}
},
props: {},
watch: {},
computed: {},
components: {
NbTank
},
methods: {},
mounted() {
+11 -11
View File
@@ -1,4 +1,4 @@
export function startWith (str, prefix) {
export function startWith(str, prefix) {
if (typeof prefix === 'undefined' || prefix === null || prefix === '' || typeof str === 'undefined' || str === null || str.length === 0 || prefix.length > str.length) {
return false
}
@@ -6,7 +6,7 @@ export function startWith (str, prefix) {
return str.substr(0, prefix.length) === prefix
}
export function endWith (str, suffix) {
export function endWith(str, suffix) {
if (suffix === null || suffix === '' || str === null || str.length === 0 || suffix.length > str.length) {
return false
}
@@ -15,7 +15,7 @@ export function endWith (str, suffix) {
}
//获取文件后缀名
export function getExtension (filename) {
export function getExtension(filename) {
if (filename === null || filename === '') {
return ''
@@ -29,7 +29,7 @@ export function getExtension (filename) {
}
//一个字符串包含子字符串
export function containStr (father, child) {
export function containStr(father, child) {
if (father === null || father === '') {
return false
@@ -39,8 +39,8 @@ export function containStr (father, child) {
//把一个大小转变成方便读的格式
//human readable file size
export function humanFileSize (bytes, si = false) {
let thresh = si ? 1024 : 1000
export function humanFileSize(bytes, si = false) {
let thresh = si ? 1000 : 1024
if (Math.abs(bytes) < thresh) {
return bytes + ' B'
}
@@ -56,7 +56,7 @@ export function humanFileSize (bytes, si = false) {
}
//把数字转换成中文大写金额
export function numberCapital (num) {
export function numberCapital(num) {
let strOutput = ''
let strUnit = '仟佰拾亿仟佰拾万仟佰拾元角分'
num += '00'
@@ -74,7 +74,7 @@ export function numberCapital (num) {
}
//转换成首字母小写的驼峰法
export function lowerCamel (str) {
export function lowerCamel(str) {
if (!str) {
console.error('不能转换空的驼峰字符串。')
@@ -87,7 +87,7 @@ export function lowerCamel (str) {
}
//转换成全部小写的使用 /分隔的字符串
export function lowerSlash (str) {
export function lowerSlash(str) {
return str.replace(/(?:^\w|[A-Z]|\b\w)/g, function (letter, index) {
return '/' + letter.toLowerCase()
}).replace(/\s+/g, '')
@@ -106,7 +106,7 @@ export function lowerSlash (str) {
4.以辅音字母+y结尾的名词,将y改变为i,再加-es.
元音字母+y结尾的名词则直接加s
*/
export function toPlural (singular) {
export function toPlural(singular) {
if (!singular) {
console.error('不能转换空字符为复数形式。')
@@ -128,4 +128,4 @@ export function toPlural (singular) {
return singular + 's'
}
}
}
@@ -1,108 +0,0 @@
export default function PluginIndent(WangEditor, $) {
// 用 createMenu 方法创建菜单
WangEditor.createMenu(function (check) {
let menuId = 'nbaligncenter';
if (!check(menuId)) {
return;
}
let editor = this;
// 创建 menu 对象
let menu = new WangEditor.Menu({
editor: editor,
id: menuId,
title: "右对齐",
// 正常状态和选中状态下的dom对象,样式需要自定义
$domNormal: $('<a href="#" tabindex="-1"><i class="fa fa-align-center"></i></a>'),
$domSelected: $('<a href="#" tabindex="-1" class="selected"><i class="fa fa-align-center"></i></a>')
});
// 菜单正常状态下,点击将触发该事件
menu.clickEvent = function (e) {
// 找到当前选区所在的 p 元素
let elem = editor.getRangeElem();
let p = editor.getSelfOrParentByName(elem, 'p');
let $p;
if (!p) {
// 未找到 p 元素,则忽略
return e.preventDefault();
}
$p = $(p);
// 使用自定义命令
function commandFn() {
$p.css('text-align', 'center');
}
editor.customCommand(e, commandFn);
// onchange 事件
if (editor.onchange && typeof editor.onchange === 'function') {
editor.onchange.call(editor);
}
};
// 菜单选中状态下,点击将触发该事件
menu.clickEventSelected = function (e) {
// 找到当前选区所在的 p 元素
let elem = editor.getRangeElem();
let p = editor.getSelfOrParentByName(elem, 'p');
let $p;
if (!p) {
// 未找到 p 元素,则忽略
return e.preventDefault();
}
$p = $(p);
// 使用自定义命令
function commandFn() {
$p.css('text-align', 'inherit');
}
editor.customCommand(e, commandFn);
// onchange 事件
if (editor.onchange && typeof editor.onchange === 'function') {
editor.onchange.call(editor);
}
};
// 定义 update selected 事件
menu.updateSelectedEvent = function () {
let rangeElem = editor.getRangeElem();
rangeElem = editor.getSelfOrParentByName(rangeElem, 'p,h1,h2,h3,h4,h5,li', function (elem) {
let cssText;
if (elem && elem.style && elem.style.cssText != null) {
cssText = elem.style.cssText;
if (cssText && /text-align:\s*center;/.test(cssText)) {
return true;
}
}
if ($(elem).attr('align') === 'center') {
// ff 中,设置align-center之后,会是 <p align="center">xxx</p>
return true;
}
return false;
});
if (rangeElem) {
return true;
}
return false;
};
// 增加到editor对象中
editor.menus[menuId] = menu;
});
}
@@ -1,109 +0,0 @@
export default function PluginIndent(WangEditor, $) {
// 用 createMenu 方法创建菜单
WangEditor.createMenu(function (check) {
let menuId = 'nbalignjustify';
if (!check(menuId)) {
return;
}
let editor = this;
// 创建 menu 对象
let menu = new WangEditor.Menu({
editor: editor,
id: menuId,
title: "两端对齐",
// 正常状态和选中状态下的dom对象,样式需要自定义
$domNormal: $('<a href="#" tabindex="-1"><i class="fa fa-align-justify"></i></a>'),
$domSelected: $('<a href="#" tabindex="-1" class="selected"><i class="fa fa-align-justify"></i></a>')
});
// 菜单正常状态下,点击将触发该事件
menu.clickEvent = function (e) {
// 找到当前选区所在的 p 元素
let elem = editor.getRangeElem();
let p = editor.getSelfOrParentByName(elem, 'p');
let $p;
if (!p) {
// 未找到 p 元素,则忽略
return e.preventDefault();
}
$p = $(p);
// 使用自定义命令
function commandFn() {
$p.css('text-align', 'justify');
}
editor.customCommand(e, commandFn);
// onchange 事件
if (editor.onchange && typeof editor.onchange === 'function') {
editor.onchange.call(editor);
}
};
// 菜单选中状态下,点击将触发该事件
menu.clickEventSelected = function (e) {
// 找到当前选区所在的 p 元素
let elem = editor.getRangeElem();
let p = editor.getSelfOrParentByName(elem, 'p');
let $p;
if (!p) {
// 未找到 p 元素,则忽略
return e.preventDefault();
}
$p = $(p);
// 使用自定义命令
function commandFn() {
$p.css('text-align', 'inherit');
}
editor.customCommand(e, commandFn);
// onchange 事件
if (editor.onchange && typeof editor.onchange === 'function') {
editor.onchange.call(editor);
}
};
// 定义 update selected 事件
menu.updateSelectedEvent = function () {
let rangeElem = editor.getRangeElem();
rangeElem = editor.getSelfOrParentByName(rangeElem, 'p,h1,h2,h3,h4,h5,li', function (elem) {
let cssText;
if (elem && elem.style && elem.style.cssText != null) {
cssText = elem.style.cssText;
if (cssText && /text-align:\s*justify;/.test(cssText)) {
return true;
}
}
if ($(elem).attr('align') === 'justify') {
// ff 中,设置align-center之后,会是 <p align="center">xxx</p>
return true;
}
return false;
});
if (rangeElem) {
return true;
}
return false;
};
// 增加到editor对象中
editor.menus[menuId] = menu;
});
}
@@ -1,108 +0,0 @@
export default function PluginIndent(WangEditor, $) {
// 用 createMenu 方法创建菜单
WangEditor.createMenu(function (check) {
let menuId = 'nbalignleft';
if (!check(menuId)) {
return;
}
let editor = this;
// 创建 menu 对象
let menu = new WangEditor.Menu({
editor: editor,
id: menuId,
title: "左对齐",
// 正常状态和选中状态下的dom对象,样式需要自定义
$domNormal: $('<a href="#" tabindex="-1"><i class="fa fa-align-left"></i></a>'),
$domSelected: $('<a href="#" tabindex="-1" class="selected"><i class="fa fa-align-left"></i></a>')
});
// 菜单正常状态下,点击将触发该事件
menu.clickEvent = function (e) {
// 找到当前选区所在的 p 元素
let elem = editor.getRangeElem();
let p = editor.getSelfOrParentByName(elem, 'p');
let $p;
if (!p) {
// 未找到 p 元素,则忽略
return e.preventDefault();
}
$p = $(p);
// 使用自定义命令
function commandFn() {
$p.css('text-align', 'left');
}
editor.customCommand(e, commandFn);
// onchange 事件
if (editor.onchange && typeof editor.onchange === 'function') {
editor.onchange.call(editor);
}
};
// 菜单选中状态下,点击将触发该事件
menu.clickEventSelected = function (e) {
// 找到当前选区所在的 p 元素
let elem = editor.getRangeElem();
let p = editor.getSelfOrParentByName(elem, 'p');
let $p;
if (!p) {
// 未找到 p 元素,则忽略
return e.preventDefault();
}
$p = $(p);
// 使用自定义命令
function commandFn() {
$p.css('text-align', 'inherit');
}
editor.customCommand(e, commandFn);
// onchange 事件
if (editor.onchange && typeof editor.onchange === 'function') {
editor.onchange.call(editor);
}
};
// 定义 update selected 事件
menu.updateSelectedEvent = function () {
let rangeElem = editor.getRangeElem();
rangeElem = editor.getSelfOrParentByName(rangeElem, 'p,h1,h2,h3,h4,h5,li', function (elem) {
let cssText;
if (elem && elem.style && elem.style.cssText != null) {
cssText = elem.style.cssText;
if (cssText && /text-align:\s*left;/.test(cssText)) {
return true;
}
}
if ($(elem).attr('align') === 'left') {
// ff 中,设置align-center之后,会是 <p align="center">xxx</p>
return true;
}
return false;
});
if (rangeElem) {
return true;
}
return false;
};
// 增加到editor对象中
editor.menus[menuId] = menu;
});
}
@@ -1,108 +0,0 @@
export default function PluginIndent(WangEditor, $) {
// 用 createMenu 方法创建菜单
WangEditor.createMenu(function (check) {
let menuId = 'nbalignright';
if (!check(menuId)) {
return;
}
let editor = this;
// 创建 menu 对象
let menu = new WangEditor.Menu({
editor: editor,
id: menuId,
title: "右对齐",
// 正常状态和选中状态下的dom对象,样式需要自定义
$domNormal: $('<a href="#" tabindex="-1"><i class="fa fa-align-right"></i></a>'),
$domSelected: $('<a href="#" tabindex="-1" class="selected"><i class="fa fa-align-right"></i></a>')
});
// 菜单正常状态下,点击将触发该事件
menu.clickEvent = function (e) {
// 找到当前选区所在的 p 元素
let elem = editor.getRangeElem();
let p = editor.getSelfOrParentByName(elem, 'p');
let $p;
if (!p) {
// 未找到 p 元素,则忽略
return e.preventDefault();
}
$p = $(p);
// 使用自定义命令
function commandFn() {
$p.css('text-align', 'right');
}
editor.customCommand(e, commandFn);
// onchange 事件
if (editor.onchange && typeof editor.onchange === 'function') {
editor.onchange.call(editor);
}
};
// 菜单选中状态下,点击将触发该事件
menu.clickEventSelected = function (e) {
// 找到当前选区所在的 p 元素
let elem = editor.getRangeElem();
let p = editor.getSelfOrParentByName(elem, 'p');
let $p;
if (!p) {
// 未找到 p 元素,则忽略
return e.preventDefault();
}
$p = $(p);
// 使用自定义命令
function commandFn() {
$p.css('text-align', 'inherit');
}
editor.customCommand(e, commandFn);
// onchange 事件
if (editor.onchange && typeof editor.onchange === 'function') {
editor.onchange.call(editor);
}
};
// 定义 update selected 事件
menu.updateSelectedEvent = function () {
let rangeElem = editor.getRangeElem();
rangeElem = editor.getSelfOrParentByName(rangeElem, 'p,h1,h2,h3,h4,h5,li', function (elem) {
let cssText;
if (elem && elem.style && elem.style.cssText != null) {
cssText = elem.style.cssText;
if (cssText && /text-align:\s*right;/.test(cssText)) {
return true;
}
}
if ($(elem).attr('align') === 'right') {
// ff 中,设置align-center之后,会是 <p align="center">xxx</p>
return true;
}
return false;
});
if (rangeElem) {
return true;
}
return false;
};
// 增加到editor对象中
editor.menus[menuId] = menu;
});
}
@@ -1,78 +0,0 @@
import Tank from "../../model/tank/Tank";
import {Notification} from 'element-ui'
import WEAttachment from "./WEAttachment.vue";
import Vue from "vue";
export default function PluginAttachment(WangEditor, $) {
// 用 createMenu 方法创建菜单
WangEditor.createMenu(function (check) {
// 定义菜单id,不要和其他菜单id重复。编辑器自带的所有菜单id,可通过『参数配置-自定义菜单』一节查看
let menuId = 'attachment';
// check将检查菜单配置(『参数配置-自定义菜单』一节描述)中是否该菜单id,如果没有,则忽略下面的代码。
if (!check(menuId)) {
return;
}
// this 指向 editor 对象自身
let editor = this;
// 创建 menu 对象
let menu = new WangEditor.Menu({
editor: editor, // 编辑器对象
id: menuId, // 菜单id
title: '附件', // 菜单标题
// 正常状态和选中状态下的dom对象,样式需要自定义
$domNormal: $('<a href="#" tabindex="-1"><i class="wangeditor-menu-img-file-zip"></i></a>'),
$domSelected: $('<a href="#" tabindex="-1" class="selected"><i class="wangeditor-menu-img-file-zip"></i></a>')
});
let template = `
<div><WEAttachment :insertcallback="insertFunc" :cancelcallback="cancelFunc"/></div>
`;
let $panelContent = $(template);
menu.dropPanel = new WangEditor.DropPanel(editor, menu, {
$content: $panelContent,
width: 400,
height: 225,
onRender: function () {
new Vue({
el: $panelContent[0],
data: function () {
return {}
},
components: {
'weattachment': WEAttachment
},
methods: {
insertFunc(iconUrl, name, url){
let html = '<p><img src="' + iconUrl + '"/>&nbsp;&nbsp;<a href="' + url + '" target="_blank">' + name + '</a></p>';
editor.command(null, 'insertHtml', html);
},
cancelFunc(){
menu.dropPanel.hide();
}
},
mounted(){
}
});
}
});
// 增加到editor对象中
editor.menus[menuId] = menu;
});
}
-49
View File
@@ -1,49 +0,0 @@
export default function PluginIndent(WangEditor, $) {
// 用 createMenu 方法创建菜单
WangEditor.createMenu(function (check) {
// 定义菜单id,不要和其他菜单id重复。编辑器自带的所有菜单id,可通过『参数配置-自定义菜单』一节查看
let menuId = 'hr';
// check将检查菜单配置(『参数配置-自定义菜单』一节描述)中是否该菜单id,如果没有,则忽略下面的代码。
if (!check(menuId)) {
return;
}
// this 指向 editor 对象自身
let editor = this;
// 创建 menu 对象
let menu = new WangEditor.Menu({
editor: editor, // 编辑器对象
id: menuId, // 菜单id
title: '分割线', // 菜单标题
// 正常状态和选中状态下的dom对象,样式需要自定义
$domNormal: $('<a href="#" tabindex="-1"><i class="fa fa-minus"></i></a>'),
$domSelected: $('<a href="#" tabindex="-1" class="selected"><i class="fa fa-minus"></i></a>')
});
// 菜单正常状态下,点击将触发该事件
menu.clickEvent = function (e) {
// 执行插入的命令
editor.command(e, 'insertHtml', "<p><hr><br></p>");
};
// 菜单选中状态下,点击将触发该事件
menu.clickEventSelected = function (e) {
console.log("暂时不做任何事情");
};
// 根据当前选区,自定义更新菜单的选中状态或者正常状态
menu.updateSelectedEvent = function () {
return false;
};
// 增加到editor对象中
editor.menus[menuId] = menu;
});
}
-76
View File
@@ -1,76 +0,0 @@
import {Notification} from "element-ui";
import Vue from "vue";
import WEImage from "./WEImage.vue";
export default function PluginImage(WangEditor, $) {
// 用 createMenu 方法创建菜单
WangEditor.createMenu(function (check) {
// 定义菜单id,不要和其他菜单id重复。编辑器自带的所有菜单id,可通过『参数配置-自定义菜单』一节查看
let menuId = 'image';
// check将检查菜单配置(『参数配置-自定义菜单』一节描述)中是否该菜单id,如果没有,则忽略下面的代码。
if (!check(menuId)) {
return;
}
// this 指向 editor 对象自身
let editor = this;
// 创建 menu 对象
let menu = new WangEditor.Menu({
editor: editor, // 编辑器对象
id: menuId, // 菜单id
title: '图片', // 菜单标题
// 正常状态和选中状态下的dom对象,样式需要自定义
$domNormal: $('<a href="#" tabindex="-1"><i class="wangeditor-menu-img-picture"></i></a>'),
$domSelected: $('<a href="#" tabindex="-1" class="selected"><i class="wangeditor-menu-img-picture"></i></a>')
});
let template = `
<div><WEImage :insertcallback="insertFunc" :cancelcallback="cancelFunc"/></div>
`;
let $panelContent = $(template);
menu.dropPanel = new WangEditor.DropPanel(editor, menu, {
$content: $panelContent,
width: 400,
height: 225,
onRender: function () {
new Vue({
el: $panelContent[0],
data: function () {
return {
}
},
components: {
'weimage': WEImage
},
methods: {
insertFunc(url){
let imgHtml = '<img src="' + url + '"/>';
editor.command(null, 'insertHtml', imgHtml);
},
cancelFunc(){
menu.dropPanel.hide();
}
},
mounted(){
}
});
}
});
// 增加到editor对象中
editor.menus[menuId] = menu;
});
}
@@ -1,98 +0,0 @@
export default function PluginIndent(WangEditor, $) {
// 用 createMenu 方法创建菜单
WangEditor.createMenu(function (check) {
// 定义菜单id,不要和其他菜单id重复。编辑器自带的所有菜单id,可通过『参数配置-自定义菜单』一节查看
let menuId = 'indent';
// check将检查菜单配置(『参数配置-自定义菜单』一节描述)中是否该菜单id,如果没有,则忽略下面的代码。
if (!check(menuId)) {
return;
}
// this 指向 editor 对象自身
let editor = this;
// 创建 menu 对象
let menu = new WangEditor.Menu({
editor: editor, // 编辑器对象
id: menuId, // 菜单id
title: '缩进', // 菜单标题
// 正常状态和选中状态下的dom对象,样式需要自定义
$domNormal: $('<a href="#" tabindex="-1"><i class="wangeditor-menu-img-indent-left"></i></a>'),
$domSelected: $('<a href="#" tabindex="-1" class="selected"><i class="wangeditor-menu-img-indent-left"></i></a>')
});
// 菜单正常状态下,点击将触发该事件
menu.clickEvent = function (e) {
// 找到当前选区所在的 p 元素
let elem = editor.getRangeElem();
let p = editor.getSelfOrParentByName(elem, 'p');
let $p;
if (!p) {
// 未找到 p 元素,则忽略
return e.preventDefault();
}
$p = $(p);
// 使用自定义命令
function commandFn() {
$p.css('text-indent', '2em');
}
editor.customCommand(e, commandFn);
};
// 菜单选中状态下,点击将触发该事件
menu.clickEventSelected = function (e) {
// 找到当前选区所在的 p 元素
let elem = editor.getRangeElem();
let p = editor.getSelfOrParentByName(elem, 'p');
let $p;
if (!p) {
// 未找到 p 元素,则忽略
return e.preventDefault();
}
$p = $(p);
// 使用自定义命令
function commandFn() {
$p.css('text-indent', '0');
}
editor.customCommand(e, commandFn);
};
// 根据当前选区,自定义更新菜单的选中状态或者正常状态
menu.updateSelectedEvent = function () {
// 获取当前选区所在的父元素
let elem = editor.getRangeElem();
let p = editor.getSelfOrParentByName(elem, 'p');
let $p;
let indent;
if (!p) {
// 未找到 p 元素,则标记为未处于选中状态
return false;
}
$p = $(p);
indent = $p.css('text-indent');
if (!indent || indent === '0px') {
// 得到的ptext-indent 属性是 0,则标记为未处于选中状态
return false;
}
// 找到 p 元素,并且 text-indent 不是 0,则标记为选中状态
return true;
};
// 增加到editor对象中
editor.menus[menuId] = menu;
});
}
@@ -1,86 +0,0 @@
<template>
<div class="we-attachment">
<div class="panel-tab">
<div class="tab-container">
<a href="javascript:void(0)" class="tab selected">上传附件</a>
</div>
</div>
<div class="content-container">
<div class="content upload-content">
<div>
<NbTank ref="nbTank" :tank="tank" :preview="false"/>
</div>
<div class="text-right" v-show="tank.exist()">
<button class="gray" @click.stop.prevent="cancelFunc">取消</button>
<button class="" @click.stop.prevent="insertFunc">插入</button>
</div>
</div>
</div>
</div>
</template>
<script>
import NbTank from "../../widget/NbTank.vue";
import Tank from "../../model/tank/Tank";
export default {
data(){
return {
tank: new Tank("*", false, 1024 * 1024 * 1024)
}
},
computed: {
nbTank(){
return this.$refs["nbTank"];
}
},
props: {
//在这种模式下不能使用大写。非常奇怪
insertcallback: {
type: Function,
required: true
},
cancelcallback: {
type: Function,
required: true
}
},
components: {
NbTank
},
watch: {},
methods: {
insertFunc(){
this.insertcallback(this.tank.fileIcon(true), this.tank.name, this.tank.url);
this.nbTank.clear();
},
cancelFunc(){
this.cancelcallback();
}
},
mounted(){
}
}
</script>
<style lang="less" rel="stylesheet/less">
.we-attachment {
.upload-content {
padding: 10px;
}
}
</style>
-111
View File
@@ -1,111 +0,0 @@
<template>
<div class="we-image">
<div class="panel-tab">
<div class="tab-container">
<a href="javascript:void(0)" class="tab" :class="{'selected':uploadTab}"
@click.stop.prevent="uploadTab=true">上传图片</a>
<a href="javascript:void(0)" class="tab" :class="{'selected':!uploadTab}"
@click.stop.prevent="uploadTab=false">网络图片</a>
</div>
</div>
<div class="content-container">
<div class="content upload-content" v-show="uploadTab">
<div>
<NbTank ref="nbTank" :tank="tank" :preview="false"/>
</div>
<div class="text-right" v-show="tank.exist()">
<button class="gray" @click.stop.prevent="cancelFunc">取消</button>
<button class="" @click.stop.prevent="insertFunc">插入</button>
</div>
</div>
<div class="content network-content" v-show="!uploadTab">
<div class="input-block">
<input type="text" class="block url-input" v-model="handurl" placeholder="http://">
</div>
<div class="text-right">
<button class="gray" @click.stop.prevent="cancelFunc">取消</button>
<button class="" @click.stop.prevent="insertFunc">插入</button>
</div>
</div>
</div>
</div>
</template>
<script>
import NbTank from "../../widget/NbTank.vue";
import Tank from "../../model/tank/Tank";
export default {
data(){
return {
handurl: null,
uploadTab: true,
tank: new Tank("image", false, 20 * 1024 * 1024, "建议使用小于1M的图片。")
}
},
computed: {
nbTank(){
return this.$refs["nbTank"];
}
},
props: {
//在这种模式下不能使用大写。非常奇怪
insertcallback: {
type: Function,
required: true
},
cancelcallback: {
type: Function,
required: true
}
},
components: {
NbTank
},
watch: {},
methods: {
insertFunc(){
if (this.uploadTab) {
let url = this.tank.url;
this.nbTank.clear();
this.insertcallback(url);
} else {
this.insertcallback(this.handurl);
this.handurl = null;
}
},
cancelFunc(){
this.cancelcallback();
}
},
mounted(){
}
}
</script>
<style lang="less" rel="stylesheet/less">
.we-image {
.upload-content {
padding: 10px;
}
.network-content {
.input-block {
margin: 20px 10px 10px 10px;
}
}
}
</style>
File diff suppressed because it is too large Load Diff
@@ -1,810 +0,0 @@
// ---------- begin 全局颜色配置 ------------
/* 编辑器边框颜色 */
@border-color: #ccc;
/* 菜单颜色、上边框颜色 */
@fore-color: #666;
/* 菜单选中状态的颜色 */
@selected-color: #1e88e5;
/* input focus 时的颜色 */
@focus-input-color: #1e88e5;
/* 按钮颜色 */
@button-color: #1e88e5;
/* tab selected 状态下的颜色 */
@selected-tab-color: #1e88e5;
// ---------- end 全局颜色配置 ------------
.wangEditor-container {
position: relative;
background-color: #fff;
border: 1px solid @border-color;
z-index: 1;
width: 100%;
a:focus,
button:focus{
outline:none;
}
//&,* {
// margin: 0;
// padding: 0;
// box-sizing: border-box;
// line-height: 1;
//}
img {
border: none;
}
.clearfix:after {
content: '';
display: table;
clear: both;
}
.clearfix {
*zoom: 1;
}
textarea {
border: none;
&:focus{
outline: none;
}
}
// 显示p head 高度的 tip
.height-tip {
position: absolute;
width: 3px;
background-color: #ccc;
left: 0;
transition: top .2s;
}
// 设置 img table 的 toolbar
.txt-toolbar {
position: absolute;
background-color: #fff;
padding: 3px 5px;
border-top: 2px solid @fore-color;
box-shadow: 1px 3px 3px #999;
// for IE8
border-left: 1px\9 solid\9 #ccc\9;
border-bottom: 1px\9 solid\9 #999\9;
border-right: 1px\9 solid\9 #999\9;
// 小三角
.tip-triangle {
display: block;
position: absolute;
width: 0;
height: 0;
border: 5px solid;
border-color: transparent transparent @fore-color transparent;
top: -12px;
left: 50%;
margin-left: -5px;
}
a {
color: @fore-color;
display: inline-block;
margin: 0 3px;
padding: 5px;
text-decoration: none;
border-radius: 3px;
&:hover {
background-color: #f1f1f1;
}
}
}
// 图品拖拽大小
.img-drag-point {
display: block;
position: absolute;
width: 12px;
height: 12px;
border-radius: 50%;
cursor: se-resize;
background-color: @fore-color;
margin-left: -6px;
margin-top: -6px;
box-shadow: 1px 1px 5px #999;
}
// 进度条
.wangEditor-upload-progress {
position: absolute;
height: 1px;
background: #1e88e5;
width: 0;
display: none;
-webkit-transition: width .5s;
-o-transition: width .5s;
transition: width .5s;
}
}
.wangEditor-fullscreen {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.wangEditor-container {
.code-textarea {
resize: none;
width: 100%;
font-size: 14px;
line-height: 1.5;
font-family: 'Verdana';
color: #333;
padding: 0 15px 0 15px;
}
}
.wangEditor-menu-container {
width: 100%;
border-bottom: 1px solid #f1f1f1;
background-color: #fff;
a {
text-decoration: none;
}
// 菜单组
.menu-group {
float: left;
padding: 0 8px;
border-right: 1px solid #f1f1f1;
}
// 单个菜单容器
.menu-item {
float: left;
position: relative;
text-align: center;
height: 31px;
width: 35px;
&:hover {
background-color: #f1f1f1;
}
// 菜单
a {
display: block;
text-align: center;
color: @fore-color;
width: 100%;
padding: 8px 0;
font-size: 0.9em;
}
// 菜单选中状态
.selected {
color: @selected-color;
}
// 激活状态
.active {
background-color: #f1f1f1;
}
// 禁用状态
.disable {
opacity: 0.5;
filter: Alpha(opacity=50);
}
}
// tip提示
.menu-tip {
display: block;
position: absolute;
z-index: 20;
width: 60px;
text-align: center;
background-color: @fore-color;
color: #fff;
padding: 7px 0;
font-size: 12px;
top: 100%;
left: 50%;
margin-left: -30px;
border-radius: 2px;
box-shadow: 1px 1px 5px #999;
display: none;
/*// 小三角
.tip-triangle {
display: block;
position: absolute;
width: 0;
height: 0;
border:5px solid;
border-color: transparent transparent @fore-color transparent;
top: -10px;
left: 50%;
margin-left: -5px;
}*/
}
.menu-tip-40 {
width: 40px;
margin-left: -20px;
}
.menu-tip-50 {
width: 50px;
margin-left: -25px;
}
}
.wangEditor-menu-shadow {
/*border-bottom-width: 0;*/
border-bottom: 1px\9 solid\9 #f1f1f1\9;
box-shadow: 0 1px 3px #999;
}
.wangEditor-container {
.wangEditor-txt{
width: 100%;
text-align: left;
padding: 15px;
padding-top: 0;
margin-top: 5px;
overflow-y: auto;
p,h1,h2,h3,h4,h5 {
margin: 10px 0;
line-height: 1.8;
* {
line-height: 1.8;
}
}
ul, ol {
padding-left: 20px;
}
img {
cursor: pointer;
}
img.clicked {
box-shadow: 1px 1px 10px #999;
}
table.clicked {
box-shadow: 1px 1px 10px #999;
}
pre code {
line-height: 1.5;
}
&:focus{
outline: none;
}
}
}
.wangEditor-container {
.wangEditor-txt {
blockquote {
display: block;
border-left: 8px solid #d0e5f2;
padding: 5px 10px;
margin: 10px 0;
line-height: 1.4;
font-size: 100%;
background-color: #f1f1f1;
}
table {
border: none;
border-collapse: collapse;
}
table td,
table th {
border: 1px solid #999;
padding: 3px 5px;
min-width: 50px;
height: 20px;
}
pre {
border: 1px solid #ccc;
background-color: #f8f8f8;
padding: 10px;
margin: 5px 0px;
font-size: 0.8em;
border-radius: 3px;
}
}
}
.wangEditor-drop-list {
display: none;
position: absolute;
background-color: #fff;
overflow: hidden;
z-index: 10;
transition: height .7s;
border-top: 1px solid #f1f1f1;
box-shadow: 1px 3px 3px #999;
// for IE8
border-left: 1px\9 solid\9 #ccc\9;
border-bottom: 1px\9 solid\9 #999\9;
border-right: 1px\9 solid\9 #999\9;
a {
text-decoration: none;
display: block;
color: @fore-color;
padding: 3px 5px;
&:hover {
background-color: #f1f1f1;
}
}
}
.wangEditor-drop-panel,
.txt-toolbar {
display: none;
position: absolute;
padding: 10px;
font-size: 14px;
/*border: 1px\9 solid\9 #cccccc\9;*/
background-color: #fff;
z-index: 10;
border-top: 2px solid @fore-color;
box-shadow: 1px 3px 3px #999;
// for IE8
border-left: 1px\9 solid\9 #ccc\9;
border-bottom: 1px\9 solid\9 #999\9;
border-right: 1px\9 solid\9 #999\9;
// 小三角
.tip-triangle {
display: block;
position: absolute;
width: 0;
height: 0;
border: 5px solid;
border-color: transparent transparent @fore-color transparent;
top: -12px;
left: 50%;
margin-left: -5px;
}
a {
text-decoration: none;
}
// 输入框
input[type=text] {
border: none;
border-bottom: 1px solid #ccc;
font-size: 14px;
height: 20px;
color: #333;
padding: 3px 0;
&:focus{
outline: none;
border-bottom: 2px solid @focus-input-color;
}
}
input[type=text].block {
display: block;
width: 100%;
}
textarea {
border: 1px solid #ccc;
&:focus {
outline: none;
border-color: @focus-input-color;
}
}
// 按钮
button {
font-size: 14px;
color: @button-color;
border: none;
padding: 10px;
background-color: #fff;
cursor: pointer;
border-radius: 3px;
&:hover {
background-color: #f1f1f1;
}
&:focus{
outline: none;
}
}
button.right {
float: right;
margin-left: 10px;
}
button.gray {
color: #999;
}
button.link {
padding: 5px 10px;
&:hover {
background-color: #fff;
text-decoration: underline;
}
}
// 颜色块
.color-item {
display: block;
float: left;
width: 25px;
height: 25px;
text-align: center;
padding: 2px;
border-radius: 2px;
text-decoration: underline;
&:hover {
background-color: #f1f1f1;
}
}
// 列表
.list-menu-item {
display: block;
float: left;
color: #333;
padding: 5px 5px;
border-radius: 2px;
&:hover {
background-color: #f1f1f1;
}
}
// 表格
table.choose-table {
border: none;
border-collapse: collapse;
td {
border: 1px solid #ccc;
width: 16px;
height: 12px;
}
td.active {
background-color: #ccc;
opacity: .5;
filter: Alpha(opacity=50);
}
}
// tab
.panel-tab {
.tab-container {
margin-bottom: 5px;
a {
display: inline-block;
color: #999;
text-align: center;
margin: 0 5px;
padding: 5px 5px;
}
a.selected {
color: @selected-tab-color;
border-bottom: 2px solid @selected-tab-color;
}
}
.content-container {
.content {
display: none;
a {
display: inline-block;
margin: 2px;
padding: 2px;
border-radius: 2px;
&:hover {
background-color: #f1f1f1;
}
}
}
.selected {
display: block;
}
}
.emotion-content-container {
height: 200px;
overflow-y: auto;
}
}
// 上传图片
.upload-icon-container {
color: #ccc;
text-align: center;
margin: 20px 20px 15px 20px !important;
padding: 5px !important;
font-size: 65px;
cursor: pointer;
border: 2px dotted #f1f1f1;
display: block !important;
&:hover {
color: #666;
border-color: #ccc;
}
}
}
.wangEditor-modal {
position: absolute;
top: 50%;
left: 50%;
background-color: #fff;
border-top: 1px solid #f1f1f1;
box-shadow: 1px 3px 3px #999;
// for IE8
border-top: 1px\9 solid\9 #ccc\9;
border-left: 1px\9 solid\9 #ccc\9;
border-bottom: 1px\9 solid\9 #999\9;
border-right: 1px\9 solid\9 #999\9;
// 关闭按钮
.wangEditor-modal-close {
position: absolute;
top: 0;
right: 0;
margin-top: -25px;
margin-right: -25px;
font-size: 1.5em;
color: #666;
cursor: pointer;
}
}
@font-face {
font-family: 'icomoon';
src:url('../fonts/icomoon.eot?-qdfu1s');
src:url('../fonts/icomoon.eot?#iefix-qdfu1s') format('embedded-opentype'),
url('../fonts/icomoon.ttf?-qdfu1s') format('truetype'),
url('../fonts/icomoon.woff?-qdfu1s') format('woff'),
url('../fonts/icomoon.svg?-qdfu1s#icomoon') format('svg');
font-weight: normal;
font-style: normal;
}
[class^="wangeditor-menu-img-"], [class*=" wangeditor-menu-img-"] {
font-family: 'icomoon';
speak: none;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
/* Better Font Rendering =========== */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.wangeditor-menu-img-link:before {content: "\e800";}
.wangeditor-menu-img-unlink:before {content: "\e801";}
.wangeditor-menu-img-code:before {content: "\e802";}
.wangeditor-menu-img-cancel:before {content: "\e803";}
.wangeditor-menu-img-terminal:before {content: "\e804";}
.wangeditor-menu-img-angle-down:before {content: "\e805";}
.wangeditor-menu-img-font:before {content: "\e806";}
.wangeditor-menu-img-bold:before {content: "\e807";}
.wangeditor-menu-img-italic:before {content: "\e808";}
.wangeditor-menu-img-header:before {content: "\e809";}
.wangeditor-menu-img-align-left:before {content: "\e80a";}
.wangeditor-menu-img-align-center:before {content: "\e80b";}
.wangeditor-menu-img-align-right:before {content: "\e80c";}
.wangeditor-menu-img-list-bullet:before {content: "\e80d";}
.wangeditor-menu-img-indent-left:before {content: "\e80e";}
.wangeditor-menu-img-indent-right:before {content: "\e80f";}
.wangeditor-menu-img-list-numbered:before {content: "\e810";}
.wangeditor-menu-img-underline:before {content: "\e811";}
.wangeditor-menu-img-table:before {content: "\e812";}
.wangeditor-menu-img-eraser:before {content: "\e813";}
.wangeditor-menu-img-text-height:before {content: "\e814";}
.wangeditor-menu-img-brush:before {content: "\e815";}
.wangeditor-menu-img-pencil:before {content: "\e816";}
.wangeditor-menu-img-minus:before {content: "\e817";}
.wangeditor-menu-img-picture:before {content: "\e818";}
.wangeditor-menu-img-file-image:before {content: "\e819";}
.wangeditor-menu-img-cw:before {content: "\e81a";}
.wangeditor-menu-img-ccw:before {content: "\e81b";}
.wangeditor-menu-img-music:before {content: "\e911";}
.wangeditor-menu-img-play:before {content: "\e912";}
.wangeditor-menu-img-location:before {content: "\e947";}
.wangeditor-menu-img-happy:before {content: "\e9df";}
.wangeditor-menu-img-sigma:before {content: "\ea67";}
.wangeditor-menu-img-enlarge2:before {content: "\e98b";}
.wangeditor-menu-img-shrink2:before {content: "\e98c";}
.wangeditor-menu-img-newspaper:before{content: "\e904";}
.wangeditor-menu-img-camera:before{content: "\e90f";}
.wangeditor-menu-img-video-camera:before{content: "\e914";}
.wangeditor-menu-img-file-zip:before{content: "\e92b";}
.wangeditor-menu-img-stack:before{content: "\e92e";}
.wangeditor-menu-img-credit-card:before{content: "\e93f";}
.wangeditor-menu-img-address-book:before{content: "\e944";}
.wangeditor-menu-img-envelop:before{content: "\e945";}
.wangeditor-menu-img-drawer:before{content: "\e95c";}
.wangeditor-menu-img-download:before{content: "\e960";}
.wangeditor-menu-img-upload:before{content: "\e961";}
.wangeditor-menu-img-lock:before{content: "\e98f";}
.wangeditor-menu-img-unlocked:before{content: "\e990";}
.wangeditor-menu-img-wrench:before{content: "\e991";}
.wangeditor-menu-img-eye:before{content: "\e9ce";}
.wangeditor-menu-img-eye-blocked:before{content: "\e9d1";}
.wangeditor-menu-img-command:before{content: "\ea4e";}
.wangeditor-menu-img-font2:before{content: "\ea5c";}
.wangeditor-menu-img-libreoffice:before{content: "\eade";}
.wangeditor-menu-img-quotes-left:before{content: "\e977";}
.wangeditor-menu-img-strikethrough:before{content: "\ea65";}
.wangeditor-menu-img-desktop:before{content: "\f108";}
.wangeditor-menu-img-tablet:before{content: "\f10a";}
.wangeditor-menu-img-search-plus:before {
content: "\f00e";
}
.wangeditor-menu-img-search-minus:before {
content: "\f010";
}
.wangeditor-menu-img-trash-o:before {
content: "\f014";
}
.wangeditor-menu-img-align-justify:before {
content: "\f039";
}
.wangeditor-menu-img-arrows-v:before {
content: "\f07d";
}
.wangeditor-menu-img-sigma2:before {
content: "\ea68";
}
.wangeditor-menu-img-omega:before {
content: "\e900";
}
.wangeditor-menu-img-cancel-circle:before {
content: "\e901";
}
.hljs {
display: block;
overflow-x: auto;
padding: 0.5em;
color: #333;
background: #f8f8f8;
-webkit-text-size-adjust: none;
}
.hljs-comment,
.diff .hljs-header {
color: #998;
font-style: italic;
}
.hljs-keyword,
.css .rule .hljs-keyword,
.hljs-winutils,
.nginx .hljs-title,
.hljs-subst,
.hljs-request,
.hljs-status {
color: #333;
font-weight: bold;
}
.hljs-number,
.hljs-hexcolor,
.ruby .hljs-constant {
color: #008080;
}
.hljs-string,
.hljs-tag .hljs-value,
.hljs-doctag,
.tex .hljs-formula {
color: #d14;
}
.hljs-title,
.hljs-id,
.scss .hljs-preprocessor {
color: #900;
font-weight: bold;
}
.hljs-list .hljs-keyword,
.hljs-subst {
font-weight: normal;
}
.hljs-class .hljs-title,
.hljs-type,
.vhdl .hljs-literal,
.tex .hljs-command {
color: #458;
font-weight: bold;
}
.hljs-tag,
.hljs-tag .hljs-title,
.hljs-rule .hljs-property,
.django .hljs-tag .hljs-keyword {
color: #000080;
font-weight: normal;
}
.hljs-attribute,
.hljs-variable,
.lisp .hljs-body,
.hljs-name {
color: #008080;
}
.hljs-regexp {
color: #009926;
}
.hljs-symbol,
.ruby .hljs-symbol .hljs-string,
.lisp .hljs-keyword,
.clojure .hljs-keyword,
.scheme .hljs-keyword,
.tex .hljs-special,
.hljs-prompt {
color: #990073;
}
.hljs-built_in {
color: #0086b3;
}
.hljs-preprocessor,
.hljs-pragma,
.hljs-pi,
.hljs-doctype,
.hljs-shebang,
.hljs-cdata {
color: #999;
font-weight: bold;
}
.hljs-deletion {
background: #fdd;
}
.hljs-addition {
background: #dfd;
}
.diff .hljs-change {
background: #0086b3;
}
.hljs-chunk {
color: #aaa;
}
Binary file not shown.
@@ -1,76 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Generated by IcoMoon</metadata>
<defs>
<font id="icomoon" horiz-adv-x="1024">
<font-face units-per-em="1024" ascent="960" descent="-64" />
<missing-glyph horiz-adv-x="1024" />
<glyph unicode="&#x20;" horiz-adv-x="512" d="" />
<glyph unicode="&#xe800;" glyph-name="link" horiz-adv-x="950" d="M831.488 264.704q0 23.552-15.36 38.912l-118.784 118.784q-16.384 16.384-38.912 16.384-24.576 0-40.96-18.432 1.024-1.024 10.24-10.24t12.288-12.288 9.216-11.264 7.168-14.336 2.048-15.36q0-23.552-16.384-38.912t-38.912-16.384q-8.192 0-15.36 2.048t-14.336 7.168-11.264 9.216-12.288 12.288-10.24 10.24q-19.456-17.408-19.456-40.96t16.384-38.912l117.76-118.784q15.36-15.36 38.912-15.36 22.528 0 38.912 15.36l83.968 82.944q15.36 16.384 15.36 37.888zM430.080 668.16q0 22.528-15.36 38.912l-117.76 117.76q-16.384 16.384-38.912 16.384t-38.912-15.36l-83.968-83.968q-16.384-15.36-16.384-37.888t16.384-38.912l118.784-118.784q15.36-15.36 38.912-15.36t40.96 17.408q-2.048 2.048-11.264 11.264t-12.288 12.288-8.192 10.24-7.168 14.336-2.048 16.384q0 22.528 15.36 38.912t38.912 15.36q9.216 0 16.384-2.048t14.336-7.168 10.24-8.192 12.288-12.288 11.264-11.264q18.432 17.408 18.432 41.984zM942.080 264.704q0-68.608-49.152-115.712l-83.968-82.944q-47.104-48.128-115.712-48.128-69.632 0-116.736 49.152l-117.76 117.76q-47.104 48.128-47.104 116.736 0 69.632 50.176 118.784l-50.176 50.176q-49.152-50.176-118.784-50.176-68.608 0-116.736 48.128l-118.784 118.784q-48.128 48.128-48.128 116.736t48.128 115.712l83.968 83.968q48.128 47.104 116.736 47.104t116.736-48.128l116.736-118.784q48.128-47.104 48.128-115.712 0-70.656-50.176-119.808l50.176-50.176q49.152 50.176 118.784 50.176 68.608 0 116.736-48.128l118.784-118.784q48.128-48.128 48.128-116.736z" />
<glyph unicode="&#xe801;" glyph-name="unlink" horiz-adv-x="950" d="M250.88 233.984l-146.432-146.432q-5.12-5.12-13.312-5.12-6.144 0-13.312 5.12-5.12 5.12-5.12 13.312t5.12 13.312l146.432 145.408q6.144 5.12 13.312 5.12t13.312-5.12q5.12-5.12 5.12-12.288t-5.12-13.312zM347.136 210.432v-183.296q0-8.192-5.12-13.312t-13.312-5.12-12.288 5.12-5.12 13.312v183.296q0 8.192 5.12 13.312t12.288 5.12 13.312-5.12 5.12-13.312zM219.136 338.432q0-8.192-5.12-13.312t-13.312-5.12h-182.272q-8.192 0-13.312 5.12t-5.12 13.312 5.12 13.312 13.312 5.12h182.272q8.192 0 13.312-5.12t5.12-13.312zM942.080 264.704q0-68.608-49.152-115.712l-83.968-82.944q-47.104-48.128-115.712-48.128-69.632 0-116.736 49.152l-190.464 191.488q-12.288 11.264-24.576 31.744l137.216 10.24 155.648-156.672q15.36-15.36 38.912-15.36t38.912 15.36l83.968 82.944q15.36 16.384 15.36 37.888 0 23.552-15.36 38.912l-156.672 157.696 10.24 136.192q20.48-12.288 31.744-23.552l192.512-192.512q48.128-49.152 48.128-116.736zM588.8 678.4l-136.192-10.24-155.648 156.672q-16.384 16.384-38.912 16.384t-38.912-15.36l-83.968-83.968q-16.384-15.36-16.384-37.888t16.384-38.912l156.672-156.672-10.24-137.216q-20.48 12.288-32.768 24.576l-191.488 191.488q-48.128 49.152-48.128 116.736 0 68.608 48.128 115.712l83.968 83.968q48.128 47.104 116.736 47.104t116.736-48.128l190.464-191.488q12.288-12.288 23.552-32.768zM951.296 631.296q0-8.192-5.12-13.312t-13.312-5.12h-183.296q-8.192 0-13.312 5.12t-5.12 13.312 5.12 12.288 13.312 5.12h183.296q8.192 0 13.312-5.12t5.12-12.288zM640 941.568v-182.272q0-8.192-5.12-13.312t-13.312-5.12-13.312 5.12-5.12 13.312v182.272q0 8.192 5.12 13.312t13.312 5.12 13.312-5.12 5.12-13.312zM872.448 855.552l-146.432-146.432q-6.144-5.12-13.312-5.12t-12.288 5.12q-5.12 6.144-5.12 13.312t5.12 13.312l145.408 145.408q6.144 5.12 13.312 5.12t13.312-5.12q5.12-5.12 5.12-12.288t-5.12-13.312z" />
<glyph unicode="&#xe802;" glyph-name="code" horiz-adv-x="1097" d="M352.256 160.256l-28.672-28.672q-5.12-5.12-12.288-5.12t-13.312 5.12l-266.24 266.24q-6.144 6.144-6.144 13.312t6.144 13.312l266.24 266.24q5.12 6.144 13.312 6.144t12.288-6.144l28.672-28.672q6.144-5.12 6.144-13.312t-6.144-12.288l-224.256-225.28 224.256-224.256q6.144-6.144 6.144-13.312t-6.144-13.312zM690.176 770.56l-212.992-738.304q-2.048-7.168-9.216-11.264t-13.312-1.024l-34.816 9.216q-8.192 3.072-11.264 9.216t-2.048 14.336l212.992 737.28q3.072 8.192 9.216 11.264t13.312 2.048l35.84-10.24q7.168-2.048 11.264-9.216t1.024-13.312zM1065.984 397.824l-266.24-266.24q-6.144-5.12-13.312-5.12t-13.312 5.12l-28.672 28.672q-5.12 6.144-5.12 13.312t5.12 13.312l224.256 224.256-224.256 225.28q-5.12 5.12-5.12 12.288t5.12 13.312l28.672 28.672q6.144 6.144 13.312 6.144t13.312-6.144l266.24-266.24q5.12-5.12 5.12-13.312t-5.12-13.312z" />
<glyph unicode="&#xe803;" glyph-name="cancel" horiz-adv-x="804" d="M741.376 204.288q0-22.528-15.36-38.912l-77.824-77.824q-16.384-15.36-38.912-15.36t-38.912 15.36l-167.936 168.96-167.936-168.96q-16.384-15.36-38.912-15.36t-38.912 15.36l-77.824 77.824q-16.384 16.384-16.384 38.912t16.384 38.912l167.936 167.936-167.936 167.936q-16.384 16.384-16.384 38.912t16.384 38.912l77.824 77.824q16.384 16.384 38.912 16.384t38.912-16.384l167.936-167.936 167.936 167.936q16.384 16.384 38.912 16.384t38.912-16.384l77.824-77.824q15.36-15.36 15.36-38.912t-15.36-38.912l-167.936-167.936 167.936-167.936q15.36-15.36 15.36-38.912z" />
<glyph unicode="&#xe804;" glyph-name="terminal" horiz-adv-x="950" d="M333.824 397.824l-266.24-266.24q-5.12-5.12-12.288-5.12t-13.312 5.12l-28.672 28.672q-6.144 6.144-6.144 13.312t6.144 13.312l224.256 224.256-224.256 225.28q-6.144 5.12-6.144 12.288t6.144 13.312l28.672 28.672q5.12 6.144 13.312 6.144t12.288-6.144l266.24-266.24q6.144-5.12 6.144-13.312t-6.144-13.312zM951.296 136.704v-35.84q0-8.192-5.12-13.312t-13.312-5.12h-548.864q-8.192 0-13.312 5.12t-5.12 13.312v35.84q0 8.192 5.12 13.312t13.312 5.12h548.864q8.192 0 13.312-5.12t5.12-13.312z" />
<glyph unicode="&#xe805;" glyph-name="angle-down" horiz-adv-x="657" d="M614.4 539.136q0-7.168-6.144-13.312l-266.24-266.24q-5.12-5.12-13.312-5.12t-12.288 5.12l-266.24 266.24q-6.144 6.144-6.144 13.312t6.144 13.312l27.648 28.672q6.144 6.144 13.312 6.144t13.312-6.144l224.256-224.256 225.28 224.256q5.12 6.144 13.312 6.144t12.288-6.144l28.672-28.672q6.144-5.12 6.144-13.312z" />
<glyph unicode="&#xe806;" glyph-name="font" horiz-adv-x="950" d="M414.72 640.512l-97.28-257.024q18.432 0 77.824-1.024t91.136-1.024q11.264 0 32.768 1.024-49.152 144.384-104.448 258.048zM0 8.704l1.024 45.056q13.312 4.096 31.744 7.168t32.768 6.144 28.672 8.192 25.6 17.408 17.408 28.672l135.168 352.256 159.744 413.696h73.728q4.096-8.192 6.144-12.288l116.736-274.432q19.456-45.056 61.44-147.456t64.512-156.672q9.216-19.456 33.792-82.944t40.96-96.256q11.264-25.6 19.456-31.744 11.264-9.216 50.176-17.408t48.128-11.264q4.096-22.528 4.096-32.768 0-2.048-1.024-7.168t0-8.192q-35.84 0-108.544 5.12t-109.568 4.096q-43.008 0-122.88-4.096t-101.376-4.096q0 24.576 2.048 44.032l74.752 16.384q1.024 0 7.168 1.024t9.216 2.048 8.192 3.072 9.216 4.096 6.144 4.096 5.12 6.144 1.024 8.192q0 9.216-17.408 55.296t-40.96 101.376-24.576 57.344l-257.024 1.024q-14.336-33.792-44.032-111.616t-28.672-93.184q0-12.288 8.192-21.504t24.576-14.336 27.648-7.168 32.768-5.12 23.552-2.048q1.024-11.264 1.024-32.768 0-5.12-2.048-16.384-32.768 0-99.328 6.144t-99.328 6.144q-5.12 0-15.36-3.072t-12.288-2.048q-46.080-8.192-107.52-8.192z" />
<glyph unicode="&#xe807;" glyph-name="bold" horiz-adv-x="804" d="M317.44 90.624q41.984-18.432 79.872-18.432 215.040 0 215.040 191.488 0 65.536-23.552 103.424-15.36 24.576-35.84 41.984t-37.888 26.624-46.080 14.336-48.128 6.144-54.272 1.024q-40.96 0-57.344-6.144 0-29.696 0-90.112t-1.024-91.136q0-4.096 0-37.888t0-55.296 2.048-48.128 7.168-37.888zM309.248 517.632q23.552-4.096 62.464-4.096 47.104 0 81.92 7.168t62.464 25.6 41.984 51.2 15.36 80.896q0 39.936-16.384 69.632t-46.080 47.104-61.44 24.576-70.656 8.192q-28.672 0-74.752-7.168 0-28.672 3.072-86.016t2.048-87.040q0-15.36 0-46.080t-1.024-45.056q0-26.624 1.024-38.912zM0 8.704l1.024 54.272q9.216 2.048 49.152 9.216t60.416 15.36q4.096 7.168 7.168 15.36t4.096 19.456 4.096 18.432 1.024 21.504 0 19.456v36.864q0 561.152-12.288 585.728-2.048 5.12-12.288 8.192t-25.6 6.144-28.672 4.096-27.648 3.072-17.408 2.048l-2.048 47.104q56.32 1.024 194.56 6.144t212.992 5.12q13.312 0 38.912 0t38.912 0q39.936 0 77.824-7.168t73.728-24.576 61.44-39.936 41.984-60.416 16.384-77.824q0-29.696-9.216-55.296t-22.528-40.96-36.864-32.768-41.984-25.6-48.128-22.528q88.064-20.48 147.456-76.8t58.368-142.336q0-56.32-20.48-102.4t-53.248-74.752-78.848-48.128-93.184-27.648-100.352-8.192q-25.6 0-75.776 2.048t-75.776 1.024q-60.416 0-175.104-6.144t-132.096-7.168z" />
<glyph unicode="&#xe808;" glyph-name="italic" horiz-adv-x="585" d="M0 9.728l10.24 49.152q3.072 1.024 46.080 12.288t63.488 21.504q16.384 19.456 23.552 57.344 1.024 4.096 35.84 165.888t64.512 310.272 29.696 168.96v14.336q-13.312 7.168-30.72 11.264t-39.936 4.096-32.768 3.072l10.24 59.392q19.456-2.048 68.608-4.096t86.016-4.096 68.608-1.024q27.648 0 56.32 1.024t68.608 4.096 56.32 4.096q-2.048-22.528-10.24-51.2-17.408-6.144-58.368-16.384t-61.44-19.456q-5.12-10.24-8.192-23.552t-5.12-23.552-4.096-25.6-4.096-24.576q-15.36-83.968-50.176-239.616t-44.032-202.752q-1.024-5.12-7.168-32.768t-11.264-52.224-9.216-47.104-4.096-32.768l1.024-10.24q9.216-3.072 105.472-18.432-2.048-24.576-9.216-56.32-6.144 0-18.432-1.024t-18.432-1.024q-16.384 0-50.176 6.144t-49.152 6.144q-78.848 1.024-117.76 1.024-28.672 0-80.896-5.12t-69.632-6.144z" />
<glyph unicode="&#xe809;" glyph-name="header" d="M961.536 8.704q-25.6 0-75.776 2.048t-76.8 2.048q-24.576 0-74.752-2.048t-75.776-2.048q-14.336 0-21.504 12.288t-7.168 25.6q0 17.408 9.216 26.624t22.528 9.216 29.696 4.096 25.6 9.216q18.432 11.264 18.432 79.872v223.232q0 12.288-1.024 17.408-7.168 3.072-28.672 3.072h-385.024q-22.528 0-29.696-3.072 0-5.12 0-17.408l-1.024-211.968q0-80.896 21.504-94.208 9.216-5.12 26.624-7.168t32.768-2.048 25.6-8.192 11.264-26.624q0-14.336-7.168-26.624t-20.48-13.312q-26.624 0-79.872 2.048t-78.848 2.048q-24.576 0-72.704-2.048t-72.704-2.048q-13.312 0-20.48 12.288t-7.168 25.6q0 17.408 9.216 25.6t20.48 10.24 26.624 4.096 24.576 9.216q18.432 13.312 18.432 81.92l-1.024 31.744v464.896q0 2.048 1.024 14.336t0 21.504-1.024 21.504-2.048 24.576-4.096 20.48-6.144 18.432-9.216 10.24q-8.192 5.12-25.6 6.144t-29.696 2.048-23.552 7.168-10.24 26.624q0 14.336 6.144 26.624t20.48 13.312q26.624 0 79.872-2.048t78.848-2.048q23.552 0 72.704 2.048t71.68 2.048q14.336 0 21.504-13.312t7.168-26.624q0-17.408-9.216-25.6t-22.528-8.192-28.672-2.048-24.576-7.168q-19.456-12.288-19.456-92.16l1.024-182.272q0-12.288 0-18.432 7.168-2.048 22.528-2.048h399.36q14.336 0 21.504 2.048 1.024 6.144 1.024 18.432v182.272q0 79.872-19.456 92.16-10.24 6.144-33.792 7.168t-37.888 7.168-14.336 28.672q0 14.336 7.168 26.624t21.504 13.312q24.576 0 75.776-2.048t74.752-2.048q24.576 0 73.728 2.048t73.728 2.048q14.336 0 21.504-13.312t7.168-26.624q0-17.408-10.24-25.6t-22.528-8.192-29.696-2.048-24.576-7.168q-20.48-13.312-20.48-92.16l1.024-538.624q0-67.584 19.456-79.872 9.216-6.144 25.6-7.168t30.72-3.072 23.552-9.216 10.24-24.576q0-15.36-6.144-27.648t-20.48-13.312z" />
<glyph unicode="&#xe80a;" glyph-name="align-left" d="M1024 192v-72.704q0-15.36-11.264-25.6t-25.6-11.264h-950.272q-15.36 0-25.6 11.264t-11.264 25.6v72.704q0 15.36 11.264 25.6t25.6 11.264h950.272q15.36 0 25.6-11.264t11.264-25.6zM804.864 411.136v-72.704q0-15.36-11.264-25.6t-25.6-11.264h-731.136q-15.36 0-25.6 11.264t-11.264 25.6v72.704q0 15.36 11.264 25.6t25.6 11.264h731.136q15.36 0 25.6-11.264t11.264-25.6zM951.296 631.296v-73.728q0-14.336-11.264-25.6t-25.6-11.264h-877.568q-15.36 0-25.6 11.264t-11.264 25.6v73.728q0 14.336 11.264 25.6t25.6 10.24h877.568q14.336 0 25.6-10.24t11.264-25.6zM731.136 850.432v-73.728q0-14.336-10.24-25.6t-25.6-10.24h-658.432q-15.36 0-25.6 10.24t-11.264 25.6v73.728q0 14.336 11.264 25.6t25.6 11.264h658.432q14.336 0 25.6-11.264t10.24-25.6z" />
<glyph unicode="&#xe80b;" glyph-name="align-center" d="M1024 192v-72.704q0-15.36-11.264-25.6t-25.6-11.264h-950.272q-15.36 0-25.6 11.264t-11.264 25.6v72.704q0 15.36 11.264 25.6t25.6 11.264h950.272q15.36 0 25.6-11.264t11.264-25.6zM804.864 411.136v-72.704q0-15.36-11.264-25.6t-25.6-11.264h-512q-14.336 0-25.6 11.264t-11.264 25.6v72.704q0 15.36 11.264 25.6t25.6 11.264h512q15.36 0 25.6-11.264t11.264-25.6zM951.296 631.296v-73.728q0-14.336-11.264-25.6t-25.6-11.264h-804.864q-14.336 0-25.6 11.264t-11.264 25.6v73.728q0 14.336 11.264 25.6t25.6 10.24h804.864q14.336 0 25.6-10.24t11.264-25.6zM731.136 850.432v-73.728q0-14.336-10.24-25.6t-25.6-10.24h-366.592q-14.336 0-25.6 10.24t-10.24 25.6v73.728q0 14.336 10.24 25.6t25.6 11.264h366.592q14.336 0 25.6-11.264t10.24-25.6z" />
<glyph unicode="&#xe80c;" glyph-name="align-right" d="M1024 192v-72.704q0-15.36-11.264-25.6t-25.6-11.264h-950.272q-15.36 0-25.6 11.264t-11.264 25.6v72.704q0 15.36 11.264 25.6t25.6 11.264h950.272q15.36 0 25.6-11.264t11.264-25.6zM1024 411.136v-72.704q0-15.36-11.264-25.6t-25.6-11.264h-731.136q-14.336 0-25.6 11.264t-11.264 25.6v72.704q0 15.36 11.264 25.6t25.6 11.264h731.136q15.36 0 25.6-11.264t11.264-25.6zM1024 631.296v-73.728q0-14.336-11.264-25.6t-25.6-11.264h-877.568q-14.336 0-25.6 11.264t-11.264 25.6v73.728q0 14.336 11.264 25.6t25.6 10.24h877.568q15.36 0 25.6-10.24t11.264-25.6zM1024 850.432v-73.728q0-14.336-11.264-25.6t-25.6-10.24h-658.432q-14.336 0-25.6 10.24t-10.24 25.6v73.728q0 14.336 10.24 25.6t25.6 11.264h658.432q15.36 0 25.6-11.264t11.264-25.6z" />
<glyph unicode="&#xe80d;" glyph-name="list-bullet" d="M219.136 155.136q0-45.056-31.744-77.824t-77.824-31.744-77.824 31.744-31.744 77.824 31.744 77.824 77.824 31.744 77.824-31.744 31.744-77.824zM219.136 448q0-46.080-31.744-77.824t-77.824-31.744-77.824 31.744-31.744 77.824 31.744 77.824 77.824 31.744 77.824-31.744 31.744-77.824zM1024 210.432v-109.568q0-7.168-5.12-13.312t-13.312-5.12h-694.272q-8.192 0-13.312 5.12t-5.12 13.312v109.568q0 7.168 5.12 12.288t13.312 6.144h694.272q7.168 0 13.312-6.144t5.12-12.288zM219.136 740.864q0-46.080-31.744-77.824t-77.824-31.744-77.824 31.744-31.744 77.824 31.744 77.824 77.824 31.744 77.824-31.744 31.744-77.824zM1024 503.296v-110.592q0-7.168-5.12-12.288t-13.312-5.12h-694.272q-8.192 0-13.312 5.12t-5.12 12.288v110.592q0 7.168 5.12 12.288t13.312 5.12h694.272q7.168 0 13.312-5.12t5.12-12.288zM1024 795.136v-109.568q0-7.168-5.12-12.288t-13.312-6.144h-694.272q-8.192 0-13.312 6.144t-5.12 12.288v109.568q0 8.192 5.12 13.312t13.312 5.12h694.272q7.168 0 13.312-5.12t5.12-13.312z" />
<glyph unicode="&#xe80e;" glyph-name="indent-left" d="M219.136 648.704v-328.704q0-7.168-5.12-13.312t-13.312-5.12q-7.168 0-12.288 5.12l-164.864 164.864q-5.12 5.12-5.12 13.312t5.12 13.312l164.864 163.84q5.12 5.12 12.288 5.12 8.192 0 13.312-5.12t5.12-13.312zM1024 210.432v-109.568q0-7.168-5.12-13.312t-13.312-5.12h-987.136q-7.168 0-13.312 5.12t-5.12 13.312v109.568q0 7.168 5.12 12.288t13.312 6.144h987.136q7.168 0 13.312-6.144t5.12-12.288zM1024 429.568v-109.568q0-7.168-5.12-13.312t-13.312-5.12h-621.568q-7.168 0-13.312 5.12t-5.12 13.312v109.568q0 7.168 5.12 13.312t13.312 5.12h621.568q7.168 0 13.312-5.12t5.12-13.312zM1024 648.704v-109.568q0-7.168-5.12-12.288t-13.312-6.144h-621.568q-7.168 0-13.312 6.144t-5.12 12.288v109.568q0 8.192 5.12 13.312t13.312 5.12h621.568q7.168 0 13.312-5.12t5.12-13.312zM1024 868.864v-109.568q0-8.192-5.12-13.312t-13.312-5.12h-987.136q-7.168 0-13.312 5.12t-5.12 13.312v109.568q0 7.168 5.12 12.288t13.312 6.144h987.136q7.168 0 13.312-6.144t5.12-12.288z" />
<glyph unicode="&#xe80f;" glyph-name="indent-right" d="M200.704 484.864q0-8.192-5.12-13.312l-163.84-164.864q-5.12-5.12-13.312-5.12-7.168 0-13.312 5.12t-5.12 13.312v328.704q0 8.192 5.12 13.312t13.312 5.12 13.312-5.12l163.84-163.84q5.12-5.12 5.12-13.312zM1024 210.432v-109.568q0-7.168-5.12-13.312t-13.312-5.12h-987.136q-7.168 0-13.312 5.12t-5.12 13.312v109.568q0 7.168 5.12 12.288t13.312 6.144h987.136q7.168 0 13.312-6.144t5.12-12.288zM1024 429.568v-109.568q0-7.168-5.12-13.312t-13.312-5.12h-621.568q-7.168 0-13.312 5.12t-5.12 13.312v109.568q0 7.168 5.12 13.312t13.312 5.12h621.568q7.168 0 13.312-5.12t5.12-13.312zM1024 648.704v-109.568q0-7.168-5.12-12.288t-13.312-6.144h-621.568q-7.168 0-13.312 6.144t-5.12 12.288v109.568q0 8.192 5.12 13.312t13.312 5.12h621.568q7.168 0 13.312-5.12t5.12-13.312zM1024 868.864v-109.568q0-8.192-5.12-13.312t-13.312-5.12h-987.136q-7.168 0-13.312 5.12t-5.12 13.312v109.568q0 7.168 5.12 12.288t13.312 6.144h987.136q7.168 0 13.312-6.144t5.12-12.288z" />
<glyph unicode="&#xe810;" glyph-name="list-numbered" d="M218.112 34.304q0-46.080-31.744-71.68t-76.8-26.624q-61.44 0-98.304 37.888l31.744 50.176q28.672-25.6 61.44-25.6 16.384 0 28.672 8.192t12.288 24.576q0 35.84-60.416 31.744l-14.336 31.744q4.096 6.144 18.432 24.576t24.576 31.744 20.48 21.504v1.024q-9.216 0-27.648-1.024t-27.648 0v-30.72h-60.416v87.040h190.464v-50.176l-54.272-66.56q28.672-6.144 46.080-27.648t17.408-50.176zM219.136 392.704v-91.136h-206.848q-4.096 20.48-4.096 30.72 0 29.696 14.336 53.248t31.744 38.912 37.888 27.648 31.744 24.576 14.336 25.6q0 14.336-9.216 22.528t-22.528 7.168q-25.6 0-46.080-32.768l-48.128 33.792q13.312 28.672 40.96 45.056t60.416 16.384q40.96 0 69.632-23.552t28.672-64.512q0-28.672-19.456-52.224t-43.008-36.864-43.008-28.672-20.48-30.72h72.704v34.816h60.416zM1024 210.432v-109.568q0-8.192-5.12-13.312t-13.312-5.12h-694.272q-8.192 0-13.312 5.12t-5.12 13.312v109.568q0 8.192 5.12 13.312t13.312 5.12h694.272q7.168 0 13.312-6.144t5.12-12.288zM219.136 724.48v-57.344h-191.488v57.344h61.44q0 22.528 0 69.632t1.024 68.608v7.168h-1.024q-5.12-10.24-28.672-30.72l-40.96 43.008 77.824 72.704h60.416v-230.4h61.44zM1024 503.296v-110.592q0-7.168-5.12-12.288t-13.312-5.12h-694.272q-8.192 0-13.312 5.12t-5.12 12.288v110.592q0 7.168 5.12 12.288t13.312 5.12h694.272q7.168 0 13.312-5.12t5.12-12.288zM1024 795.136v-109.568q0-7.168-5.12-12.288t-13.312-6.144h-694.272q-8.192 0-13.312 6.144t-5.12 12.288v109.568q0 8.192 5.12 13.312t13.312 5.12h694.272q7.168 0 13.312-5.12t5.12-13.312z" />
<glyph unicode="&#xe811;" glyph-name="underline" horiz-adv-x="878" d="M27.648 833.024q-21.504 1.024-25.6 2.048l-2.048 50.176q7.168 0 22.528 0 34.816 0 64.512-2.048 75.776-4.096 94.208-4.096 49.152 0 96.256 2.048 66.56 2.048 83.968 3.072 31.744 0 49.152 1.024l-1.024-8.192 1.024-36.864v-5.12q-33.792-5.12-70.656-5.12-33.792 0-45.056-14.336-7.168-7.168-7.168-74.752 0-8.192 0-18.432t0-15.36l1.024-131.072 8.192-159.744q3.072-70.656 28.672-114.688 20.48-33.792 55.296-53.248 50.176-26.624 100.352-26.624 59.392 0 109.568 16.384 31.744 10.24 56.32 28.672 27.648 20.48 37.888 36.864 20.48 31.744 29.696 64.512 12.288 41.984 12.288 131.072 0 45.056-2.048 73.728t-6.144 69.632-8.192 91.136l-2.048 33.792q-3.072 37.888-13.312 50.176-19.456 20.48-44.032 19.456l-57.344-1.024-8.192 2.048 1.024 49.152h48.128l116.736-6.144q44.032-2.048 112.64 6.144l10.24-2.048q3.072-21.504 3.072-28.672 0-4.096-2.048-17.408-25.6-7.168-48.128-8.192-41.984-6.144-45.056-9.216-8.192-9.216-8.192-23.552 0-4.096 0-15.36t1.024-17.408q5.12-11.264 13.312-226.304 3.072-111.616-9.216-174.080-8.192-43.008-23.552-69.632-21.504-36.864-63.488-70.656-43.008-32.768-104.448-50.176-62.464-19.456-145.408-19.456-95.232 0-162.816 26.624t-101.376 69.632q-34.816 43.008-48.128 111.616-9.216 45.056-9.216 135.168v190.464q0 107.52-9.216 121.856-14.336 20.48-83.968 21.504zM877.568 27.136v36.864q0 8.192-5.12 13.312t-13.312 5.12h-840.704q-8.192 0-13.312-5.12t-5.12-13.312v-36.864q0-8.192 5.12-13.312t13.312-5.12h840.704q8.192 0 13.312 5.12t5.12 13.312z" />
<glyph unicode="&#xe812;" glyph-name="table" horiz-adv-x="950" d="M292.864 173.568v109.568q0 8.192-5.12 13.312t-13.312 5.12h-183.296q-7.168 0-13.312-5.12t-5.12-13.312v-109.568q0-8.192 5.12-13.312t13.312-5.12h183.296q8.192 0 13.312 5.12t5.12 13.312zM292.864 392.704v110.592q0 7.168-5.12 12.288t-13.312 5.12h-183.296q-7.168 0-13.312-5.12t-5.12-12.288v-110.592q0-7.168 5.12-12.288t13.312-5.12h183.296q8.192 0 13.312 5.12t5.12 12.288zM584.704 173.568v109.568q0 8.192-5.12 13.312t-12.288 5.12h-183.296q-8.192 0-13.312-5.12t-5.12-13.312v-109.568q0-8.192 5.12-13.312t13.312-5.12h183.296q7.168 0 12.288 5.12t5.12 13.312zM292.864 612.864v109.568q0 8.192-5.12 13.312t-13.312 5.12h-183.296q-7.168 0-13.312-5.12t-5.12-13.312v-109.568q0-8.192 5.12-13.312t13.312-5.12h183.296q8.192 0 13.312 5.12t5.12 13.312zM584.704 392.704v110.592q0 7.168-5.12 12.288t-12.288 5.12h-183.296q-8.192 0-13.312-5.12t-5.12-12.288v-110.592q0-7.168 5.12-12.288t13.312-5.12h183.296q7.168 0 12.288 5.12t5.12 12.288zM877.568 173.568v109.568q0 8.192-5.12 13.312t-13.312 5.12h-182.272q-8.192 0-13.312-5.12t-5.12-13.312v-109.568q0-8.192 5.12-13.312t13.312-5.12h182.272q8.192 0 13.312 5.12t5.12 13.312zM584.704 612.864v109.568q0 8.192-5.12 13.312t-12.288 5.12h-183.296q-8.192 0-13.312-5.12t-5.12-13.312v-109.568q0-8.192 5.12-13.312t13.312-5.12h183.296q7.168 0 12.288 5.12t5.12 13.312zM877.568 392.704v110.592q0 7.168-5.12 12.288t-13.312 5.12h-182.272q-8.192 0-13.312-5.12t-5.12-12.288v-110.592q0-7.168 5.12-12.288t13.312-5.12h182.272q8.192 0 13.312 5.12t5.12 12.288zM877.568 612.864v109.568q0 8.192-5.12 13.312t-13.312 5.12h-182.272q-8.192 0-13.312-5.12t-5.12-13.312v-109.568q0-8.192 5.12-13.312t13.312-5.12h182.272q8.192 0 13.312 5.12t5.12 13.312zM951.296 795.136v-621.568q0-37.888-27.648-64.512t-64.512-26.624h-768q-36.864 0-64.512 26.624t-26.624 64.512v621.568q0 37.888 26.624 64.512t64.512 27.648h768q37.888 0 64.512-27.648t27.648-64.512z" />
<glyph unicode="&#xe813;" glyph-name="eraser" horiz-adv-x="1097" d="M512 155.136l192.512 220.16h-439.296l-192.512-220.16h439.296zM1090.56 770.56q9.216-19.456 6.144-40.96t-17.408-36.864l-512-585.728q-22.528-24.576-55.296-24.576h-439.296q-21.504 0-38.912 11.264t-27.648 31.744q-8.192 19.456-5.12 40.96t17.408 36.864l512 585.728q21.504 24.576 54.272 24.576h439.296q21.504 0 39.936-11.264t26.624-31.744z" />
<glyph unicode="&#xe814;" glyph-name="text-height" d="M996.352 155.136q19.456 0 24.576-10.24t-6.144-25.6l-72.704-92.16q-11.264-15.36-27.648-15.36t-27.648 15.36l-72.704 92.16q-11.264 15.36-6.144 25.6t23.552 10.24h46.080v585.728h-46.080q-18.432 0-23.552 10.24t6.144 25.6l72.704 92.16q11.264 15.36 27.648 15.36t27.648-15.36l72.704-92.16q11.264-15.36 6.144-25.6t-24.576-10.24h-45.056v-585.728h45.056zM46.080 886.272l30.72-15.36q7.168-3.072 120.832-3.072 25.6 0 75.776 1.024t74.752 1.024q21.504 0 61.44 0t61.44 0h167.936q3.072 0 12.288 0t11.264 0 9.216 1.024 10.24 5.12 8.192 10.24l24.576 1.024q2.048 0 7.168-1.024t8.192 0q1.024-63.488 1.024-191.488 0-46.080-2.048-62.464-22.528-8.192-38.912-10.24-14.336 24.576-31.744 72.704-1.024 5.12-6.144 27.648t-8.192 41.984-4.096 20.48q-3.072 4.096-7.168 7.168t-8.192 3.072-8.192 1.024-10.24 1.024-9.216-1.024q-9.216 0-37.888 1.024t-43.008 0-35.84-1.024-40.96-4.096q-5.12-46.080-4.096-76.8 0-54.272 1.024-222.208t1.024-260.096q0-9.216-1.024-40.96t0-52.224 7.168-38.912q22.528-12.288 70.656-24.576t68.608-21.504q2.048-22.528 2.048-28.672 0-8.192-1.024-16.384l-19.456-1.024q-44.032-1.024-124.928 5.12t-117.76 5.12q-28.672 0-87.040-5.12t-86.016-5.12q-2.048 29.696-2.048 29.696v5.12q9.216 15.36 34.816 24.576t56.32 17.408 45.056 15.36q10.24 23.552 10.24 218.112 0 58.368-1.024 173.056t-2.048 174.080v66.56q0 1.024 0 8.192t1.024 14.336-1.024 15.36-2.048 13.312-3.072 8.192q-6.144 7.168-92.16 7.168-18.432 0-53.248-7.168t-45.056-15.36q-11.264-7.168-19.456-40.96t-18.432-63.488-24.576-30.72q-23.552 15.36-31.744 25.6v218.112z" />
<glyph unicode="&#xe815;" glyph-name="brush" d="M922.624 960q39.936 0 70.656-26.624t29.696-66.56q0-35.84-25.6-86.016-189.44-359.424-266.24-430.080-55.296-52.224-123.904-52.224-72.704 0-123.904 53.248t-52.224 124.928q0 73.728 53.248 121.856l364.544 330.752q33.792 30.72 73.728 30.72zM403.456 369.152q22.528-43.008 60.416-74.752t86.016-43.008l1.024-40.96q2.048-121.856-73.728-197.632t-199.68-76.8q-69.632 0-123.904 26.624t-88.064 72.704-49.152 104.448-16.384 125.952q4.096-3.072 23.552-17.408t35.84-25.6 32.768-20.48 26.624-9.216q23.552 0 31.744 20.48 14.336 37.888 32.768 64.512t39.936 43.008 50.176 27.648 58.368 14.336 71.68 6.144z" />
<glyph unicode="&#xe816;" glyph-name="pencil" horiz-adv-x="878" d="M207.872 82.432l51.2 52.224-134.144 134.144-52.224-52.224v-61.44h73.728v-72.704h61.44zM505.856 612.864q0 12.288-12.288 12.288-5.12 0-9.216-4.096l-310.272-309.248q-4.096-4.096-4.096-10.24 0-12.288 13.312-12.288 5.12 0 9.216 4.096l310.272 309.248q3.072 4.096 3.072 10.24zM475.136 722.432l237.568-237.568-475.136-476.16h-237.568v238.592zM865.28 667.136q0-29.696-20.48-51.2l-95.232-95.232-237.568 238.592 95.232 94.208q20.48 21.504 51.2 21.504 29.696 0 52.224-21.504l134.144-134.144q20.48-22.528 20.48-52.224z" />
<glyph unicode="&#xe817;" glyph-name="minus" horiz-adv-x="804" d="M804.864 539.136v-109.568q0-22.528-16.384-38.912t-38.912-15.36h-694.272q-23.552 0-38.912 15.36t-16.384 38.912v109.568q0 23.552 16.384 38.912t38.912 16.384h694.272q22.528 0 38.912-16.384t16.384-38.912z" />
<glyph unicode="&#xe818;" glyph-name="picture" horiz-adv-x="1097" d="M365.568 631.296q0-46.080-31.744-77.824t-77.824-32.768-77.824 32.768-31.744 77.824 31.744 76.8 77.824 32.768 77.824-32.768 31.744-76.8zM951.296 411.136v-256h-804.864v109.568l182.272 183.296 92.16-91.136 291.84 291.84zM1005.568 813.568h-914.432q-7.168 0-12.288-5.12t-6.144-13.312v-694.272q0-8.192 6.144-13.312t12.288-5.12h914.432q7.168 0 13.312 5.12t5.12 13.312v694.272q0 7.168-5.12 13.312t-13.312 5.12zM1096.704 795.136v-694.272q0-37.888-26.624-64.512t-64.512-27.648h-914.432q-36.864 0-64.512 27.648t-26.624 64.512v694.272q0 37.888 26.624 64.512t64.512 27.648h914.432q37.888 0 64.512-27.648t26.624-64.512z" />
<glyph unicode="&#xe819;" glyph-name="file-image" horiz-adv-x="878" d="M838.656 742.912q16.384-16.384 27.648-43.008t11.264-51.2v-657.408q0-23.552-15.36-38.912t-38.912-16.384h-768q-23.552 0-38.912 16.384t-16.384 38.912v913.408q0 23.552 16.384 38.912t38.912 16.384h512q22.528 0 50.176-11.264t43.008-27.648zM584.704 882.176v-215.040h215.040q-5.12 16.384-12.288 23.552l-179.2 179.2q-6.144 7.168-23.552 12.288zM804.864 8.704v585.728h-237.568q-23.552 0-38.912 15.36t-16.384 38.912v238.592h-439.296v-878.592h732.16zM731.136 264.704v-182.272h-584.704v109.568l109.568 109.568 72.704-72.704 220.16 219.136zM256 375.296q-46.080 0-77.824 31.744t-31.744 77.824 31.744 77.824 77.824 31.744 77.824-31.744 31.744-77.824-31.744-77.824-77.824-31.744z" />
<glyph unicode="&#xe81a;" glyph-name="cw" horiz-adv-x="878" d="M877.568 813.568v-256q0-14.336-10.24-25.6t-26.624-11.264h-256q-23.552 0-32.768 23.552-10.24 22.528 7.168 38.912l78.848 78.848q-83.968 78.848-198.656 78.848-59.392 0-113.664-23.552t-93.184-62.464-63.488-93.184-22.528-113.664 22.528-113.664 63.488-93.184 93.184-62.464 113.664-23.552q67.584 0 128 29.696t102.4 83.968q4.096 6.144 13.312 7.168 8.192 0 14.336-5.12l77.824-78.848q5.12-4.096 6.144-11.264t-5.12-13.312q-61.44-75.776-150.528-116.736t-186.368-41.984q-89.088 0-171.008 34.816t-139.264 94.208-94.208 140.288-34.816 169.984 34.816 169.984 94.208 140.288 139.264 94.208 171.008 34.816q83.968 0 161.792-31.744t140.288-90.112l73.728 73.728q16.384 18.432 39.936 8.192 22.528-9.216 22.528-33.792z" />
<glyph unicode="&#xe81b;" glyph-name="ccw" horiz-adv-x="878" d="M877.568 448q0-89.088-34.816-169.984t-93.184-140.288-140.288-94.208-169.984-34.816q-98.304 0-187.392 41.984t-150.528 116.736q-4.096 6.144-4.096 13.312t5.12 11.264l77.824 78.848q6.144 5.12 14.336 5.12 9.216-1.024 13.312-7.168 41.984-54.272 102.4-83.968t129.024-29.696q59.392 0 112.64 23.552t94.208 62.464 62.464 93.184 22.528 113.664-22.528 113.664-62.464 93.184-94.208 62.464-112.64 23.552q-56.32 0-107.52-20.48t-92.16-58.368l78.848-78.848q17.408-16.384 8.192-38.912-10.24-23.552-33.792-23.552h-256q-15.36 0-25.6 11.264t-11.264 25.6v256q0 24.576 22.528 33.792 22.528 10.24 39.936-8.192l73.728-73.728q61.44 58.368 140.288 90.112t162.816 31.744q89.088 0 169.984-34.816t140.288-94.208 93.184-140.288 34.816-169.984z" />
<glyph unicode="&#xe900;" glyph-name="omega" d="M704 64h256l64 128v-256h-384v214.214c131.112 56.484 224 197.162 224 361.786 0 214.432-157.598 382.266-352 382.266-194.406 0-352-167.832-352-382.266 0-164.624 92.886-305.302 224-361.786v-214.214h-384v256l64-128h256v32.59c-187.63 66.46-320 227.402-320 415.41 0 247.424 229.23 448 512 448s512-200.576 512-448c0-188.008-132.37-348.95-320-415.41v-32.59z" />
<glyph unicode="&#xe901;" glyph-name="cancel-circle" d="M512 960c-282.77 0-512-229.23-512-512s229.23-512 512-512 512 229.23 512 512-229.23 512-512 512zM512 32c-229.75 0-416 186.25-416 416s186.25 416 416 416 416-186.25 416-416-186.25-416-416-416zM672 704l-160-160-160 160-96-96 160-160-160-160 96-96 160 160 160-160 96 96-160 160 160 160z" />
<glyph unicode="&#xe904;" glyph-name="newspaper" d="M896 704v128h-896v-704c0-35.346 28.654-64 64-64h864c53.022 0 96 42.978 96 96v544h-128zM832 128h-768v640h768v-640zM128 640h640v-64h-640zM512 512h256v-64h-256zM512 384h256v-64h-256zM512 256h192v-64h-192zM128 512h320v-320h-320z" />
<glyph unicode="&#xe90f;" glyph-name="camera" d="M304 352c0-114.876 93.124-208 208-208s208 93.124 208 208-93.124 208-208 208-208-93.124-208-208zM960 704h-224c-16 64-32 128-96 128h-256c-64 0-80-64-96-128h-224c-35.2 0-64-28.8-64-64v-576c0-35.2 28.8-64 64-64h896c35.2 0 64 28.8 64 64v576c0 35.2-28.8 64-64 64zM512 68c-156.85 0-284 127.148-284 284 0 156.85 127.15 284 284 284 156.852 0 284-127.15 284-284 0-156.852-127.146-284-284-284zM960 512h-128v64h128v-64z" />
<glyph unicode="&#xe911;" glyph-name="music" d="M960 960h64v-736c0-88.366-100.29-160-224-160s-224 71.634-224 160c0 88.368 100.29 160 224 160 62.684 0 119.342-18.4 160-48.040v368.040l-512-113.778v-494.222c0-88.366-100.288-160-224-160s-224 71.634-224 160c0 88.368 100.288 160 224 160 62.684 0 119.342-18.4 160-48.040v624.040l576 128z" />
<glyph unicode="&#xe912;" glyph-name="play" d="M981.188 799.892c-143.632 20.65-302.332 32.108-469.186 32.108-166.86 0-325.556-11.458-469.194-32.108-27.53-107.726-42.808-226.75-42.808-351.892 0-125.14 15.278-244.166 42.808-351.89 143.638-20.652 302.336-32.11 469.194-32.11 166.854 0 325.552 11.458 469.186 32.11 27.532 107.724 42.812 226.75 42.812 351.89 0 125.142-15.28 244.166-42.812 351.892zM384.002 256v384l320-192-320-192z" />
<glyph unicode="&#xe914;" glyph-name="video-camera" d="M384 672c0 88.366 71.634 160 160 160s160-71.634 160-160c0-88.366-71.634-160-160-160s-160 71.634-160 160zM0 672c0 88.366 71.634 160 160 160s160-71.634 160-160c0-88.366-71.634-160-160-160s-160 71.634-160 160zM768 352v96c0 35.2-28.8 64-64 64h-640c-35.2 0-64-28.8-64-64v-320c0-35.2 28.8-64 64-64h640c35.2 0 64 28.8 64 64v96l256-160v448l-256-160zM640 192h-512v192h512v-192z" />
<glyph unicode="&#xe92b;" glyph-name="file-zip" d="M917.806 730.924c-22.208 30.292-53.174 65.7-87.178 99.704s-69.412 64.964-99.704 87.178c-51.574 37.82-76.592 42.194-90.924 42.194h-496c-44.112 0-80-35.888-80-80v-864c0-44.112 35.884-80 80-80h736c44.112 0 80 35.888 80 80v624c0 14.332-4.372 39.35-42.194 90.924v0 0zM785.374 785.374c30.7-30.7 54.8-58.398 72.58-81.374h-153.954v153.946c22.98-17.78 50.678-41.878 81.374-72.572v0 0zM896 16c0-8.672-7.328-16-16-16h-736c-8.672 0-16 7.328-16 16v864c0 8.672 7.328 16 16 16 0 0 495.956 0.002 496 0v-224c0-17.672 14.322-32 32-32h224v-624zM256 896h128v-64h-128v64zM384 832h128v-64h-128v64zM256 768h128v-64h-128v64zM384 704h128v-64h-128v64zM256 640h128v-64h-128v64zM384 576h128v-64h-128v64zM256 512h128v-64h-128v64zM384 448h128v-64h-128v64zM256 112c0-26.4 21.6-48 48-48h160c26.4 0 48 21.6 48 48v160c0 26.4-21.6 48-48 48h-80v64h-128v-272zM448 192v-64h-128v64h128z" />
<glyph unicode="&#xe92e;" glyph-name="stack" d="M1024 640l-512 256-512-256 512-256 512 256zM512 811.030l342.058-171.030-342.058-171.030-342.058 171.030 342.058 171.030zM921.444 499.278l102.556-51.278-512-256-512 256 102.556 51.278 409.444-204.722zM921.444 307.278l102.556-51.278-512-256-512 256 102.556 51.278 409.444-204.722z" />
<glyph unicode="&#xe93f;" glyph-name="credit-card" d="M928 832h-832c-52.8 0-96-43.2-96-96v-576c0-52.8 43.2-96 96-96h832c52.8 0 96 43.2 96 96v576c0 52.8-43.2 96-96 96zM96 768h832c17.346 0 32-14.654 32-32v-96h-896v96c0 17.346 14.654 32 32 32zM928 128h-832c-17.346 0-32 14.654-32 32v288h896v-288c0-17.346-14.654-32-32-32zM128 320h64v-128h-64zM256 320h64v-128h-64zM384 320h64v-128h-64z" />
<glyph unicode="&#xe944;" glyph-name="address-book" d="M192 960v-1024h768v1024h-768zM576 703.67c70.51 0 127.67-57.16 127.67-127.67s-57.16-127.67-127.67-127.67-127.67 57.16-127.67 127.67 57.16 127.67 127.67 127.67v0zM768 192h-384v64c0 70.696 57.306 128 128 128v0h128c70.696 0 128-57.304 128-128v-64zM64 896h96v-192h-96v192zM64 640h96v-192h-96v192zM64 384h96v-192h-96v192zM64 128h96v-192h-96v192z" />
<glyph unicode="&#xe945;" glyph-name="envelop" d="M928 832h-832c-52.8 0-96-43.2-96-96v-640c0-52.8 43.2-96 96-96h832c52.8 0 96 43.2 96 96v640c0 52.8-43.2 96-96 96zM398.74 409.628l-270.74-210.892v501.642l270.74-290.75zM176.38 704h671.24l-335.62-252-335.62 252zM409.288 398.302l102.712-110.302 102.71 110.302 210.554-270.302h-626.528l210.552 270.302zM625.26 409.628l270.74 290.75v-501.642l-270.74 210.892z" />
<glyph unicode="&#xe947;" glyph-name="location" d="M512 960c-176.732 0-320-143.268-320-320 0-320 320-704 320-704s320 384 320 704c0 176.732-143.27 320-320 320zM512 448c-106.040 0-192 85.96-192 192s85.96 192 192 192 192-85.96 192-192-85.96-192-192-192z" />
<glyph unicode="&#xe95c;" glyph-name="drawer" d="M1016.988 307.99l-256 320c-6.074 7.592-15.266 12.010-24.988 12.010h-448c-9.72 0-18.916-4.418-24.988-12.010l-256-320c-4.538-5.674-7.012-12.724-7.012-19.99v-288c0-35.346 28.654-64 64-64h896c35.348 0 64 28.654 64 64v288c0 7.266-2.472 14.316-7.012 19.99zM960 256h-224l-128-128h-192l-128 128h-224v20.776l239.38 299.224h417.24l239.38-299.224v-20.776zM736 448h-448c-17.672 0-32 14.328-32 32s14.328 32 32 32h448c17.674 0 32-14.328 32-32s-14.326-32-32-32zM800 320h-576c-17.672 0-32 14.326-32 32s14.328 32 32 32h576c17.674 0 32-14.326 32-32s-14.326-32-32-32z" />
<glyph unicode="&#xe960;" glyph-name="download" d="M512 384l256 256h-192v256h-128v-256h-192zM744.726 488.728l-71.74-71.742 260.080-96.986-421.066-157.018-421.066 157.018 260.080 96.986-71.742 71.742-279.272-104.728v-256l512-192 512 192v256z" />
<glyph unicode="&#xe961;" glyph-name="upload" d="M448 384h128v256h192l-256 256-256-256h192zM640 528v-98.712l293.066-109.288-421.066-157.018-421.066 157.018 293.066 109.288v98.712l-384-144v-256l512-192 512 192v256z" />
<glyph unicode="&#xe977;" glyph-name="quotes-left" d="M225 512c123.712 0 224-100.29 224-224 0-123.712-100.288-224-224-224s-224 100.288-224 224l-1 32c0 247.424 200.576 448 448 448v-128c-85.474 0-165.834-33.286-226.274-93.726-11.634-11.636-22.252-24.016-31.83-37.020 11.438 1.8 23.16 2.746 35.104 2.746zM801 512c123.71 0 224-100.29 224-224 0-123.712-100.29-224-224-224s-224 100.288-224 224l-1 32c0 247.424 200.576 448 448 448v-128c-85.474 0-165.834-33.286-226.274-93.726-11.636-11.636-22.254-24.016-31.832-37.020 11.44 1.8 23.16 2.746 35.106 2.746z" />
<glyph unicode="&#xe98b;" glyph-name="enlarge2" d="M1024 960v-416l-160 160-192-192-96 96 192 192-160 160zM448 288l-192-192 160-160h-416v416l160-160 192 192z" />
<glyph unicode="&#xe98c;" glyph-name="shrink2" d="M448 384v-416l-160 160-192-192-96 96 192 192-160 160zM1024 864l-192-192 160-160h-416v416l160-160 192 192z" />
<glyph unicode="&#xe98f;" glyph-name="lock" d="M592 512h-16v192c0 105.87-86.13 192-192 192h-128c-105.87 0-192-86.13-192-192v-192h-16c-26.4 0-48-21.6-48-48v-480c0-26.4 21.6-48 48-48h544c26.4 0 48 21.6 48 48v480c0 26.4-21.6 48-48 48zM192 704c0 35.29 28.71 64 64 64h128c35.29 0 64-28.71 64-64v-192h-256v192z" />
<glyph unicode="&#xe990;" glyph-name="unlocked" d="M768 896c105.87 0 192-86.13 192-192v-192h-128v192c0 35.29-28.71 64-64 64h-128c-35.29 0-64-28.71-64-64v-192h16c26.4 0 48-21.6 48-48v-480c0-26.4-21.6-48-48-48h-544c-26.4 0-48 21.6-48 48v480c0 26.4 21.6 48 48 48h400v192c0 105.87 86.13 192 192 192h128z" />
<glyph unicode="&#xe991;" glyph-name="wrench" d="M1002.934 142.124l-460.552 394.76c21.448 40.298 33.618 86.282 33.618 135.116 0 159.058-128.942 288-288 288-29.094 0-57.172-4.332-83.646-12.354l166.39-166.39c24.89-24.89 24.89-65.62 0-90.51l-101.49-101.49c-24.89-24.89-65.62-24.89-90.51 0l-166.39 166.39c-8.022-26.474-12.354-54.552-12.354-83.646 0-159.058 128.942-288 288-288 48.834 0 94.818 12.17 135.116 33.62l394.76-460.552c22.908-26.724 62.016-28.226 86.904-3.338l101.492 101.492c24.888 24.888 23.386 63.994-3.338 86.902z" />
<glyph unicode="&#xe9ce;" glyph-name="eye" d="M512 768c-223.318 0-416.882-130.042-512-320 95.118-189.958 288.682-320 512-320 223.312 0 416.876 130.042 512 320-95.116 189.958-288.688 320-512 320zM764.45 598.296c60.162-38.374 111.142-89.774 149.434-150.296-38.292-60.522-89.274-111.922-149.436-150.296-75.594-48.218-162.89-73.704-252.448-73.704-89.56 0-176.858 25.486-252.452 73.704-60.158 38.372-111.138 89.772-149.432 150.296 38.292 60.524 89.274 111.924 149.434 150.296 3.918 2.5 7.876 4.922 11.86 7.3-9.96-27.328-15.41-56.822-15.41-87.596 0-141.382 114.616-256 256-256 141.382 0 256 114.618 256 256 0 30.774-5.452 60.268-15.408 87.598 3.978-2.378 7.938-4.802 11.858-7.302v0zM512 544c0-53.020-42.98-96-96-96s-96 42.98-96 96 42.98 96 96 96 96-42.982 96-96z" />
<glyph unicode="&#xe9d1;" glyph-name="eye-blocked" d="M945.942 945.942c-18.746 18.744-49.136 18.744-67.882 0l-202.164-202.164c-51.938 15.754-106.948 24.222-163.896 24.222-223.318 0-416.882-130.042-512-320 41.122-82.124 100.648-153.040 173.022-207.096l-158.962-158.962c-18.746-18.746-18.746-49.136 0-67.882 9.372-9.374 21.656-14.060 33.94-14.060s24.568 4.686 33.942 14.058l864 864c18.744 18.746 18.744 49.138 0 67.884zM416 640c42.24 0 78.082-27.294 90.92-65.196l-121.724-121.724c-37.902 12.838-65.196 48.68-65.196 90.92 0 53.020 42.98 96 96 96zM110.116 448c38.292 60.524 89.274 111.924 149.434 150.296 3.918 2.5 7.876 4.922 11.862 7.3-9.962-27.328-15.412-56.822-15.412-87.596 0-54.89 17.286-105.738 46.7-147.418l-60.924-60.924c-52.446 36.842-97.202 83.882-131.66 138.342zM768 518c0 27.166-4.256 53.334-12.102 77.898l-321.808-321.808c24.568-7.842 50.742-12.090 77.91-12.090 141.382 0 256 114.618 256 256zM830.026 670.026l-69.362-69.362c1.264-0.786 2.53-1.568 3.786-2.368 60.162-38.374 111.142-89.774 149.434-150.296-38.292-60.522-89.274-111.922-149.436-150.296-75.594-48.218-162.89-73.704-252.448-73.704-38.664 0-76.902 4.76-113.962 14.040l-76.894-76.894c59.718-21.462 123.95-33.146 190.856-33.146 223.31 0 416.876 130.042 512 320-45.022 89.916-112.118 166.396-193.974 222.026z" />
<glyph unicode="&#xe9df;" glyph-name="happy" d="M512-64c282.77 0 512 229.23 512 512s-229.23 512-512 512-512-229.23-512-512 229.23-512 512-512zM512 864c229.75 0 416-186.25 416-416s-186.25-416-416-416-416 186.25-416 416 186.25 416 416 416zM512 361.24c115.95 0 226.23 30.806 320 84.92-14.574-178.438-153.128-318.16-320-318.16-166.868 0-305.422 139.872-320 318.304 93.77-54.112 204.050-85.064 320-85.064zM256 608c0 53.019 28.654 96 64 96s64-42.981 64-96c0-53.019-28.654-96-64-96s-64 42.981-64 96zM640 608c0 53.019 28.654 96 64 96s64-42.981 64-96c0-53.019-28.654-96-64-96s-64 42.981-64 96z" />
<glyph unicode="&#xea4e;" glyph-name="command" d="M736 64c-88.224 0-160 71.776-160 160v96h-128v-96c0-88.224-71.776-160-160-160s-160 71.776-160 160 71.776 160 160 160h96v128h-96c-88.224 0-160 71.776-160 160s71.776 160 160 160 160-71.776 160-160v-96h128v96c0 88.224 71.776 160 160 160s160-71.776 160-160-71.776-160-160-160h-96v-128h96c88.224 0 160-71.776 160-160s-71.774-160-160-160zM640 320v-96c0-52.934 43.066-96 96-96s96 43.066 96 96-43.066 96-96 96h-96zM288 320c-52.934 0-96-43.066-96-96s43.066-96 96-96 96 43.066 96 96v96h-96zM448 384h128v128h-128v-128zM640 576h96c52.934 0 96 43.066 96 96s-43.066 96-96 96-96-43.066-96-96v-96zM288 768c-52.934 0-96-43.066-96-96s43.066-96 96-96h96v96c0 52.934-43.064 96-96 96z" />
<glyph unicode="&#xea5c;" glyph-name="font2" d="M799.596 943.792c-90.526 0-148.62 16.208-241.848 16.208-301.284 0-441.792-171.584-441.792-345.872 0-102.678 48.64-136.458 144.564-136.458-6.758 14.864-18.914 31.080-18.914 104.034 0 204.010 77.006 263.458 175.636 267.51 0 0-80.918-793.374-315.778-888.542v-24.672h316.594l108.026 512h197.844l44.072 128h-214.908l51.944 246.19c59.446-12.156 117.542-24.316 167.532-24.316 62.148 0 118.894 18.914 149.968 162.126-37.826-12.16-78.362-16.208-122.94-16.208z" />
<glyph unicode="&#xea65;" glyph-name="strikethrough" d="M1024 448v-64h-234.506c27.504-38.51 42.506-82.692 42.506-128 0-70.878-36.66-139.026-100.58-186.964-59.358-44.518-137.284-69.036-219.42-69.036-82.138 0-160.062 24.518-219.42 69.036-63.92 47.938-100.58 116.086-100.58 186.964h128c0-69.382 87.926-128 192-128s192 58.618 192 128c0 69.382-87.926 128-192 128h-512v64h299.518c-2.338 1.654-4.656 3.324-6.938 5.036-63.92 47.94-100.58 116.086-100.58 186.964s36.66 139.024 100.58 186.964c59.358 44.518 137.282 69.036 219.42 69.036 82.136 0 160.062-24.518 219.42-69.036 63.92-47.94 100.58-116.086 100.58-186.964h-128c0 69.382-87.926 128-192 128s-192-58.618-192-128c0-69.382 87.926-128 192-128 78.978 0 154.054-22.678 212.482-64h299.518z" />
<glyph unicode="&#xea67;" glyph-name="sigma" d="M941.606 225.292l44.394 94.708h38l-64-384h-960v74.242l331.546 391.212-331.546 331.546v227h980l44-256h-34.376l-18.72 38.88c-35.318 73.364-61.904 89.12-138.904 89.12h-662l353.056-353.056-297.42-350.944h542.364c116.008 0 146.648 41.578 173.606 97.292z" />
<glyph unicode="&#xea68;" glyph-name="sigma2" d="M941.606 225.292l44.394 94.708h38l-64-384h-960v74.242l331.546 391.212-331.546 331.546v227h980l44-256h-34.376l-18.72 38.88c-35.318 73.364-61.904 89.12-138.904 89.12h-662l353.056-353.056-297.42-350.944h542.364c116.008 0 146.648 41.578 173.606 97.292z" />
<glyph unicode="&#xeade;" glyph-name="libreoffice" d="M534.626 937.372c-12.444 12.444-37.026 22.628-54.626 22.628h-384c-17.6 0-32-14.4-32-32v-960c0-17.6 14.4-32 32-32h768c17.6 0 32 14.4 32 32v576c0 17.6-10.182 42.182-22.626 54.626l-338.748 338.746zM832 0h-704v896h351.158c2.916-0.48 8.408-2.754 10.81-4.478l337.556-337.554c1.722-2.402 3.996-7.894 4.476-10.81v-543.158zM864 960h-192c-17.6 0-21.818-10.182-9.374-22.626l210.746-210.746c12.446-12.446 22.628-8.228 22.628 9.372v192c0 17.6-14.4 32-32 32z" />
<glyph unicode="&#xf00e;" glyph-name="search-plus" horiz-adv-x="951" d="M585.143 493.714v-36.571q0-7.429-5.429-12.857t-12.857-5.429h-128v-128q0-7.429-5.429-12.857t-12.857-5.429h-36.571q-7.429 0-12.857 5.429t-5.429 12.857v128h-128q-7.429 0-12.857 5.429t-5.429 12.857v36.571q0 7.429 5.429 12.857t12.857 5.429h128v128q0 7.429 5.429 12.857t12.857 5.429h36.571q7.429 0 12.857-5.429t5.429-12.857v-128h128q7.429 0 12.857-5.429t5.429-12.857zM658.286 475.428q0 105.714-75.143 180.857t-180.857 75.143-180.857-75.143-75.143-180.857 75.143-180.857 180.857-75.143 180.857 75.143 75.143 180.857zM950.857 0q0-30.286-21.429-51.714t-51.714-21.429q-30.857 0-51.429 21.714l-196 195.429q-102.286-70.857-228-70.857-81.714 0-156.286 31.714t-128.571 85.714-85.714 128.571-31.714 156.286 31.714 156.286 85.714 128.571 128.571 85.714 156.286 31.714 156.286-31.714 128.571-85.714 85.714-128.571 31.714-156.286q0-125.714-70.857-228l196-196q21.143-21.143 21.143-51.429z" />
<glyph unicode="&#xf010;" glyph-name="search-minus" horiz-adv-x="951" d="M585.143 493.714v-36.571q0-7.429-5.429-12.857t-12.857-5.429h-329.143q-7.429 0-12.857 5.429t-5.429 12.857v36.571q0 7.429 5.429 12.857t12.857 5.429h329.143q7.429 0 12.857-5.429t5.429-12.857zM658.286 475.428q0 105.714-75.143 180.857t-180.857 75.143-180.857-75.143-75.143-180.857 75.143-180.857 180.857-75.143 180.857 75.143 75.143 180.857zM950.857 0q0-30.286-21.429-51.714t-51.714-21.429q-30.857 0-51.429 21.714l-196 195.429q-102.286-70.857-228-70.857-81.714 0-156.286 31.714t-128.571 85.714-85.714 128.571-31.714 156.286 31.714 156.286 85.714 128.571 128.571 85.714 156.286 31.714 156.286-31.714 128.571-85.714 85.714-128.571 31.714-156.286q0-125.714-70.857-228l196-196q21.143-21.143 21.143-51.429z" />
<glyph unicode="&#xf014;" glyph-name="trash-o" horiz-adv-x="805" d="M292.571 530.286v-329.143q0-8-5.143-13.143t-13.143-5.143h-36.571q-8 0-13.143 5.143t-5.143 13.143v329.143q0 8 5.143 13.143t13.143 5.143h36.571q8 0 13.143-5.143t5.143-13.143zM438.857 530.286v-329.143q0-8-5.143-13.143t-13.143-5.143h-36.571q-8 0-13.143 5.143t-5.143 13.143v329.143q0 8 5.143 13.143t13.143 5.143h36.571q8 0 13.143-5.143t5.143-13.143zM585.143 530.286v-329.143q0-8-5.143-13.143t-13.143-5.143h-36.571q-8 0-13.143 5.143t-5.143 13.143v329.143q0 8 5.143 13.143t13.143 5.143h36.571q8 0 13.143-5.143t5.143-13.143zM658.286 116.571v541.714h-512v-541.714q0-12.571 4-23.143t8.286-15.429 6-4.857h475.429q1.714 0 6 4.857t8.286 15.429 4 23.143zM274.286 731.428h256l-27.429 66.857q-4 5.143-9.714 6.286h-181.143q-5.714-1.143-9.714-6.286zM804.571 713.143v-36.571q0-8-5.143-13.143t-13.143-5.143h-54.857v-541.714q0-47.429-26.857-82t-64.571-34.571h-475.429q-37.714 0-64.571 33.429t-26.857 80.857v544h-54.857q-8 0-13.143 5.143t-5.143 13.143v36.571q0 8 5.143 13.143t13.143 5.143h176.571l40 95.429q8.571 21.143 30.857 36t45.143 14.857h182.857q22.857 0 45.143-14.857t30.857-36l40-95.429h176.571q8 0 13.143-5.143t5.143-13.143z" />
<glyph unicode="&#xf039;" glyph-name="align-justify" d="M1024 182.857v-73.143q0-14.857-10.857-25.714t-25.714-10.857h-950.857q-14.857 0-25.714 10.857t-10.857 25.714v73.143q0 14.857 10.857 25.714t25.714 10.857h950.857q14.857 0 25.714-10.857t10.857-25.714zM1024 402.286v-73.143q0-14.857-10.857-25.714t-25.714-10.857h-950.857q-14.857 0-25.714 10.857t-10.857 25.714v73.143q0 14.857 10.857 25.714t25.714 10.857h950.857q14.857 0 25.714-10.857t10.857-25.714zM1024 621.714v-73.143q0-14.857-10.857-25.714t-25.714-10.857h-950.857q-14.857 0-25.714 10.857t-10.857 25.714v73.143q0 14.857 10.857 25.714t25.714 10.857h950.857q14.857 0 25.714-10.857t10.857-25.714zM1024 841.143v-73.143q0-14.857-10.857-25.714t-25.714-10.857h-950.857q-14.857 0-25.714 10.857t-10.857 25.714v73.143q0 14.857 10.857 25.714t25.714 10.857h950.857q14.857 0 25.714-10.857t10.857-25.714z" />
<glyph unicode="&#xf07d;" glyph-name="arrows-v" horiz-adv-x="439" d="M402.286 768q0-14.857-10.857-25.714t-25.714-10.857h-73.143v-585.143h73.143q14.857 0 25.714-10.857t10.857-25.714-10.857-25.714l-146.286-146.286q-10.857-10.857-25.714-10.857t-25.714 10.857l-146.286 146.286q-10.857 10.857-10.857 25.714t10.857 25.714 25.714 10.857h73.143v585.143h-73.143q-14.857 0-25.714 10.857t-10.857 25.714 10.857 25.714l146.286 146.286q10.857 10.857 25.714 10.857t25.714-10.857l146.286-146.286q10.857-10.857 10.857-25.714z" />
<glyph unicode="&#xf108;" glyph-name="desktop" horiz-adv-x="1097" d="M1024 384v475.429q0 7.429-5.429 12.857t-12.857 5.429h-914.286q-7.429 0-12.857-5.429t-5.429-12.857v-475.429q0-7.429 5.429-12.857t12.857-5.429h914.286q7.429 0 12.857 5.429t5.429 12.857zM1097.143 859.428v-621.714q0-37.714-26.857-64.571t-64.571-26.857h-310.857q0-21.143 9.143-44.286t18.286-40.571 9.143-24.857q0-14.857-10.857-25.714t-25.714-10.857h-292.571q-14.857 0-25.714 10.857t-10.857 25.714q0 8 9.143 25.143t18.286 40 9.143 44.571h-310.857q-37.714 0-64.571 26.857t-26.857 64.571v621.714q0 37.714 26.857 64.571t64.571 26.857h914.286q37.714 0 64.571-26.857t26.857-64.571z" />
<glyph unicode="&#xf10a;" glyph-name="tablet" horiz-adv-x="658" d="M365.714 146.286q0 14.857-10.857 25.714t-25.714 10.857-25.714-10.857-10.857-25.714 10.857-25.714 25.714-10.857 25.714 10.857 10.857 25.714zM585.143 237.714v548.571q0 7.429-5.429 12.857t-12.857 5.429h-475.429q-7.429 0-12.857-5.429t-5.429-12.857v-548.571q0-7.429 5.429-12.857t12.857-5.429h475.429q7.429 0 12.857 5.429t5.429 12.857zM658.286 786.286v-621.714q0-37.714-26.857-64.571t-64.571-26.857h-475.429q-37.714 0-64.571 26.857t-26.857 64.571v621.714q0 37.714 26.857 64.571t64.571 26.857h475.429q37.714 0 64.571-26.857t26.857-64.571z" />
</font></defs></svg>

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.
Binary file not shown.
+9 -6
View File
@@ -22,13 +22,16 @@ MenuManager.refreshMenus = function (user) {
let matterListMenu = new Menu('全部文件', '/', false, 'fa fa-th')
menus.push(matterListMenu)
//网站设置
let preferenceMenu = new Menu('网站偏好', '/preference', false, 'fa fa-dashboard')
menus.push(preferenceMenu)
if(user.role === 'ADMINISTRATOR'){
//网站设置
let preferenceMenu = new Menu('网站偏好', '/preference', false, 'fa fa-dashboard')
menus.push(preferenceMenu)
//用户列表
let userMenu = new Menu('用户列表', '/user/list', false, 'fa fa-user')
menus.push(userMenu)
}
//用户列表
let userMenu = new Menu('用户列表', '/user/list', false, 'fa fa-user')
menus.push(userMenu)
//退出登录
let logoutMenu = new Menu('退出登录', '/user/login', false, 'fa fa-power-off')
+23 -6
View File
@@ -1,9 +1,11 @@
import BaseEntity from '../base/BaseEntity'
import Filter from '../base/Filter'
import { Notification,Message } from 'element-ui'
import {getMimeType, MimeUtil} from '../../util/MimeUtil'
import {containStr, endWith, getExtension, startWith} from '../../filter/str'
import User from '../user/User'
import UserInputSelection from '../../../backyard/user/widget/UserInputSelection'
import Vue from "vue"
export default class Matter extends BaseEntity {
constructor(args) {
@@ -11,18 +13,20 @@ export default class Matter extends BaseEntity {
this.puuid = null
this.userUuid = null
this.dir = false
this.alien = false
this.name = null
this.md5 = null
this.size = 0
this.privacy = true
this.path = null
//本地操作变量
this.check = false //作为勾选变量
/*
这部分是辅助UI的字段信息
*/
//作为勾选变量
this.check = false
//允许用户选择的文件类型
this.filter = "*"
//本地字段
@@ -42,7 +46,7 @@ export default class Matter extends BaseEntity {
getFilters() {
return [
new Filter(Filter.prototype.Type.INPUT, '父级菜单uuid', 'puuid', null, null, false),
new Filter(Filter.prototype.Type.HTTP_INPUT_SELECTION, '用户', 'userUuid', null, User, true, UserInputSelection),
new Filter(Filter.prototype.Type.HTTP_INPUT_SELECTION, '用户', 'userUuid', null, User, false, UserInputSelection),
new Filter(Filter.prototype.Type.INPUT, '关键字', 'name'),
new Filter(Filter.prototype.Type.CHECK, '文件夹', 'dir'),
new Filter(Filter.prototype.Type.SORT, '文件夹', 'orderDir'),
@@ -57,6 +61,7 @@ export default class Matter extends BaseEntity {
static URL_MATTER_DELETE = '/matter/delete'
static URL_MATTER_DELETE_BATCH = '/matter/delete/batch'
static URL_MATTER_RENAME = '/matter/rename'
static URL_CHANGE_PRIVACY = '/matter/change/privacy'
static URL_MATTER_MOVE = '/matter/move'
static URL_MATTER_DOWNLOAD = '/matter/download'
static URL_MATTER_UPLOAD = '/matter/upload'
@@ -127,6 +132,15 @@ export default class Matter extends BaseEntity {
}, errorCallback)
}
httpChangePrivacy(privacy, successCallback, errorCallback) {
let that = this
this.httpPost(Matter.URL_CHANGE_PRIVACY, {'uuid': this.uuid, 'privacy': privacy}, function (response) {
that.privacy = privacy
Message.success(response.data.msg)
typeof successCallback === 'function' && successCallback(response)
}, errorCallback)
}
httpMove(srcUuids, destUuid, successCallback, errorCallback) {
let form = {'srcUuids': srcUuids}
if (destUuid) {
@@ -277,6 +291,8 @@ export default class Matter extends BaseEntity {
formData.append('userUuid', that.userUuid)
formData.append('puuid', that.puuid)
formData.append('file', that.file)
formData.append('alien', that.alien)
formData.append('privacy', that.privacy)
//闭包
@@ -284,7 +300,6 @@ export default class Matter extends BaseEntity {
let lastSize = 0
that.httpPost(Matter.URL_MATTER_UPLOAD, formData, function (response) {
//上传到tank服务器成功了,更新matterUuid.
that.uuid = response.data.data.uuid
if (typeof successCallback === "function") {
@@ -293,8 +308,6 @@ export default class Matter extends BaseEntity {
}, function (response) {
console.log("上传到tank服务器失败", response.data)
console.log(response)
that.errorMessage = '上传出错,请稍后重试'
that.clear()
@@ -345,4 +358,8 @@ export default class Matter extends BaseEntity {
}
getDownloadUrl() {
return Vue.http.options.root + '/alien/download/' + this.uuid + '/' + this.name
}
}
+26 -24
View File
@@ -1,24 +1,19 @@
import BaseEntity from '../base/BaseEntity'
import Tank from '../tank/Tank'
export default class Preference extends BaseEntity {
constructor (args) {
constructor(args) {
super(args)
//网站名称
this.name = null
//logo
this.logoUrl = null
this.logoTankUuid = null
this.faviconUrl = null
this.faviconTankUuid = null
//底部第一行文字
this.footerLine1 = null
this.footerLine2 = null
this.logoTank = new Tank('image', false, 1024 * 1024, '图片不能超过1M')
this.faviconTank = new Tank('.ico', false, 1024 * 1024, '图片不能超过1M')
this.validatorSchema = {
name: {
@@ -30,42 +25,49 @@ export default class Preference extends BaseEntity {
static URL_API_PREFERENCE_FETCH = '/preference/fetch'
render (obj) {
render(obj) {
super.render(obj)
this.renderEntity('logoTank', Tank)
this.renderEntity('faviconTank', Tank)
}
getForm () {
getForm() {
return {
name: this.name,
logoUrl: this.logoUrl,
logoTankUuid: this.logoTankUuid,
faviconUrl: this.faviconUrl,
faviconTankUuid: this.faviconTankUuid,
footerLine1: this.footerLine1,
footerLine2: this.footerLine2
}
}
validate(){
if (this.logoTank) {
this.logoTankUuid = this.logoTank.uuid
this.logoUrl = this.logoTank.url
}
if (this.faviconTank) {
this.faviconTankUuid = this.faviconTank.uuid
this.faviconUrl = this.faviconTank.url
}
validate() {
return super.validate()
}
httpFetch (successCallback, errorCallback) {
httpFetch(successCallback, errorCallback) {
let that = this
this.httpPost(Preference.URL_API_PREFERENCE_FETCH,{},function (response) {
this.httpPost(Preference.URL_API_PREFERENCE_FETCH, {}, function (response) {
that.render(response.data.data)
that.updateTitleAndFavicon()
typeof successCallback === 'function' && successCallback(response)
},errorCallback)
}, errorCallback)
}
//修改title和favicon
updateTitleAndFavicon() {
if (this.faviconUrl) {
//修改favicon
let link = document.querySelector("link[rel*='icon']") || document.createElement('link');
link.type = 'image/x-icon';
link.rel = 'shortcut icon';
link.href = this.faviconUrl;
document.getElementsByTagName('head')[0].appendChild(link);
}
document.title = this.name
}
}
-54
View File
@@ -1,54 +0,0 @@
import BaseEntity from '../base/BaseEntity'
import Filter from '../base/Filter'
import { simpleDateTime } from '../../filter/time'
import Tank from '../tank/Tank'
export default class Tag extends BaseEntity {
constructor (args) {
super(args)
this.userUuid = null
this.name = null
this.logoTank = new Tank('image', false, 1024 * 1024, '图片不能超过1M')
this.logoTankUuid = null
this.logoUrl = null
this.validatorSchema = {
name: {
rules: [{required: true, message: '名称必填'}, {min: 1, max: 45, message: '名称最长45字'}],
error: null
}
}
}
render(obj){
super.render(obj)
this.renderEntity('logoTank',Tank)
}
getFilters () {
return [
new Filter(Filter.prototype.Type.SORT, '排序', 'orderSort'),
new Filter(Filter.prototype.Type.INPUT, '名称', 'name'),
new Filter(Filter.prototype.Type.INPUT, '用户ID', 'userUuid', null, null, false, null)
]
}
getForm(){
return{
name: this.name,
logoTankUuid: this.logoTankUuid,
logoUrl: this.logoUrl,
uuid: this.uuid ? this.uuid : null
}
}
validate () {
if(this.logoTank){
this.logoTankUuid = this.logoTank.uuid
this.logoUrl = this.logoTank.url
}
return super.validate()
}
}
-356
View File
@@ -1,356 +0,0 @@
import BaseEntity from '../base/BaseEntity'
import {containStr, endWith, getExtension, startWith} from '../../filter/str'
import Vue from 'vue'
import {getMimeType} from "../../util/MimeUtil";
//当前tank处于怎样的步骤中
let Procedure = {
'FREE': 'FREE',
'UPLOADING': 'UPLOADING',
'DOWNLOADING': 'DOWNLOADING'
}
export default class Tank extends BaseEntity {
constructor(filter = '*', privacy = true, maxSize = 0, uploadHint = null) {
super()
/*
此部分是数据库中的字段
*/
this.userUuid = null
this.name = null
this.matterUuid = null
this.size = 0
this.privacy = privacy
this.url = null
this.remark = null
this.confirmed = false
/*
此部分是上传的地址和token,临时信息。
*/
this.uploadTokenUuid = null
this.uploadUrl = null
/*
这部分是辅助UI的字段信息
*/
//文件的类型,这个一般是由文件名推测出来的。
this.type = null
//允许用户选择的文件类型
this.filter = filter
//本地字段
//允许上传的最大大小。
this.maxSize = maxSize
//给用户的提示文字
this.uploadHint = uploadHint
//浏览器中选择好的原生file,未作任何处理。
this.file = null
this.disabled = false
//当前文件处于哪一个步骤中
this.procedure = Procedure.FREE
//当前上传进度的数值 0-1之间
this.progress = 0
//实时上传速度 byte/s
this.speed = 0
}
static URL_UPLOAD = '/matter/upload'
render(obj) {
super.render(obj)
this.type = getMimeType(this.name)
}
getForm() {
return {
filename: this.name,
privacy: this.privacy,
size: this.size
}
}
//从file中装填metaData
validate() {
if (!this.file) {
this.errorMessage = '请选择上传文件'
return false
}
this.name = this.file.name
if (!this.name) {
this.errorMessage = '请选择上传文件'
return false
}
if(this.file.size > this.maxSize){
this.errorMessage = '文件超出指定大小'
return false
}
this.size = this.file.size
this.type = getMimeType(this.name)
this.type = this.file.type
if (!this.type) {
this.type = getMimeType(this.name)
}
this.errorMessage = null
return true
}
//具有了这最基本的3种属性,才能叫做“存在”
exist() {
return this.name && this.size && this.confirmed
}
//公有图片链接。
publicImgUrl() {
if (!this.exist()) {
return null
}
if (!this.privacy && this.confirmed) {
if (startWith(this.type, 'image')) {
return this.url
} else {
return null
}
} else {
return null
}
}
//文件图标。在富文本编辑器中,我们使用图片,其他地方使用图标来表示。
fileIcon(inEditor = false) {
let host = window.location.protocol + "//" + window.location.host;
//给不同的文件准备不同的图标
if (startWith(this.type, 'application/pdf')) {
if (inEditor) {
return host + '/static/img/file/pdf.png'
} else {
return 'fa fa-file-pdf-o color-pdf'
}
}
if (startWith(this.type, 'application/msword') || startWith(this.type, 'application/vnd.openxmlformats-officedocument.wordprocessingml.document')) {
if (inEditor) {
return host + '/static/img/file/doc.png'
} else {
return 'fa fa-file-word-o color-doc'
}
}
if (startWith(this.type, 'application/vnd.ms-powerpoint') || startWith(this.type, 'application/vnd.openxmlformats-officedocument.presentationml.presentation')) {
if (inEditor) {
return host + '/static/img/file/ppt.png'
} else {
return 'fa fa-file-powerpoint-o color-ppt'
}
}
if (startWith(this.type, 'application/vnd.ms-excel') || startWith(this.type, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')) {
if (inEditor) {
return host + '/static/img/file/xls.png'
} else {
return 'fa fa-file-excel-o color-xls'
}
}
if (startWith(this.type, 'audio')) {
if (inEditor) {
return host + '/static/img/file/audio.png'
} else {
return 'fa fa-file-audio-o color-audio'
}
}
if (startWith(this.type, 'video')) {
if (inEditor) {
return host + '/static/img/file/video.png'
} else {
return 'fa fa-file-movie-o color-video'
}
}
if (startWith(this.type, 'text')) {
if (inEditor) {
return host + '/static/img/file/text.png'
} else {
return 'fa fa-file-text-o color-text'
}
}
if (startWith(this.type, 'image')) {
if (inEditor) {
return host + '/static/img/file/image.png'
} else {
return 'fa fa-file-image-o color-image'
}
}
if (endWith(this.name, 'zip') || endWith(this.name, 'rar') || endWith(this.name, '7z') || endWith(this.name, 'gz')) {
if (inEditor) {
return host + '/static/img/file/archive.png'
} else {
return 'fa fa-file-archive-o color-archive'
}
}
if (inEditor) {
return host + '/static/img/file/file.png'
} else {
return 'fa fa-file-o text-success'
}
}
//验证过滤器有没有误填写,这个方法主要给开发者使用。
validateFilter() {
let filter = this.filter
if (filter === null || filter === '') {
this.errorMessage = '过滤器设置错误,请检查-1'
console.error('过滤器设置错误,请检查.-1')
return false
}
if (filter !== '*') {
let regex1 = /^(image|audio|video|text)(\|(image|audio|video|text))*$/g
let regex2 = /^(\.[\w]+)(\|\.[\w]+)*$/
// 测试几种特殊类型 image|audio|video|text
if (!regex1.test(filter)) {
//测试后缀名
if (!regex2.test(filter)) {
this.errorMessage = '过滤器设置错误,请检查-2'
console.error('过滤器设置错误,请检查.-2')
return false
}
}
}
//validate privacy
let privacy = this.privacy
if (privacy !== true) {
if (privacy !== false) {
this.errorMessage = 'privacy属性为Boolean类型'
console.error('privacy属性为Boolean类型.')
return false
}
}
return true
}
//验证用户上传的文件是否符合过滤器
validateFileType() {
if (!this.filter) {
this.errorMessage = '该过滤条件有问题'
return false
}
if (this.filter === '*') {
this.errorMessage = null
return true
}
let extension = getExtension(this.name)
let simpleType = this.type.substring(0, this.type.indexOf('/'))
//专门解决android微信浏览器中名字乱命名的bug.
if (startWith(this.name, 'image%3A')) {
extension = 'jpg'
simpleType = 'image'
} else if (startWith(this.name, 'video%3A')) {
extension = 'mp4'
simpleType = 'video'
} else if (startWith(this.name, 'audio%3A')) {
extension = 'mp3'
simpleType = 'audio'
}
if (containStr(this.filter, extension)) {
this.errorMessage = null
return true
}
if (simpleType) {
if (containStr(this.filter, simpleType)) {
this.errorMessage = null
return true
}
}
this.errorMessage = '您上传的文件格式不符合要求'
return false
}
//在上传的途中,清空一切,从头开始。
clear() {
//filter,privacy不变
let newTank = new Tank()
newTank.filter = this.filter
newTank.privacy = this.privacy
newTank.errorMessage = this.errorMessage
newTank.uploadHint = this.uploadHint
newTank.maxSize = this.maxSize
this.render(newTank)
}
//文件上传
httpUpload(successCallback, failureCallback) {
let that = this
//验证是否装填好
if (!this.validate()) {
return
}
//验证用户填写的过滤条件是否正确
if (!this.validateFilter()) {
return
}
//验证是否满足过滤器
if (!this.validateFileType()) {
return
}
//(兼容性:chromeffIE9及以上)
let formData = new FormData()
formData.append('uploadTokenUuid', that.uploadTokenUuid)
formData.append('file', that.file)
that.procedure = Procedure.UPLOADING
that.httpPost(that.uploadUrl, formData, function (response) {
//上传到tank服务器成功了,更新matterUuid.
that.matterUuid = response.data.data.uuid
}, function (response) {
console.log("上传到tank服务器失败", response.data)
console.log(response)
that.procedure = Procedure.FREE
that.errorMessage = '上传出错,请稍后重试'
that.clear()
that.defaultErrorHandler(response, failureCallback)
}, {
progress: function (event) {
//上传进度。
that.progress = event.loaded / event.total
}
})
}
}
Tank.prototype.Procedure = Procedure
+7 -3
View File
@@ -77,6 +77,8 @@ export default class User extends BaseEntity {
this.avatarUrl = null
this.lastIp = null
this.lastTime = null
//默认大小限制100Mb.
this.sizeLimit = 104857600
this.status = Status.USER_STATUS_OK
//local fields
@@ -205,10 +207,12 @@ export default class User extends BaseEntity {
getForm() {
let form = {
avatarUrl: this.avatarUrl,
username: this.username,
password: this.password,
email: this.email,
gender: this.gender
gender: this.gender,
sizeLimit: this.sizeLimit
}
if (this.phone) {
@@ -239,9 +243,9 @@ export default class User extends BaseEntity {
this.render(new User())
//菜单刷新一次。
/*//菜单刷新一次。
this.refreshMenus()
*/
this.clearLocalStorage()
}
+2 -3
View File
@@ -50,7 +50,7 @@ const router = new Router({
breadcrumbs: []
}
},
{
/*{
path: 'user/profile/:uuid',
name: 'UserProfile',
component: UserDetail,
@@ -64,7 +64,7 @@ const router = new Router({
}
]
}
},
},*/
{
path: 'user/list',
name: 'UserList',
@@ -154,7 +154,6 @@ const router = new Router({
]
}
},
{
path: 'preference',
name: 'PreferenceIndex',
-13
View File
@@ -1,13 +0,0 @@
import $ from "jquery";
//check whether an obj is number.
export function smoothScroll(dom) {
let that = this;
if (!dom) {
console.error("使用smoothScroll必须指定dom.");
}
$('html, body').animate({
scrollTop: $(dom).offset().top
}, 500);
}
-186
View File
@@ -1,186 +0,0 @@
<template>
<div>
<div v-if="!pager.loading">
<Multiselect v-model="innerTags"
tag-placeholder="点击添加"
placeholder="搜索或添加"
selectedLabel="已选"
deselectLabel="点击移除"
selectLabel="点击选择"
:options="options"
label="name"
:multiple="true"
:taggable="taggable"
:max="max"
@tag="addTag"
@select="select"
>
<span class="italic" slot="maxElements">
最多只能选择 {{max}}
</span>
<span class="italic" slot="noResult">
没有符合条件的条目
</span>
</Multiselect>
</div>
<div v-if="pager.loading">
<i class="fa fa-spinner fa-spin fa-fw"></i>
</div>
</div>
</template>
<script>
//文档;http://monterail.github.io/vue-multiselect/
import Multiselect from 'vue-multiselect'
import 'vue-multiselect/dist/vue-multiselect.min.css'
import Pager from '../../common/model/base/Pager'
export default {
data () {
return {
innerTags: [],
options: [],
pager: new Pager(this.Clazz, 50)
}
},
props: {
//我们的备选项来自这个Clazz.
Clazz: {
type: Function,
required: false,
'default': null
},
tags: {
type: Array,
'default': () => []
},
//允许选中的最大数量
max: {
type: Number,
'default': 10
},
//允许自定义输入
taggable: {
type: Boolean,
'default': true
},
//列表的过滤条件
initFilter: {
type: Object,
required: false
}
},
components: {
Multiselect
},
watch: {
'innerTags' (newVal, oldVal) {
//清空tags
this.tags.splice(0, this.tags.length)
//把innerTags中所有的item追加过来
this.tags.push.apply(this.tags, this.innerTags)
},
'tags' (newVal, oldVal) {
this.fillInnerTags()
}
},
methods: {
refresh () {
let that = this
if (!this.Clazz) {
return
}
this.pager.httpFastPage(function () {
let list = that.pager.getList()
if (list && list.length > 0) {
that.options.splice(0, that.options.length)
list.forEach(item => {
that.options.push(item)
})
}
})
},
//用tags的元素去装填innerTags
fillInnerTags () {
if (this.isTagsEqual()) {
//Event from inner.
} else {
//Event from outer
//清空innerTags
this.innerTags.splice(0, this.innerTags.length)
//把tags中所有的item追加过来
this.innerTags.push.apply(this.innerTags, this.tags)
}
},
//判断innerTags和tags是否一样
isTagsEqual () {
let that = this
if (this.innerTags.length !== this.tags.length) {
return false
}
this.innerTags.forEach(item => {
if (that.tags.indexOf(item) === -1) {
return false
}
})
return true
},
//手动输入标签
addTag (newTag) {
this.innerTags.push(newTag)
},
//标签选中的回掉函数
select (newTag) {
}
},
mounted () {
this.fillInnerTags()
if (this.initFilter) {
for (let key in this.initFilter) {
if (this.initFilter.hasOwnProperty(key)) {
this.pager.setFilterValue(key, this.initFilter[key])
}
}
}
this.refresh()
}
}
</script>
<style lang="less" rel="stylesheet/less">
.multiselect {
&.multiselect--active {
z-index: 1100;
}
.multiselect__content {
z-index: 1100;
}
}
</style>
-192
View File
@@ -1,192 +0,0 @@
<template>
<div class="nb-tank-block">
<NbExpanding>
<div v-show="edit && tank.procedure === tank.Procedure.FREE && !tank.exist()">
<div>
<span class="btn btn-primary btn-sm btn-file">
<slot name="button">
<i class="fa fa-folder-open-o"></i>
<span>选择文件</span>
</slot>
<input ref="refFile" type="file" name="avatar" @change.prevent.stop="fileChanged"/>
</span>
</div>
<div class="mt5 italic" v-if="!tank.errorMessage && tank.uploadHint">
<i class="fa fa-info-circle"></i> {{tank.uploadHint}}
</div>
<div class="mt5 " v-if="tank.errorMessage">
<i class="fa fa-warning text-danger"></i> <span class="text-danger">{{tank.errorMessage}}</span>
</div>
</div>
</NbExpanding>
<NbExpanding>
<div class="huge-block clearfix"
v-if="tank.procedure === tank.Procedure.UPLOADING">
<div class="media">
<div class="pull-right">
<i class="btn-action f16 fa fa-trash text-danger" @click.stop.prevent="del()"></i>
</div>
<div class="media-body">{{tank.file.name}}</div>
</div>
<div class="progress" :class="{'progress-striped active' : tank.procedure === tank.Procedure.UPLOADING}">
<div :style="'width: '+(tank.progress*100)+'%'" class="progress-bar progress-bar-primary">
<span>已上传 {{(tank.progress * 100).toFixed(1)}}%</span>
</div>
</div>
<div>
已上传:{{ (tank.file.size * tank.progress).toFixed(0) | humanFileSize }}/{{ tank.file.size | humanFileSize}}
速度:{{tank.speed | humanFileSize}}/s
</div>
</div>
</NbExpanding>
<NbExpanding>
<div class="tiny-block"
v-if="tank.exist()">
<div class="w200 p10 mb10 bg-white br5 border" v-show="preview && tank.publicImgUrl()">
<img class="wp100" :src="tank.publicImgUrl()"/>
</div>
<div>
<i class="f16" v-show="tank.fileIcon() && !tank.publicImgUrl()" :class="[tank.fileIcon()]"></i>
<span class="f14 black">
{{tank.name}}
</span>
<span>
{{tank.size | humanFileSize}}
</span>
<span v-if="edit">
<i class="btn-action f16 fa fa-trash text-danger" @click.stop.prevent="del()"></i>
</span>
</div>
</div>
</NbExpanding>
</div>
</template>
<script>
import {startWith, endWith, getExtension, containStr} from '../../common/filter/str'
import Tank from '../../common/model/tank/Tank'
import $ from 'jquery'
import {MessageBox, Notification} from 'element-ui'
import NbExpanding from './NbExpanding.vue'
export default {
data() {
return {}
},
props: {
//上传的照片是否需要预览
preview: {
type: Boolean,
required: false,
'default': true
},
//当前是否是编辑状态(编辑状态可以上传,非编辑状态只能下载)
edit: {
type: Boolean,
required: false,
'default': true
},
tank: {
type: Tank,
required: true
},
uploadSuccessCallback: {
type: Function,
required: false
}
},
components: {
NbExpanding
},
computed: {},
methods: {
fileChanged() {
let that = this
let value = that.$refs['refFile'].value
if (!value) {
return
}
this.beginUpload(this.$refs['refFile'].files[0])
},
beginUpload(file) {
let that = this
this.tank.file = file
this.tank.httpUpload(function (response) {
if (typeof that.uploadSuccessCallback === 'function') {
that.uploadSuccessCallback(that.tank)
}
}, function () {
console.error('上传失败啦')
that.clear()
})
},
del() {
let that = this
MessageBox.confirm('是否删除此文件?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(function () {
that.clear()
},
function () {
}
)
},
clear() {
let that = this
that.tank.clear()
that.$refs['refFile'].value = ''
}
},
mounted() {
}
}
</script>
<style lang="less" rel="stylesheet/less">
.nb-tank-block {
.huge-block {
background-color: white;
border-radius: 5px;
padding: 10px;
border: 1px solid #eeeeee;
.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>
-228
View File
@@ -1,228 +0,0 @@
<template>
<div class="nb-tanks-block">
<div class="tank-block" v-for="(tank,tankIndex) in tanks">
<NbExpanding>
<div v-show="tank.procedure === tank.Procedure.FETCHING_UPLOAD_TOKEN">
<i class="fa fa-spinner fa-spin fa-fw"></i> 准备上传中...
</div>
</NbExpanding>
<NbExpanding>
<div class="huge-block clearfix"
v-if="tank.procedure === tank.Procedure.UPLOADING">
<div class="media">
<div class="pull-right">
<i class="btn-action f16 fa fa-trash text-danger" @click.stop.prevent="del(tank,tankIndex)"></i>
</div>
<div class="media-body">{{tank.file.name}}</div>
</div>
<div class="progress" :class="{'progress-striped active' : tank.procedure === tank.Procedure.UPLOADING}">
<div :style="'width: '+(tank.progress*100)+'%'" class="progress-bar progress-bar-primary">
<span>已上传 {{(tank.progress * 100).toFixed(1)}}%</span>
</div>
</div>
<div>
已上传:{{ (tank.file.size * tank.progress).toFixed(0) | humanFileSize }}/{{ tank.file.size | humanFileSize}} 速度:{{tank.speed | humanFileSize}}/s
</div>
</div>
</NbExpanding>
<NbExpanding>
<div class="tiny-block"
v-if="tank.exist()">
<div class="w200 p10 mb10 bg-white br5 border" v-show="tank.publicImgUrl()">
<img class="wp100" :src="tank.publicImgUrl()"/>
</div>
<div>
<i class="f16" v-show="tank.fileIcon() && !tank.publicImgUrl()" :class="[tank.fileIcon()]"></i>
<span class="f14 black cursor hover-underline" @click.stop.prevent="tank.download()">
{{tank.name}}
</span>
<span>
{{tank.size | humanFileSize}}
</span>
<span>
<i class="btn-action f16 fa fa-download text-success" @click.stop.prevent="tank.download()"></i>
</span>
<span v-if="edit">
<i class="btn-action f16 fa fa-trash text-danger" @click.stop.prevent="del(tank,tankIndex)"></i>
</span>
</div>
</div>
</NbExpanding>
</div>
<div
v-show="tanks.length < maxNum && edit && templateTank.procedure === templateTank.Procedure.FREE && !templateTank.exist()">
<div>
<span class="btn btn-primary btn-sm btn-file">
<slot name="button">
<i class="fa fa-folder-open-o"></i>
<span>选择文件</span>
</slot>
<input ref="refFile" type="file" name="avatar" @change.prevent.stop="fileChanged"/>
</span>
</div>
<div class="mt5 italic" v-if="!templateTank.errorMessage && templateTank.uploadHint">
<i class="fa fa-info-circle"></i> {{templateTank.uploadHint}}
</div>
<div class="mt5 " v-if="templateTank.errorMessage">
<i class="fa fa-warning text-danger"></i> <span class="text-danger">{{templateTank.errorMessage}}</span>
</div>
</div>
</div>
</template>
<script>
import { startWith, endWith, getExtension, containStr } from '../../common/filter/str'
import Tank from '../../common/model/tank/Tank'
import $ from 'jquery'
import { MessageBox, Notification } from 'element-ui'
import NbExpanding from './NbExpanding.vue'
export default {
data () {
return {}
},
props: {
tanks: {
type: Array,
required: true,
'default': []
},
edit: {
type: Boolean,
required: false,
'default': true
},
maxNum: {
type: Number,
required: false,
'default': 9
},
templateTank: {
type: Tank,
required: false,
'default': function () {
return new Tank('*', true)
},
validator: function (tank) {
return tank.validateFilter()
}
},
success: {
type: Function,
required: false
},
remove: {
type: Function,
required: false
}
},
components: {
NbExpanding
},
computed: {},
methods: {
fileChanged () {
let that = this
let tank = new Tank('*', true)
tank.render(this.templateTank)
tank.file = this.$refs['refFile'].files[0]
that.$refs['refFile'].value = ''
//提前验证,有错误及时显示
if (!tank.validate()) {
this.templateTank.errorMessage = tank.errorMessage
console.error(tank.errorMessage)
return
} else {
this.templateTank.errorMessage = null
}
this.tanks.push(tank)
tank.httpUpload(function () {
if (that.success) {
that.success(tank)
}
}, function () {
console.error('上传失败啦')
//一次检查哪些失败了,失败了的移除掉。
for (let i = 0; i < that.tanks.length; i++) {
let itemTank = that.tanks[i]
if (itemTank.errorMessage) {
that.templateTank.errorMessage = itemTank.errorMessage
that.tanks.splice(i, 1)
}
}
})
},
del (tank, tankIndex) {
let that = this
console.log('del')
console.log(tank)
MessageBox.confirm('是否删除此文件?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(function () {
tank.clear()
if (that.remove) {
that.remove(tank)
}
that.tanks.splice(tankIndex, 1)
},
function () {
}
)
}
},
mounted () {
}
}
</script>
<style lang="less" rel="stylesheet/less">
.nb-tanks-block {
.tank-block {
transition-duration: 0.3s;
margin: 5px 0;
.huge-block {
background-color: white;
border-radius: 5px;
border: 1px solid #eeeeee;
padding: 10px;
.progress {
margin-bottom: 10px;
}
}
}
}
</style>
@@ -1,9 +1,9 @@
<template>
<div class="nb-filter-http-input-selection" v-show="filter.visible">
<div class="nb-filter-http-input-selection" v-show="filter.visible">
<component v-bind:is="filter.component" :activeItem="activeItem"/>
<component v-bind:is="filter.component" :activeItem="activeItem"/>
</div>
</div>
</template>
@@ -14,7 +14,7 @@
import NbPager from '../NbPager.vue'
export default {
data () {
data() {
return {
show: false,
activeItem: new (this.filter.Clazz)()
@@ -44,7 +44,8 @@
NbPager
},
watch: {
'activeItem.uuid' (newVal, oldVal) {
'activeItem.uuid'(newVal, oldVal) {
if (newVal) {
this.filter.value = this.activeItem.uuid
@@ -54,20 +55,28 @@
this.callback && this.callback()
}
},
'filter.value'(newVal, oldVal) {
if (newVal && newVal === this.activeItem.uuid) {
//inner change. ignore
} else {
//outer change.
this.activeItem.uuid = newVal
}
}
},
computed: {},
methods: {},
mounted () {
mounted() {
}
}
</script>
<style lang="less" rel="stylesheet/less">
.nb-filter-http-input-selection {
.nb-filter-http-input-selection {
}
}
</style>
</style>
+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1514189634329" class="icon" style="" viewBox="0 0 1219 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10648" xmlns:xlink="http://www.w3.org/1999/xlink" width="238.0859375" height="200"><defs><style type="text/css"></style></defs><path d="M1197.787429 327.192381a19.504762 19.504762 0 0 1 19.553523 19.407238v614.156191c0 34.913524-28.574476 63.24419-63.878095 63.24419H63.878095C28.623238 1024 0 995.718095 0 960.75581V346.599619a19.504762 19.504762 0 0 1 19.602286-19.358476h1178.185143z m-66.80381-213.089524C1179.550476 114.102857 1219.047619 153.209905 1219.047619 201.386667v80.213333H1.657905V88.259048C1.657905 39.497143 41.593905 0 90.794667 0h290.864762c17.408 0 33.987048 7.655619 45.104761 20.967619l78.214096 93.135238h626.005333z" fill="#1ab394" p-id="10649"></path></svg>

After

Width:  |  Height:  |  Size: 943 B