refactor(front): 重构前端组件和 API
- 更新了多个组件的样式和结构 - 重命名了一些 API 文件 - 添加了新的 API 接口 - 优化了部分代码的可读性和性能
This commit is contained in:
+3
-3
@@ -2,21 +2,21 @@ import request from '@/utils/request'
|
||||
|
||||
export function startPipeline() {
|
||||
return request({
|
||||
url: 'api/devops/pipeline/start',
|
||||
url: 'api/devops/pipelineInstance/start',
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
|
||||
export function restartPipeline() {
|
||||
return request({
|
||||
url: 'api/devops/pipeline/restart',
|
||||
url: 'api/devops/pipelineInstance/restart',
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
|
||||
export function queryLastPipelineDetail(instanceId) {
|
||||
return request({
|
||||
url: 'api/devops/pipeline/last',
|
||||
url: 'api/devops/pipelineInstance/last',
|
||||
method: 'post',
|
||||
data: {
|
||||
instanceId
|
||||
@@ -0,0 +1,9 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function getPipelineTemplate(id) {
|
||||
return request({
|
||||
url: 'api/devops/pipelineTemplate/getPipelineTemplate',
|
||||
method: 'post',
|
||||
data: { id }
|
||||
})
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import request from '@/utils/request'
|
||||
import { encrypt } from '@/utils/rsaEncrypt'
|
||||
import { encrypt } from '@/utils/CsRsaUtil'
|
||||
|
||||
export function add(data) {
|
||||
return request({
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
<el-breadcrumb class="app-breadcrumb" separator="/">
|
||||
<transition-group name="breadcrumb">
|
||||
<el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path">
|
||||
<span v-if="item.redirect==='noredirect'||index==levelList.length-1" class="no-redirect">{{ item.meta.title }}</span>
|
||||
<span v-if="item.redirect==='noredirect'||index==levelList.length-1" class="no-redirect">{{
|
||||
item.meta.title
|
||||
}}</span>
|
||||
<a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
|
||||
</el-breadcrumb-item>
|
||||
</transition-group>
|
||||
@@ -73,6 +75,7 @@ export default {
|
||||
font-size: 14px;
|
||||
line-height: 50px;
|
||||
margin-left: 8px;
|
||||
|
||||
.no-redirect {
|
||||
color: #97a8be;
|
||||
cursor: text;
|
||||
|
||||
@@ -123,15 +123,21 @@ export default {
|
||||
props: {
|
||||
permission: {
|
||||
type: Object,
|
||||
default: () => { return {} }
|
||||
default: () => {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
hiddenColumns: {
|
||||
type: Array,
|
||||
default: () => { return [] }
|
||||
default: () => {
|
||||
return []
|
||||
}
|
||||
},
|
||||
ignoreColumns: {
|
||||
type: Array,
|
||||
default: () => { return [] }
|
||||
default: () => {
|
||||
return []
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@@ -253,16 +259,18 @@ export default {
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.crud-opts {
|
||||
padding: 4px 0;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.crud-opts .crud-opts-right {
|
||||
margin-left: auto;
|
||||
}
|
||||
.crud-opts .crud-opts-right span {
|
||||
float: left;
|
||||
}
|
||||
.crud-opts {
|
||||
padding: 4px 0;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.crud-opts .crud-opts-right {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.crud-opts .crud-opts-right span {
|
||||
float: left;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
</template>
|
||||
<script>
|
||||
import { pagination } from '@crud/crud'
|
||||
|
||||
export default {
|
||||
mixins: [pagination()]
|
||||
}
|
||||
|
||||
@@ -1,12 +1,26 @@
|
||||
<!--搜索与重置-->
|
||||
<template>
|
||||
<span>
|
||||
<el-button class="filter-item" size="mini" type="success" icon="el-icon-search" @click="crud.toQuery">搜索</el-button>
|
||||
<el-button v-if="crud.optShow.reset" class="filter-item" size="mini" type="warning" icon="el-icon-refresh-left" @click="crud.resetQuery()">重置</el-button>
|
||||
<el-button
|
||||
class="filter-item"
|
||||
size="mini"
|
||||
type="success"
|
||||
icon="el-icon-search"
|
||||
@click="crud.toQuery"
|
||||
>搜索</el-button>
|
||||
<el-button
|
||||
v-if="crud.optShow.reset"
|
||||
class="filter-item"
|
||||
size="mini"
|
||||
type="warning"
|
||||
icon="el-icon-refresh-left"
|
||||
@click="crud.resetQuery()"
|
||||
>重置</el-button>
|
||||
</span>
|
||||
</template>
|
||||
<script>
|
||||
import { crud } from '@crud/crud'
|
||||
|
||||
export default {
|
||||
mixins: [crud()],
|
||||
props: {
|
||||
|
||||
@@ -1,18 +1,48 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-button v-permission="permission.edit" :loading="crud.status.cu === 2" :disabled="disabledEdit" size="mini" type="primary" icon="el-icon-edit" @click.stop="crud.toEdit(data)" />
|
||||
<el-popover v-model="pop" v-permission="permission.del" placement="top" width="180" trigger="manual" @show="onPopoverShow" @hide="onPopoverHide">
|
||||
<el-button
|
||||
v-permission="permission.edit"
|
||||
:loading="crud.status.cu === 2"
|
||||
:disabled="disabledEdit"
|
||||
size="mini"
|
||||
type="primary"
|
||||
icon="el-icon-edit"
|
||||
@click.stop="crud.toEdit(data)"
|
||||
/>
|
||||
<el-popover
|
||||
v-model="pop"
|
||||
v-permission="permission.del"
|
||||
placement="top"
|
||||
width="180"
|
||||
trigger="manual"
|
||||
@show="onPopoverShow"
|
||||
@hide="onPopoverHide"
|
||||
>
|
||||
<p>{{ msg }}</p>
|
||||
<div style="text-align: right; margin: 0">
|
||||
<el-button size="mini" type="text" @click="doCancel">取消</el-button>
|
||||
<el-button :loading="crud.dataStatus[crud.getDataId(data)].delete === 2" type="primary" size="mini" @click="crud.doDelete(data)">确定</el-button>
|
||||
<el-button
|
||||
:loading="crud.dataStatus[crud.getDataId(data)].delete === 2"
|
||||
type="primary"
|
||||
size="mini"
|
||||
@click="crud.doDelete(data)"
|
||||
>确定
|
||||
</el-button>
|
||||
</div>
|
||||
<el-button slot="reference" :disabled="disabledDle" type="danger" icon="el-icon-delete" size="mini" @click.stop="toDelete" />
|
||||
<el-button
|
||||
slot="reference"
|
||||
:disabled="disabledDle"
|
||||
type="danger"
|
||||
icon="el-icon-delete"
|
||||
size="mini"
|
||||
@click.stop="toDelete"
|
||||
/>
|
||||
</el-popover>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import CRUD, { crud } from '@crud/crud'
|
||||
|
||||
export default {
|
||||
mixins: [crud()],
|
||||
props: {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { download, initData } from '@/api/data'
|
||||
import { downloadFile, parseTime } from '@/utils/index'
|
||||
import Vue from 'vue'
|
||||
import { DownloadFile } from '@/utils/CsDomUtil'
|
||||
|
||||
/**
|
||||
* CRUD配置
|
||||
@@ -30,15 +30,20 @@ function CRUD(options) {
|
||||
// Form 表单
|
||||
form: {},
|
||||
// 重置表单
|
||||
defaultForm: () => {},
|
||||
defaultForm: () => {
|
||||
},
|
||||
// 等待时间
|
||||
time: 50,
|
||||
// CRUD Method
|
||||
crudMethod: {
|
||||
add: (form) => {},
|
||||
del: (id) => {},
|
||||
edit: (form) => {},
|
||||
get: (id) => {}
|
||||
add: (form) => {
|
||||
},
|
||||
del: (id) => {
|
||||
},
|
||||
edit: (form) => {
|
||||
},
|
||||
get: (id) => {
|
||||
}
|
||||
},
|
||||
// 主页操作栏显示哪些按钮
|
||||
optShow: {
|
||||
@@ -328,7 +333,7 @@ function CRUD(options) {
|
||||
doExport() {
|
||||
crud.downloadLoading = true
|
||||
download(crud.url + '/download', crud.getQueryParams()).then(result => {
|
||||
downloadFile(result, crud.title + '数据', 'xlsx')
|
||||
DownloadFile(result, crud.title + '数据', 'xlsx')
|
||||
crud.downloadLoading = false
|
||||
}).catch(() => {
|
||||
crud.downloadLoading = false
|
||||
@@ -419,6 +424,7 @@ function CRUD(options) {
|
||||
*/
|
||||
resetDataStatus() {
|
||||
const dataStatus = {}
|
||||
|
||||
function resetStatus(datas) {
|
||||
datas.forEach(e => {
|
||||
dataStatus[crud.getDataId(e)] = {
|
||||
@@ -430,6 +436,7 @@ function CRUD(options) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
resetStatus(crud.data)
|
||||
crud.dataStatus = dataStatus
|
||||
},
|
||||
@@ -461,7 +468,9 @@ function CRUD(options) {
|
||||
*/
|
||||
selectChange(selection, row) {
|
||||
// 如果selection中存在row代表是选中,否则是取消选中
|
||||
if (selection.find(val => { return crud.getDataId(val) === crud.getDataId(row) })) {
|
||||
if (selection.find(val => {
|
||||
return crud.getDataId(val) === crud.getDataId(row)
|
||||
})) {
|
||||
if (row.children) {
|
||||
row.children.forEach(val => {
|
||||
crud.getTable().toggleRowSelection(val, true)
|
||||
@@ -674,9 +683,6 @@ function presenter(crud) {
|
||||
})
|
||||
this.crud = this.$crud['defalut'] || cruds[0]
|
||||
},
|
||||
methods: {
|
||||
parseTime
|
||||
},
|
||||
created() {
|
||||
for (const k in this.$crud) {
|
||||
if (this.$crud[k].queryOnPresenterCreated) {
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
import { DeBounce } from '@/utils/CsUtil'
|
||||
|
||||
require('echarts/theme/macarons') // echarts theme
|
||||
import { debounce } from '@/utils'
|
||||
|
||||
const animationDuration = 6000
|
||||
|
||||
@@ -31,7 +32,7 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
this.initChart()
|
||||
this.__resizeHandler = debounce(() => {
|
||||
this.__resizeHandler = DeBounce(() => {
|
||||
if (this.chart) {
|
||||
this.chart.resize()
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
import { DeBounce } from '@/utils/CsUtil'
|
||||
|
||||
require('echarts/theme/macarons') // echarts theme
|
||||
import { debounce } from '@/utils'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
@@ -30,7 +30,7 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
this.initChart()
|
||||
this.__resizeHandler = debounce(() => {
|
||||
this.__resizeHandler = DeBounce(() => {
|
||||
if (this.chart) {
|
||||
this.chart.resize()
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
import { DeBounce } from '@/utils/CsUtil'
|
||||
|
||||
require('echarts/theme/macarons') // echarts theme
|
||||
import { debounce } from '@/utils'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
@@ -30,7 +30,7 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
this.initChart()
|
||||
this.__resizeHandler = debounce(() => {
|
||||
this.__resizeHandler = DeBounce(() => {
|
||||
if (this.chart) {
|
||||
this.chart.resize()
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
import { DeBounce } from '@/utils/CsUtil'
|
||||
|
||||
require('echarts/theme/macarons') // echarts theme
|
||||
import { debounce } from '@/utils'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
@@ -30,7 +30,7 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
this.initChart()
|
||||
this.__resizeHandler = debounce(() => {
|
||||
this.__resizeHandler = DeBounce(() => {
|
||||
if (this.chart) {
|
||||
this.chart.resize()
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
import { DeBounce } from '@/utils/CsUtil'
|
||||
|
||||
require('echarts/theme/macarons') // echarts theme
|
||||
import { debounce } from '@/utils'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
@@ -30,7 +30,7 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
this.initChart()
|
||||
this.__resizeHandler = debounce(() => {
|
||||
this.__resizeHandler = DeBounce(() => {
|
||||
if (this.chart) {
|
||||
this.chart.resize()
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
import { DeBounce } from '@/utils/CsUtil'
|
||||
|
||||
require('echarts/theme/macarons') // echarts theme
|
||||
import { debounce } from '@/utils'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
@@ -30,7 +30,7 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
this.initChart()
|
||||
this.__resizeHandler = debounce(() => {
|
||||
this.__resizeHandler = DeBounce(() => {
|
||||
if (this.chart) {
|
||||
this.chart.resize()
|
||||
}
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
import { DeBounce } from '@/utils/CsUtil'
|
||||
|
||||
require('echarts/theme/macarons') // echarts theme
|
||||
import { debounce } from '@/utils'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
@@ -29,7 +30,7 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
this.initChart()
|
||||
this.__resizeHandler = debounce(() => {
|
||||
this.__resizeHandler = DeBounce(() => {
|
||||
if (this.chart) {
|
||||
this.chart.resize()
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
import { DeBounce } from '@/utils/CsUtil'
|
||||
|
||||
require('echarts/theme/macarons') // echarts theme
|
||||
import { debounce } from '@/utils'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
@@ -30,7 +30,7 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
this.initChart()
|
||||
this.__resizeHandler = debounce(() => {
|
||||
this.__resizeHandler = DeBounce(() => {
|
||||
if (this.chart) {
|
||||
this.chart.resize()
|
||||
}
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
import { DeBounce } from '@/utils/CsUtil'
|
||||
|
||||
require('echarts/theme/macarons') // echarts theme
|
||||
import { debounce } from '@/utils'
|
||||
|
||||
const animationDuration = 3000
|
||||
|
||||
@@ -31,7 +32,7 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
this.initChart()
|
||||
this.__resizeHandler = debounce(() => {
|
||||
this.__resizeHandler = DeBounce(() => {
|
||||
if (this.chart) {
|
||||
this.chart.resize()
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
import { DeBounce } from '@/utils/CsUtil'
|
||||
|
||||
require('echarts/theme/macarons') // echarts theme
|
||||
import { debounce } from '@/utils'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
@@ -30,7 +30,7 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
this.initChart()
|
||||
this.__resizeHandler = debounce(() => {
|
||||
this.__resizeHandler = DeBounce(() => {
|
||||
if (this.chart) {
|
||||
this.chart.resize()
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
import { DeBounce } from '@/utils/CsUtil'
|
||||
|
||||
require('echarts/theme/macarons') // echarts theme
|
||||
import { debounce } from '@/utils'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
@@ -30,7 +30,7 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
this.initChart()
|
||||
this.__resizeHandler = debounce(() => {
|
||||
this.__resizeHandler = DeBounce(() => {
|
||||
if (this.chart) {
|
||||
this.chart.resize()
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
import { DeBounce } from '@/utils/CsUtil'
|
||||
|
||||
require('echarts/theme/macarons') // echarts theme
|
||||
import { debounce } from '@/utils'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
@@ -30,7 +30,7 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
this.initChart()
|
||||
this.__resizeHandler = debounce(() => {
|
||||
this.__resizeHandler = DeBounce(() => {
|
||||
if (this.chart) {
|
||||
this.chart.resize()
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
import { DeBounce } from '@/utils/CsUtil'
|
||||
|
||||
require('echarts/theme/macarons') // echarts theme
|
||||
import { debounce } from '@/utils'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
@@ -30,7 +30,7 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
this.initChart()
|
||||
this.__resizeHandler = debounce(() => {
|
||||
this.__resizeHandler = DeBounce(() => {
|
||||
if (this.chart) {
|
||||
this.chart.resize()
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
import { DeBounce } from '@/utils/CsUtil'
|
||||
|
||||
require('echarts/theme/macarons') // echarts theme
|
||||
import { debounce } from '@/utils'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
@@ -30,7 +30,7 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
this.initChart()
|
||||
this.__resizeHandler = debounce(() => {
|
||||
this.__resizeHandler = DeBounce(() => {
|
||||
if (this.chart) {
|
||||
this.chart.resize()
|
||||
}
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<template>
|
||||
<a href="https://github.com/odboy-tianjun/cutejava" target="_blank" class="github-corner" aria-label="View source on Github">
|
||||
<a
|
||||
href="https://github.com/odboy-tianjun/cutejava"
|
||||
target="_blank"
|
||||
class="github-corner"
|
||||
aria-label="View source on Github"
|
||||
>
|
||||
<svg
|
||||
width="80"
|
||||
height="80"
|
||||
@@ -43,10 +48,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width:500px) {
|
||||
@media (max-width: 500px) {
|
||||
.github-corner:hover .octo-arm {
|
||||
animation: none
|
||||
}
|
||||
|
||||
.github-corner .octo-arm {
|
||||
animation: octocat-wave 560ms ease-in-out
|
||||
}
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
width="64"
|
||||
height="64"
|
||||
>
|
||||
<path d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z" />
|
||||
<path
|
||||
d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -106,7 +106,9 @@ export default {
|
||||
|
||||
for (const router of routes) {
|
||||
// skip hidden router
|
||||
if (router.hidden) { continue }
|
||||
if (router.hidden) {
|
||||
continue
|
||||
}
|
||||
|
||||
const data = {
|
||||
path: !this.ishttp(router.path) ? path.resolve(basePath, router.path) : router.path,
|
||||
@@ -167,7 +169,7 @@ export default {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
|
||||
::v-deep .el-input__inner {
|
||||
::v-deep .el-input__inner {
|
||||
border-radius: 0;
|
||||
border: 0;
|
||||
padding-left: 0;
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
<template>
|
||||
<div class="icon-body">
|
||||
<el-input v-model="name" style="position: relative;" clearable placeholder="请输入图标名称" @clear="filterIcons" @input.native="filterIcons">
|
||||
<el-input
|
||||
v-model="name"
|
||||
style="position: relative;"
|
||||
clearable
|
||||
placeholder="请输入图标名称"
|
||||
@clear="filterIcons"
|
||||
@input.native="filterIcons"
|
||||
>
|
||||
<i slot="suffix" class="el-icon-search el-input__icon" />
|
||||
</el-input>
|
||||
<div class="icon-list">
|
||||
@@ -14,6 +21,7 @@
|
||||
|
||||
<script>
|
||||
import icons from './requireIcons'
|
||||
|
||||
export default {
|
||||
name: 'IconSelect',
|
||||
data() {
|
||||
@@ -42,26 +50,29 @@ export default {
|
||||
</script>
|
||||
|
||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||
.icon-body {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
.icon-list {
|
||||
height: 200px;
|
||||
overflow-y: scroll;
|
||||
div {
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
margin-bottom: -5px;
|
||||
cursor: pointer;
|
||||
width: 33%;
|
||||
float: left;
|
||||
}
|
||||
span {
|
||||
display: inline-block;
|
||||
vertical-align: -0.15em;
|
||||
fill: currentColor;
|
||||
overflow: hidden;
|
||||
}
|
||||
.icon-body {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
|
||||
.icon-list {
|
||||
height: 200px;
|
||||
overflow-y: scroll;
|
||||
|
||||
div {
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
margin-bottom: -5px;
|
||||
cursor: pointer;
|
||||
width: 33%;
|
||||
float: left;
|
||||
}
|
||||
|
||||
span {
|
||||
display: inline-block;
|
||||
vertical-align: -0.15em;
|
||||
fill: currentColor;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
const req = require.context('../../assets/icons/svg', false, /\.svg$/)
|
||||
const requireAll = requireContext => requireContext.keys()
|
||||
|
||||
|
||||
@@ -95,6 +95,7 @@ export default {
|
||||
background: #fff;
|
||||
padding: 32px 16px;
|
||||
}
|
||||
|
||||
.pagination-container.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { addClass, removeClass } from '@/utils'
|
||||
import { AddClass, RemoveClass } from '@/utils/CsDomUtil'
|
||||
|
||||
export default {
|
||||
name: 'RightPanel',
|
||||
@@ -46,9 +46,9 @@ export default {
|
||||
this.addEventClick()
|
||||
}
|
||||
if (value) {
|
||||
addClass(document.body, 'showRightPanel')
|
||||
AddClass(document.body, 'showRightPanel')
|
||||
} else {
|
||||
removeClass(document.body, 'showRightPanel')
|
||||
RemoveClass(document.body, 'showRightPanel')
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -81,69 +81,70 @@ export default {
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.showRightPanel {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
width: calc(100% - 15px);
|
||||
}
|
||||
.showRightPanel {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
width: calc(100% - 15px);
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.rightPanel-background {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
opacity: 0;
|
||||
transition: opacity .3s cubic-bezier(.7, .3, .1, 1);
|
||||
background: rgba(0, 0, 0, .2);
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.rightPanel {
|
||||
width: 100%;
|
||||
max-width: 260px;
|
||||
height: 100vh;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
box-shadow: 0px 0px 15px 0px rgba(0, 0, 0, .05);
|
||||
transition: all .25s cubic-bezier(.7, .3, .1, 1);
|
||||
transform: translate(100%);
|
||||
background: #fff;
|
||||
z-index: 40000;
|
||||
}
|
||||
|
||||
.show {
|
||||
transition: all .3s cubic-bezier(.7, .3, .1, 1);
|
||||
|
||||
.rightPanel-background {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
opacity: 0;
|
||||
transition: opacity .3s cubic-bezier(.7, .3, .1, 1);
|
||||
background: rgba(0, 0, 0, .2);
|
||||
z-index: -1;
|
||||
z-index: 20000;
|
||||
opacity: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.rightPanel {
|
||||
width: 100%;
|
||||
max-width: 260px;
|
||||
height: 100vh;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
box-shadow: 0px 0px 15px 0px rgba(0, 0, 0, .05);
|
||||
transition: all .25s cubic-bezier(.7, .3, .1, 1);
|
||||
transform: translate(100%);
|
||||
background: #fff;
|
||||
z-index: 40000;
|
||||
transform: translate(0);
|
||||
}
|
||||
}
|
||||
|
||||
.show {
|
||||
transition: all .3s cubic-bezier(.7, .3, .1, 1);
|
||||
.handle-button {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
position: absolute;
|
||||
left: -48px;
|
||||
text-align: center;
|
||||
font-size: 24px;
|
||||
border-radius: 6px 0 0 6px !important;
|
||||
z-index: 0;
|
||||
pointer-events: auto;
|
||||
cursor: pointer;
|
||||
color: #fff;
|
||||
line-height: 48px;
|
||||
|
||||
.rightPanel-background {
|
||||
z-index: 20000;
|
||||
opacity: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.rightPanel {
|
||||
transform: translate(0);
|
||||
}
|
||||
}
|
||||
|
||||
.handle-button {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
position: absolute;
|
||||
left: -48px;
|
||||
text-align: center;
|
||||
i {
|
||||
font-size: 24px;
|
||||
border-radius: 6px 0 0 6px !important;
|
||||
z-index: 0;
|
||||
pointer-events: auto;
|
||||
cursor: pointer;
|
||||
color: #fff;
|
||||
line-height: 48px;
|
||||
i {
|
||||
font-size: 24px;
|
||||
line-height: 48px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -4,9 +4,15 @@
|
||||
<svg-icon class-name="size-icon" icon-class="size" />
|
||||
</div>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item v-for="item of sizeOptions" :key="item.value" :disabled="size===item.value" :command="item.value">
|
||||
<el-dropdown-item
|
||||
v-for="item of sizeOptions"
|
||||
:key="item.value"
|
||||
:disabled="size===item.value"
|
||||
:command="item.value"
|
||||
>
|
||||
{{
|
||||
item.label }}
|
||||
item.label
|
||||
}}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
<script>
|
||||
// doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage
|
||||
import { isExternal } from '@/utils/validate'
|
||||
import { IsExternal } from '@/utils/CsValidateUtil'
|
||||
|
||||
export default {
|
||||
name: 'SvgIcon',
|
||||
@@ -23,7 +23,7 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
isExternal() {
|
||||
return isExternal(this.iconClass)
|
||||
return IsExternal(this.iconClass)
|
||||
},
|
||||
iconName() {
|
||||
return `#icon-${this.iconClass}`
|
||||
@@ -56,7 +56,7 @@ export default {
|
||||
|
||||
.svg-external-icon {
|
||||
background-color: currentColor;
|
||||
mask-size: cover!important;
|
||||
mask-size: cover !important;
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
const version = require('element-ui/package.json').version // element-ui version from node_modules
|
||||
const ORIGINAL_THEME = '#409EFF' // default color
|
||||
import Cookies from 'js-cookie'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { isExternal } from '@/utils/validate'
|
||||
import { IsExternal } from '@/utils/CsValidateUtil'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
@@ -18,7 +18,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
linkProps(url) {
|
||||
if (isExternal(url)) {
|
||||
if (IsExternal(url)) {
|
||||
return {
|
||||
is: 'a',
|
||||
href: url,
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
<script>
|
||||
import path from 'path'
|
||||
import { isExternal } from '@/utils/validate'
|
||||
import { IsExternal } from '@/utils/CsValidateUtil'
|
||||
import Item from './Item'
|
||||
import AppLink from './Link'
|
||||
import FixiOSBug from './FixiOSBug'
|
||||
@@ -82,10 +82,10 @@ export default {
|
||||
return false
|
||||
},
|
||||
resolvePath(routePath) {
|
||||
if (isExternal(routePath)) {
|
||||
if (IsExternal(routePath)) {
|
||||
return routePath
|
||||
}
|
||||
if (isExternal(this.basePath)) {
|
||||
if (IsExternal(this.basePath)) {
|
||||
return this.basePath
|
||||
}
|
||||
return path.resolve(this.basePath, routePath)
|
||||
|
||||
@@ -10,7 +10,7 @@ import Element from 'element-ui'
|
||||
import dict from './components/Dict'
|
||||
|
||||
// 防止二次提交
|
||||
import { preventReClick } from '@/utils/commands'
|
||||
import { preventReClick } from '@/plugins/PreventReClickDirective'
|
||||
|
||||
// 一键复制插件
|
||||
import VueClipboard from 'vue-clipboard2'
|
||||
@@ -19,7 +19,7 @@ import VueClipboard from 'vue-clipboard2'
|
||||
import SplitPane from 'vue-splitpane'
|
||||
|
||||
// 权限指令
|
||||
import checkPer from '@/utils/permission'
|
||||
import checkPer from '@/plugins/CheckPermPlugin'
|
||||
import permission from './components/Permission'
|
||||
import './assets/styles/element-variables.scss'
|
||||
|
||||
@@ -35,8 +35,8 @@ import './router/index' // permission control
|
||||
|
||||
Vue.use(checkPer)
|
||||
Vue.use(permission)
|
||||
Vue.directive(preventReClick)
|
||||
Vue.use(dict)
|
||||
Vue.use(preventReClick)
|
||||
Vue.use(VueClipboard)
|
||||
Vue.use(Element, {
|
||||
size: Cookies.get('size') || 'small' // set element-ui default size
|
||||
|
||||
@@ -2,10 +2,7 @@ import {
|
||||
initData,
|
||||
download
|
||||
} from '@/api/data'
|
||||
import {
|
||||
parseTime,
|
||||
downloadFile
|
||||
} from '@/utils'
|
||||
import { DownloadFile } from '@/utils/CsDomUtil'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
@@ -46,8 +43,7 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
parseTime,
|
||||
downloadFile,
|
||||
DownloadFile,
|
||||
async init() {
|
||||
if (!await this.beforeInit()) {
|
||||
return
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import Vue from 'vue'
|
||||
|
||||
/**
|
||||
* 防止重复提交指令,需要在main.js中全局注册 Vue.directive('preventReClick', preventReClick)
|
||||
* 使用默认的 3000 毫秒防重复点击时间
|
||||
* 例子: <el-button v-prevent-re-click >提交</el-button>
|
||||
* 自定义防重复点击时间为 5000 毫秒
|
||||
* 例子: <el-button v-prevent-re-click >提交</el-button>
|
||||
*/
|
||||
export const preventReClick = Vue.directive('preventReClick', {
|
||||
inserted(el, binding) {
|
||||
el.addEventListener('click', () => {
|
||||
if (!el.disabled) {
|
||||
el.disabled = true
|
||||
setTimeout(() => {
|
||||
el.disabled = false
|
||||
}, binding.value || 3000)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -34,7 +34,7 @@ const user = {
|
||||
setToken(res.token, rememberMe)
|
||||
commit('SET_TOKEN', res.token)
|
||||
setUserInfo(res.user, commit)
|
||||
// 第一次加载菜单时用到, 具体见 src 目录下的 permission.js
|
||||
// 第一次加载菜单时用到, 具体见 src/plugins/CheckPermPlugin.js
|
||||
commit('SET_LOAD_MENUS', true)
|
||||
resolve()
|
||||
}).catch(error => {
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
import { FormatDateTimeShortStr } from '@/utils/CsUtil'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import axios from 'axios'
|
||||
|
||||
/**
|
||||
* Check if an element has a class
|
||||
* @param {HTMLElement} elm
|
||||
* @param {string} cls
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function HasClass(ele, cls) {
|
||||
return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'))
|
||||
}
|
||||
|
||||
/**
|
||||
* Add class to element
|
||||
* @param {HTMLElement} elm
|
||||
* @param {string} cls
|
||||
*/
|
||||
export function AddClass(ele, cls) {
|
||||
if (!HasClass(ele, cls)) ele.className += ' ' + cls
|
||||
}
|
||||
/**
|
||||
* Remove class from element
|
||||
* @param {HTMLElement} elm
|
||||
* @param {string} cls
|
||||
*/
|
||||
export function RemoveClass(ele, cls) {
|
||||
if (HasClass(ele, cls)) {
|
||||
const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)')
|
||||
ele.className = ele.className.replace(reg, ' ')
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} element
|
||||
* @param {string} className
|
||||
*/
|
||||
export function ToggleClass(element, className) {
|
||||
if (!element || !className) {
|
||||
return
|
||||
}
|
||||
let classString = element.className
|
||||
const nameIndex = classString.indexOf(className)
|
||||
if (nameIndex === -1) {
|
||||
classString += '' + className
|
||||
} else {
|
||||
classString =
|
||||
classString.substr(0, nameIndex) +
|
||||
classString.substr(nameIndex + className.length)
|
||||
}
|
||||
element.className = classString
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载文件
|
||||
* @param obj 后端返回的数据
|
||||
* @param name 文件名
|
||||
* @param suffix 文件后缀
|
||||
* @constructor
|
||||
*/
|
||||
export function DownloadFile(obj, name, suffix) {
|
||||
const url = window.URL.createObjectURL(new Blob([obj]))
|
||||
const link = document.createElement('a')
|
||||
link.style.display = 'none'
|
||||
link.href = url
|
||||
const fileName = FormatDateTimeShortStr(new Date()) + '-' + name + '.' + suffix
|
||||
link.setAttribute('download', fileName)
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
* @param api 上传地址
|
||||
* @param file 上传的文件
|
||||
* @returns {Promise<axios.AxiosResponse<any>>}
|
||||
*/
|
||||
export function UploadFile(api, file) {
|
||||
const data = new FormData()
|
||||
data.append('file', file)
|
||||
const config = {
|
||||
headers: { 'Authorization': getToken() }
|
||||
}
|
||||
return axios.post(api, data, config)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,330 @@
|
||||
import store from '@/store'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
/**
|
||||
* 权限校验
|
||||
* @param value
|
||||
* @returns {boolean|*}
|
||||
*/
|
||||
export function CheckPermissions(value) {
|
||||
if (value && value instanceof Array && value.length > 0) {
|
||||
// 拥有的权限
|
||||
const roles = store.getters && store.getters.roles
|
||||
// 需要的权限
|
||||
const permissionRoles = value
|
||||
return roles.some(role => {
|
||||
return permissionRoles.includes(role)
|
||||
})
|
||||
} else {
|
||||
console.error(`need roles! Like v-permission="['admin','editor']"`)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串转数字
|
||||
* @param value
|
||||
* @returns {Number|*}
|
||||
*/
|
||||
export function StringToNumber(value) {
|
||||
try {
|
||||
return value ? Number(value) : value
|
||||
} catch (e) {
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保留几位小数
|
||||
* @param num Number
|
||||
* @param accuracy 精度
|
||||
* @returns {string|number}
|
||||
*/
|
||||
export function NumberToFixed(num, accuracy) {
|
||||
return num instanceof Number ? num.toFixed(accuracy) : num
|
||||
}
|
||||
|
||||
/**
|
||||
* 浅拷贝
|
||||
* @param source 源对象
|
||||
* @param target 目标对象
|
||||
* @returns {*}
|
||||
*/
|
||||
export function CopyObject(source, target) {
|
||||
return Object.assign(target, source)
|
||||
}
|
||||
|
||||
/**
|
||||
* 深拷贝对象
|
||||
* @param obj
|
||||
*/
|
||||
export function DeepCopyObject(obj) {
|
||||
return JSON.parse(JSON.stringify(obj))
|
||||
}
|
||||
|
||||
/**
|
||||
* 统计对象属性等于targetValue的数量
|
||||
* @param arr 对象数组
|
||||
* @param propKey 属性名称
|
||||
* @param targetValue 目标值
|
||||
* @returns {*|number}
|
||||
*/
|
||||
export function CountArraysObjectByPropKey(arr, propKey, targetValue) {
|
||||
if (!Array.isArray(arr)) return 0
|
||||
return arr.filter(item => item[propKey] === targetValue).length
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据value获取label
|
||||
* @param options /
|
||||
* @param value /
|
||||
* @returns {*}
|
||||
*/
|
||||
export function GetOptionLabelByValue(options, value) {
|
||||
if (options instanceof Array) {
|
||||
const find = options.find(f => f.value === value)
|
||||
if (find) {
|
||||
return find.label
|
||||
}
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化字节数字符串
|
||||
* @param value
|
||||
* @returns {string}
|
||||
* @constructor
|
||||
*/
|
||||
export function FormatBytesStr(value) {
|
||||
if (typeof value !== 'number' || isNaN(value) || value <= 0) {
|
||||
return '0 Bytes'
|
||||
}
|
||||
const units = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
|
||||
const index = Math.floor(Math.log(value) / Math.log(1024))
|
||||
const unit = units[Math.min(index, units.length - 1)]
|
||||
const result = (value / Math.pow(1024, index)).toFixed(2)
|
||||
return `${result} ${unit}`
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化日期字符串
|
||||
* @param originVal
|
||||
* @returns {string}
|
||||
* @constructor
|
||||
*/
|
||||
export function FormatDateStr(originVal) {
|
||||
if (originVal === undefined) {
|
||||
return ''
|
||||
}
|
||||
const dt = new Date(originVal)
|
||||
const y = dt.getFullYear()
|
||||
const m = (dt.getMonth() + 1 + '').padStart(2, '0')
|
||||
const d = (dt.getDate() + '').padStart(2, '0')
|
||||
return `${y}-${m}-${d}`
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化日期时间字符串
|
||||
* @param originVal
|
||||
* @returns {string}
|
||||
* @constructor
|
||||
*/
|
||||
export function FormatDateTimeStr(originVal) {
|
||||
if (originVal) {
|
||||
return dayjs(originVal).format('YYYY-MM-DD HH:mm:ss')
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化日期时间字符串,不带分割符号
|
||||
* @param originVal
|
||||
* @returns {string}
|
||||
* @constructor
|
||||
*/
|
||||
export function FormatDateTimeShortStr(originVal) {
|
||||
if (originVal) {
|
||||
return dayjs(originVal).format('YYYYMMDDHHmmss')
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化表格行列中的日期时间字符串
|
||||
* @param row
|
||||
* @param column
|
||||
* @param cellValue
|
||||
* @param index
|
||||
* @returns {string}
|
||||
* @constructor
|
||||
*/
|
||||
export function FormatRowDateTimeStr(row, column, cellValue, index) {
|
||||
if (cellValue === undefined) {
|
||||
return ''
|
||||
}
|
||||
const dt = new Date(cellValue)
|
||||
const y = dt.getFullYear()
|
||||
const m = (dt.getMonth() + 1 + '').padStart(2, '0')
|
||||
const d = (dt.getDate() + '').padStart(2, '0')
|
||||
const hh = (dt.getHours() + '').padStart(2, '0')
|
||||
const mm = (dt.getMinutes() + '').padStart(2, '0')
|
||||
const ss = (dt.getSeconds() + '').padStart(2, '0')
|
||||
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取变量类型
|
||||
* @param value
|
||||
* @returns {string}
|
||||
* @constructor
|
||||
*/
|
||||
export function GetValueType(value) {
|
||||
return Object.prototype.toString.call(value).slice(8, -1).toLowerCase()
|
||||
}
|
||||
|
||||
/**
|
||||
* 数组去重
|
||||
* @param arr
|
||||
* @returns {any[]}
|
||||
* @constructor
|
||||
*/
|
||||
export function UniqueArrays(arr) {
|
||||
return [...new Set(arr)]
|
||||
}
|
||||
|
||||
/**
|
||||
* 手机号掩码
|
||||
* @param mobile
|
||||
* @returns {*|string}
|
||||
* @constructor
|
||||
*/
|
||||
export function MaskMobile(mobile) {
|
||||
if (mobile.length > 7) {
|
||||
return mobile.substr(0, 3) + '****' + mobile.substr(7)
|
||||
}
|
||||
return mobile
|
||||
}
|
||||
|
||||
/**
|
||||
* 邮箱掩码
|
||||
* @param email
|
||||
* @returns {string}
|
||||
* @constructor
|
||||
*/
|
||||
export function MaskEmail(email) {
|
||||
if (String(email).indexOf('@') > 0) {
|
||||
const str = email.split('@')
|
||||
let _s = ''
|
||||
if (str[0].length > 3) {
|
||||
for (let i = 0; i < str[0].length - 3; i++) {
|
||||
_s += '*'
|
||||
}
|
||||
}
|
||||
return str[0].substr(0, 3) + _s + '@' + str[1]
|
||||
}
|
||||
return email
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Url中的查询参数
|
||||
* @param {string} url
|
||||
* @returns {Object}
|
||||
*/
|
||||
export function GetUrlQueryArgs(url) {
|
||||
url = url == null ? window.location.href : url
|
||||
const search = url.substring(url.lastIndexOf('?') + 1)
|
||||
const obj = {}
|
||||
const reg = /([^?&=]+)=([^?&=]*)/g
|
||||
search.replace(reg, (rs, $1, $2) => {
|
||||
const name = decodeURIComponent($1)
|
||||
let val = decodeURIComponent($2)
|
||||
val = String(val)
|
||||
obj[name] = val
|
||||
return rs
|
||||
})
|
||||
return obj
|
||||
}
|
||||
|
||||
/**
|
||||
* 将Url中的查询参数转成对象
|
||||
* @param {string} url
|
||||
* @returns {Object}
|
||||
*/
|
||||
export function ParseUrlQueryArgsToObject(url) {
|
||||
const search = url.split('?')[1]
|
||||
if (!search) {
|
||||
return {}
|
||||
}
|
||||
return JSON.parse(
|
||||
'{"' +
|
||||
decodeURIComponent(search)
|
||||
.replace(/"/g, '\\"')
|
||||
.replace(/&/g, '","')
|
||||
.replace(/=/g, '":"')
|
||||
.replace(/\+/g, ' ') +
|
||||
'"}'
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并两个属性不一致的对象
|
||||
* @param {Object} target
|
||||
* @param {(Object|Array)} source
|
||||
* @returns {Object}
|
||||
*/
|
||||
export function MergeObject(target, source) {
|
||||
if (typeof target !== 'object') {
|
||||
target = {}
|
||||
}
|
||||
if (Array.isArray(source)) {
|
||||
return source.slice()
|
||||
}
|
||||
Object.keys(source).forEach(property => {
|
||||
const sourceProperty = source[property]
|
||||
if (typeof sourceProperty === 'object') {
|
||||
target[property] = MergeObject(target[property], sourceProperty)
|
||||
} else {
|
||||
target[property] = sourceProperty
|
||||
}
|
||||
})
|
||||
return target
|
||||
}
|
||||
/**
|
||||
* 防抖动
|
||||
* @param {Function} func
|
||||
* @param {number} wait
|
||||
* @param {boolean} immediate
|
||||
* @return {*}
|
||||
*/
|
||||
export function DeBounce(func, wait, immediate = false) {
|
||||
let timeout, args, context, timestamp, result
|
||||
const later = function() {
|
||||
// 据上一次触发时间间隔
|
||||
const last = +new Date() - timestamp
|
||||
// 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
|
||||
if (last < wait && last > 0) {
|
||||
timeout = setTimeout(later, wait - last)
|
||||
} else {
|
||||
timeout = null
|
||||
// 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
|
||||
if (!immediate) {
|
||||
result = func.apply(context, args)
|
||||
context = args = null
|
||||
}
|
||||
}
|
||||
}
|
||||
return function(...args) {
|
||||
context = this
|
||||
timestamp = +new Date()
|
||||
const callNow = immediate && !timeout
|
||||
// 如果延时不存在,重新设定延时
|
||||
if (!timeout) timeout = setTimeout(later, wait)
|
||||
if (callNow) {
|
||||
result = func.apply(context, args)
|
||||
context = args = null
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -1,90 +1,98 @@
|
||||
/**
|
||||
* Created by PanJiaChen on 16/11/18.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 是否链接
|
||||
* @param {string} path
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
export function isExternal(path) {
|
||||
export function IsExternal(path) {
|
||||
return /^(https?:|mailto:|tel:)/.test(path)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} str
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
export function validUsername(str) {
|
||||
const valid_map = ['admin', 'editor']
|
||||
return valid_map.indexOf(str.trim()) >= 0
|
||||
}
|
||||
// /**
|
||||
// * 是否有效用户名
|
||||
// * @param {string} str
|
||||
// * @returns {Boolean}
|
||||
// */
|
||||
// export function IsValidUsername(str) {
|
||||
// const validMap = ['admin', 'editor']
|
||||
// return validMap.indexOf(str.trim()) >= 0
|
||||
// }
|
||||
|
||||
/**
|
||||
* 是否有效链接
|
||||
* @param {string} url
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
export function validURL(url) {
|
||||
export function IsValidURL(url) {
|
||||
const reg = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/
|
||||
return reg.test(url)
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否小写字母
|
||||
* @param {string} str
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
export function validLowerCase(str) {
|
||||
export function IsValidLowerCaseLetter(str) {
|
||||
const reg = /^[a-z]+$/
|
||||
return reg.test(str)
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否大写字母
|
||||
* @param {string} str
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
export function validUpperCase(str) {
|
||||
export function IsValidUpperCase(str) {
|
||||
const reg = /^[A-Z]+$/
|
||||
return reg.test(str)
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否包含大、小写字母
|
||||
* @param {string} str
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
export function validAlphabets(str) {
|
||||
export function IsValidLetter(str) {
|
||||
const reg = /^[A-Za-z]+$/
|
||||
return reg.test(str)
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否邮箱
|
||||
* @param {string} email
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
export function validEmail(email) {
|
||||
export function IsValidEmail(email) {
|
||||
const reg = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
|
||||
return reg.test(email)
|
||||
}
|
||||
|
||||
export function isvalidPhone(phone) {
|
||||
const reg = /^1([38][0-9]|4[014-9]|[59][0-35-9]|6[2567]|7[0-8])\d{8}$/
|
||||
return reg.test(phone)
|
||||
}
|
||||
// /**
|
||||
// * 是否手机号
|
||||
// * @param phone
|
||||
// * @returns {boolean}
|
||||
// * @constructor
|
||||
// */
|
||||
// export function IsValidPhone(phone) {
|
||||
// const reg = /^1([38][0-9]|4[014-9]|[59][0-35-9]|6[2567]|7[0-8])\d{8}$/
|
||||
// return reg.test(phone)
|
||||
// }
|
||||
|
||||
/**
|
||||
* 是否是字符串
|
||||
* @param {string} str
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
export function isString(str) {
|
||||
if (typeof str === 'string' || str instanceof String) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
export function IsString(str) {
|
||||
return typeof str === 'string' || str instanceof String
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否数组
|
||||
* @param {Array} arg
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
export function isArray(arg) {
|
||||
export function IsArray(arg) {
|
||||
if (typeof Array.isArray === 'undefined') {
|
||||
return Object.prototype.toString.call(arg) === '[object Array]'
|
||||
}
|
||||
@@ -97,7 +105,7 @@ export function isArray(arg) {
|
||||
* @param value
|
||||
* @param callback
|
||||
*/
|
||||
export function validateIP(rule, value, callback) {
|
||||
export function IsValidIP(rule, value, callback) {
|
||||
if (value === '' || value === undefined || value == null) {
|
||||
callback()
|
||||
} else {
|
||||
@@ -111,7 +119,7 @@ export function validateIP(rule, value, callback) {
|
||||
}
|
||||
|
||||
/* 是否手机号码或者固话*/
|
||||
export function validatePhoneTwo(rule, value, callback) {
|
||||
export function IsValidPhoneTwo(rule, value, callback) {
|
||||
const reg = /^((0\d{2,3}-\d{7,8})|(1([38][0-9]|4[014-9]|[59][0-35-9]|6[2567]|7[0-8])\d{8}))$/
|
||||
if (value === '' || value === undefined || value == null) {
|
||||
callback()
|
||||
@@ -125,7 +133,7 @@ export function validatePhoneTwo(rule, value, callback) {
|
||||
}
|
||||
|
||||
/* 是否固话*/
|
||||
export function validateTelephone(rule, value, callback) {
|
||||
export function IsValidTelephone(rule, value, callback) {
|
||||
const reg = /0\d{2}-\d{7,8}/
|
||||
if (value === '' || value === undefined || value == null) {
|
||||
callback()
|
||||
@@ -139,7 +147,7 @@ export function validateTelephone(rule, value, callback) {
|
||||
}
|
||||
|
||||
/* 是否手机号码*/
|
||||
export function validatePhone(rule, value, callback) {
|
||||
export function IsValidPhone(rule, value, callback) {
|
||||
const reg = /^1([38][0-9]|4[014-9]|[59][0-35-9]|6[2567]|7[0-8])\d{8}$/
|
||||
if (value === '' || value === undefined || value == null) {
|
||||
callback()
|
||||
@@ -153,7 +161,7 @@ export function validatePhone(rule, value, callback) {
|
||||
}
|
||||
|
||||
/* 是否身份证号码*/
|
||||
export function validateIdNo(rule, value, callback) {
|
||||
export function IsValidIdNumber(rule, value, callback) {
|
||||
const reg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/
|
||||
if (value === '' || value === undefined || value == null) {
|
||||
callback()
|
||||
@@ -0,0 +1,42 @@
|
||||
import store from '@/store'
|
||||
import Vue from 'vue'
|
||||
|
||||
/**
|
||||
* WebSocket客户端
|
||||
*/
|
||||
export default function() {
|
||||
const user = store.getters && store.getters.user
|
||||
const webSocketApi = store.getters && store.getters.websocketApi
|
||||
this.context = Vue.prototype
|
||||
this.wsUri = webSocketApi.replace('{sid}', user.username)
|
||||
/**
|
||||
* 初始化WebSocket连接
|
||||
* @param handleError -> function (e) { e是异常本身 }
|
||||
* @param handleMessage -> function (e) { e.data是message }
|
||||
*/
|
||||
this.connect = function(handleError, handleMessage) {
|
||||
this.wsClient = new WebSocket(this.wsUri)
|
||||
// 连接发生错误
|
||||
this.wsClient.onerror = handleError
|
||||
// 收到消息
|
||||
this.wsClient.onmessage = handleMessage
|
||||
return this
|
||||
}
|
||||
/**
|
||||
* 发送客户端数据
|
||||
* @param data 客户端数据
|
||||
*/
|
||||
this.sendData = function(data) {
|
||||
this.wsClient.send(JSON.stringify(data))
|
||||
}
|
||||
/**
|
||||
* 用于关闭ws连接
|
||||
*/
|
||||
this.close = function() {
|
||||
console.log('关闭连接')
|
||||
if (this.wsClient.readyState === 1) {
|
||||
this.sendData([{}])
|
||||
this.wsClient.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
import Vue from 'vue'
|
||||
|
||||
/**
|
||||
* 防止重复提交指令<br/>
|
||||
* 例子: <el-button v-prevent-re-click >提交</el-button>
|
||||
*/
|
||||
const preventReClick = Vue.directive('preventReClick', {
|
||||
inserted(el, binding) {
|
||||
el.addEventListener('click', () => {
|
||||
if (!el.disabled) {
|
||||
el.disabled = true
|
||||
setTimeout(() => {
|
||||
el.disabled = false
|
||||
}, binding.value || 3000)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
export { preventReClick }
|
||||
@@ -1,385 +0,0 @@
|
||||
/**
|
||||
* Created by PanJiaChen on 16/11/18.
|
||||
*/
|
||||
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
/**
|
||||
* Parse the time to string
|
||||
* @param {(Object|string|number)} time
|
||||
* @param {string} cFormat
|
||||
* @returns {string}
|
||||
*/
|
||||
export function parseTime(time, cFormat) {
|
||||
if (arguments.length === 0) {
|
||||
return null
|
||||
}
|
||||
const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
|
||||
let date
|
||||
if (typeof time === 'undefined' || time === null || time === 'null') {
|
||||
return ''
|
||||
} else if (typeof time === 'object') {
|
||||
date = time
|
||||
} else {
|
||||
if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
|
||||
time = parseInt(time)
|
||||
}
|
||||
if ((typeof time === 'number') && (time.toString().length === 10)) {
|
||||
time = time * 1000
|
||||
}
|
||||
date = new Date(time)
|
||||
}
|
||||
const formatObj = {
|
||||
y: date.getFullYear(),
|
||||
m: date.getMonth() + 1,
|
||||
d: date.getDate(),
|
||||
h: date.getHours(),
|
||||
i: date.getMinutes(),
|
||||
s: date.getSeconds(),
|
||||
a: date.getDay()
|
||||
}
|
||||
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
|
||||
let value = formatObj[key]
|
||||
// Note: getDay() returns 0 on Sunday
|
||||
if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value ] }
|
||||
if (result.length > 0 && value < 10) {
|
||||
value = '0' + value
|
||||
}
|
||||
return value || 0
|
||||
})
|
||||
return time_str
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} time
|
||||
* @param {string} option
|
||||
* @returns {string}
|
||||
*/
|
||||
export function formatTime(time, option) {
|
||||
if (('' + time).length === 10) {
|
||||
time = parseInt(time) * 1000
|
||||
} else {
|
||||
time = +time
|
||||
}
|
||||
const d = new Date(time)
|
||||
const now = Date.now()
|
||||
|
||||
const diff = (now - d) / 1000
|
||||
|
||||
if (diff < 30) {
|
||||
return '刚刚'
|
||||
} else if (diff < 3600) {
|
||||
// less 1 hour
|
||||
return Math.ceil(diff / 60) + '分钟前'
|
||||
} else if (diff < 3600 * 24) {
|
||||
return Math.ceil(diff / 3600) + '小时前'
|
||||
} else if (diff < 3600 * 24 * 2) {
|
||||
return '1天前'
|
||||
}
|
||||
if (option) {
|
||||
return parseTime(time, option)
|
||||
} else {
|
||||
return (
|
||||
d.getMonth() +
|
||||
1 +
|
||||
'月' +
|
||||
d.getDate() +
|
||||
'日' +
|
||||
d.getHours() +
|
||||
'时' +
|
||||
d.getMinutes() +
|
||||
'分'
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} url
|
||||
* @returns {Object}
|
||||
*/
|
||||
export function getQueryObject(url) {
|
||||
url = url == null ? window.location.href : url
|
||||
const search = url.substring(url.lastIndexOf('?') + 1)
|
||||
const obj = {}
|
||||
const reg = /([^?&=]+)=([^?&=]*)/g
|
||||
search.replace(reg, (rs, $1, $2) => {
|
||||
const name = decodeURIComponent($1)
|
||||
let val = decodeURIComponent($2)
|
||||
val = String(val)
|
||||
obj[name] = val
|
||||
return rs
|
||||
})
|
||||
return obj
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input value
|
||||
* @returns {number} output value
|
||||
*/
|
||||
export function byteLength(str) {
|
||||
// returns the byte length of an utf8 string
|
||||
let s = str.length
|
||||
for (var i = str.length - 1; i >= 0; i--) {
|
||||
const code = str.charCodeAt(i)
|
||||
if (code > 0x7f && code <= 0x7ff) s++
|
||||
else if (code > 0x7ff && code <= 0xffff) s += 2
|
||||
if (code >= 0xDC00 && code <= 0xDFFF) i--
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array} actual
|
||||
* @returns {Array}
|
||||
*/
|
||||
export function cleanArray(actual) {
|
||||
const newArray = []
|
||||
for (let i = 0; i < actual.length; i++) {
|
||||
if (actual[i]) {
|
||||
newArray.push(actual[i])
|
||||
}
|
||||
}
|
||||
return newArray
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} json
|
||||
* @returns {Array}
|
||||
*/
|
||||
export function param(json) {
|
||||
if (!json) return ''
|
||||
return cleanArray(
|
||||
Object.keys(json).map(key => {
|
||||
if (json[key] === undefined) return ''
|
||||
return encodeURIComponent(key) + '=' + encodeURIComponent(json[key])
|
||||
})
|
||||
).join('&')
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} url
|
||||
* @returns {Object}
|
||||
*/
|
||||
export function param2Obj(url) {
|
||||
const search = url.split('?')[1]
|
||||
if (!search) {
|
||||
return {}
|
||||
}
|
||||
return JSON.parse(
|
||||
'{"' +
|
||||
decodeURIComponent(search)
|
||||
.replace(/"/g, '\\"')
|
||||
.replace(/&/g, '","')
|
||||
.replace(/=/g, '":"')
|
||||
.replace(/\+/g, ' ') +
|
||||
'"}'
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} val
|
||||
* @returns {string}
|
||||
*/
|
||||
export function html2Text(val) {
|
||||
const div = document.createElement('div')
|
||||
div.innerHTML = val
|
||||
return div.textContent || div.innerText
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges two objects, giving the last one precedence
|
||||
* @param {Object} target
|
||||
* @param {(Object|Array)} source
|
||||
* @returns {Object}
|
||||
*/
|
||||
export function objectMerge(target, source) {
|
||||
if (typeof target !== 'object') {
|
||||
target = {}
|
||||
}
|
||||
if (Array.isArray(source)) {
|
||||
return source.slice()
|
||||
}
|
||||
Object.keys(source).forEach(property => {
|
||||
const sourceProperty = source[property]
|
||||
if (typeof sourceProperty === 'object') {
|
||||
target[property] = objectMerge(target[property], sourceProperty)
|
||||
} else {
|
||||
target[property] = sourceProperty
|
||||
}
|
||||
})
|
||||
return target
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} element
|
||||
* @param {string} className
|
||||
*/
|
||||
export function toggleClass(element, className) {
|
||||
if (!element || !className) {
|
||||
return
|
||||
}
|
||||
let classString = element.className
|
||||
const nameIndex = classString.indexOf(className)
|
||||
if (nameIndex === -1) {
|
||||
classString += '' + className
|
||||
} else {
|
||||
classString =
|
||||
classString.substr(0, nameIndex) +
|
||||
classString.substr(nameIndex + className.length)
|
||||
}
|
||||
element.className = classString
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} type
|
||||
* @returns {Date}
|
||||
*/
|
||||
export function getTime(type) {
|
||||
if (type === 'start') {
|
||||
return new Date().getTime() - 3600 * 1000 * 24 * 90
|
||||
} else {
|
||||
return new Date(new Date().toDateString())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Function} func
|
||||
* @param {number} wait
|
||||
* @param {boolean} immediate
|
||||
* @return {*}
|
||||
*/
|
||||
export function debounce(func, wait, immediate) {
|
||||
let timeout, args, context, timestamp, result
|
||||
|
||||
const later = function() {
|
||||
// 据上一次触发时间间隔
|
||||
const last = +new Date() - timestamp
|
||||
|
||||
// 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
|
||||
if (last < wait && last > 0) {
|
||||
timeout = setTimeout(later, wait - last)
|
||||
} else {
|
||||
timeout = null
|
||||
// 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
|
||||
if (!immediate) {
|
||||
result = func.apply(context, args)
|
||||
if (!timeout) context = args = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return function(...args) {
|
||||
context = this
|
||||
timestamp = +new Date()
|
||||
const callNow = immediate && !timeout
|
||||
// 如果延时不存在,重新设定延时
|
||||
if (!timeout) timeout = setTimeout(later, wait)
|
||||
if (callNow) {
|
||||
result = func.apply(context, args)
|
||||
context = args = null
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array} arr
|
||||
* @returns {Array}
|
||||
*/
|
||||
export function uniqueArr(arr) {
|
||||
return Array.from(new Set(arr))
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string}
|
||||
*/
|
||||
export function createUniqueString() {
|
||||
const timestamp = +new Date() + ''
|
||||
const randomNum = parseInt((1 + Math.random()) * 65536) + ''
|
||||
return (+(randomNum + timestamp)).toString(32)
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an element has a class
|
||||
* @param {HTMLElement} elm
|
||||
* @param {string} cls
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function hasClass(ele, cls) {
|
||||
return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'))
|
||||
}
|
||||
|
||||
/**
|
||||
* Add class to element
|
||||
* @param {HTMLElement} elm
|
||||
* @param {string} cls
|
||||
*/
|
||||
export function addClass(ele, cls) {
|
||||
if (!hasClass(ele, cls)) ele.className += ' ' + cls
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove class from element
|
||||
* @param {HTMLElement} elm
|
||||
* @param {string} cls
|
||||
*/
|
||||
export function removeClass(ele, cls) {
|
||||
if (hasClass(ele, cls)) {
|
||||
const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)')
|
||||
ele.className = ele.className.replace(reg, ' ')
|
||||
}
|
||||
}
|
||||
|
||||
// 替换邮箱字符
|
||||
export function regEmail(email) {
|
||||
if (String(email).indexOf('@') > 0) {
|
||||
const str = email.split('@')
|
||||
let _s = ''
|
||||
if (str[0].length > 3) {
|
||||
for (var i = 0; i < str[0].length - 3; i++) {
|
||||
_s += '*'
|
||||
}
|
||||
}
|
||||
var new_email = str[0].substr(0, 3) + _s + '@' + str[1]
|
||||
}
|
||||
return new_email
|
||||
}
|
||||
|
||||
// 替换手机字符
|
||||
export function regMobile(mobile) {
|
||||
if (mobile.length > 7) {
|
||||
var new_mobile = mobile.substr(0, 3) + '****' + mobile.substr(7)
|
||||
}
|
||||
return new_mobile
|
||||
}
|
||||
|
||||
// 下载文件
|
||||
export function downloadFile(obj, name, suffix) {
|
||||
const url = window.URL.createObjectURL(new Blob([obj]))
|
||||
const link = document.createElement('a')
|
||||
link.style.display = 'none'
|
||||
link.href = url
|
||||
const fileName = parseTime(new Date()) + '-' + name + '.' + suffix
|
||||
link.setAttribute('download', fileName)
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
}
|
||||
|
||||
// 数组去重
|
||||
export const uniqueArrays = (arr) => [...new Set(arr)]
|
||||
|
||||
// 获取变量类型
|
||||
export const type = (value) => Object.prototype.toString.call(value).slice(8, -1).toLowerCase()
|
||||
|
||||
// 深拷贝对象
|
||||
export const deepClone = (obj) => JSON.parse(JSON.stringify(obj))
|
||||
|
||||
// 格式化日期时间字符串
|
||||
export const formatDateTimeStr = (date) => {
|
||||
if (date) {
|
||||
return dayjs(date).format('YYYY-MM-DD HH:mm:ss')
|
||||
}
|
||||
return ''
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
import Vue from 'vue'
|
||||
|
||||
/**
|
||||
* 防止重复提交指令<br/>
|
||||
* 例子: <el-button v-prevent-re-click >提交</el-button>
|
||||
*/
|
||||
const preventReClick = Vue.directive('preventReClick', {
|
||||
inserted(el, binding) {
|
||||
el.addEventListener('click', () => {
|
||||
if (!el.disabled) {
|
||||
el.disabled = true
|
||||
setTimeout(() => {
|
||||
el.disabled = false
|
||||
}, binding.value || 3000)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
export { preventReClick }
|
||||
@@ -1,137 +0,0 @@
|
||||
import store from '@/store'
|
||||
|
||||
const PermissionUtil = {
|
||||
/**
|
||||
* 权限校验
|
||||
* @param value
|
||||
* @returns {boolean|*}
|
||||
*/
|
||||
validate: function(value) {
|
||||
if (value && value instanceof Array && value.length > 0) {
|
||||
// 拥有的权限
|
||||
const roles = store.getters && store.getters.roles
|
||||
// 需要的权限
|
||||
const permissionRoles = value
|
||||
return roles.some(role => {
|
||||
return permissionRoles.includes(role)
|
||||
})
|
||||
} else {
|
||||
console.error(`need roles! Like v-permission="['admin','editor']"`)
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const StringUtil = {
|
||||
/**
|
||||
* 字符串转数字
|
||||
* @param value
|
||||
* @returns {Number|*}
|
||||
*/
|
||||
toNumber: function(value) {
|
||||
if (value) {
|
||||
return Number(value)
|
||||
}
|
||||
return 0
|
||||
},
|
||||
/**
|
||||
* 保留几位小数
|
||||
* @param num Number
|
||||
* @param accuracy 精度
|
||||
* @returns {string|number}
|
||||
*/
|
||||
retailNum: function(num, accuracy) {
|
||||
return num instanceof Number ? num.toFixed(accuracy) : 0
|
||||
}
|
||||
}
|
||||
|
||||
const ObjectUtil = {
|
||||
/**
|
||||
* 浅拷贝
|
||||
* @param source 源对象
|
||||
* @param target 目标对象
|
||||
* @returns {*}
|
||||
*/
|
||||
copy: function(source, target) {
|
||||
return Object.assign(target, source)
|
||||
}
|
||||
}
|
||||
|
||||
const LabelUtil = {
|
||||
/**
|
||||
* 根据value获取label
|
||||
* @param options /
|
||||
* @param value /
|
||||
* @returns {*}
|
||||
*/
|
||||
getLabel: function(options, value) {
|
||||
if (options instanceof Array) {
|
||||
const find = options.find(f => f.value === value)
|
||||
if (find) {
|
||||
return find.label
|
||||
}
|
||||
return ''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const SizeUtil = {
|
||||
formatBytes: function(value) {
|
||||
if (typeof value !== 'number' || isNaN(value) || value <= 0) {
|
||||
return '0 Bytes'
|
||||
}
|
||||
const units = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
|
||||
const index = Math.floor(Math.log(value) / Math.log(1024))
|
||||
const unit = units[Math.min(index, units.length - 1)]
|
||||
const result = (value / Math.pow(1024, index)).toFixed(2)
|
||||
return `${result} ${unit}`
|
||||
}
|
||||
}
|
||||
|
||||
const DateUtil = {
|
||||
formatDate: function(originVal) {
|
||||
if (originVal === undefined) {
|
||||
return ''
|
||||
}
|
||||
const dt = new Date(originVal)
|
||||
const y = dt.getFullYear()
|
||||
const m = (dt.getMonth() + 1 + '').padStart(2, '0')
|
||||
const d = (dt.getDate() + '').padStart(2, '0')
|
||||
return `${y}-${m}-${d}`
|
||||
},
|
||||
formatDateTime: function(originVal) {
|
||||
if (originVal === undefined) {
|
||||
return ''
|
||||
}
|
||||
const dt = new Date(originVal)
|
||||
const y = dt.getFullYear()
|
||||
const m = (dt.getMonth() + 1 + '').padStart(2, '0')
|
||||
const d = (dt.getDate() + '').padStart(2, '0')
|
||||
const hh = (dt.getHours() + '').padStart(2, '0')
|
||||
const mm = (dt.getMinutes() + '').padStart(2, '0')
|
||||
const ss = (dt.getSeconds() + '').padStart(2, '0')
|
||||
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
|
||||
},
|
||||
formatRowDateTime: function(row, column, cellValue, index) {
|
||||
if (cellValue === undefined) {
|
||||
return ''
|
||||
}
|
||||
const dt = new Date(cellValue)
|
||||
const y = dt.getFullYear()
|
||||
const m = (dt.getMonth() + 1 + '').padStart(2, '0')
|
||||
const d = (dt.getDate() + '').padStart(2, '0')
|
||||
const hh = (dt.getHours() + '').padStart(2, '0')
|
||||
const mm = (dt.getMinutes() + '').padStart(2, '0')
|
||||
const ss = (dt.getSeconds() + '').padStart(2, '0')
|
||||
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
PermissionUtil,
|
||||
StringUtil,
|
||||
ObjectUtil,
|
||||
LabelUtil,
|
||||
DateUtil,
|
||||
SizeUtil
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import Date from './datetime.js'
|
||||
import Date from '../plugins/DateExtendPlugin.js'
|
||||
|
||||
export const calendarBaseShortcuts = [{
|
||||
text: '今天',
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
import axios from 'axios'
|
||||
import { getToken } from '@/utils/auth'
|
||||
|
||||
export function upload(api, file) {
|
||||
var data = new FormData()
|
||||
data.append('file', file)
|
||||
const config = {
|
||||
headers: { 'Authorization': getToken() }
|
||||
}
|
||||
return axios.post(api, data, config)
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
/**
|
||||
* @param context 上下文,例如 this
|
||||
* @param wsUri websocket地址
|
||||
* @constructor
|
||||
*/
|
||||
function EasyWebSocket(context, wsUri) {
|
||||
this.context = context
|
||||
this.wsUri = wsUri
|
||||
this.webSocket = null
|
||||
/**
|
||||
* 初始化WebSocket连接
|
||||
* @param handleError -> function (e) { e是异常本身 }
|
||||
* @param handleMessage -> function (e) { e.data是message }
|
||||
*/
|
||||
this.connect = function(handleError, handleMessage) {
|
||||
this.webSocket = new WebSocket(this.wsUri)
|
||||
// 连接发生错误
|
||||
this.webSocket.onerror = handleError
|
||||
// 收到消息
|
||||
this.webSocket.onmessage = handleMessage
|
||||
return this
|
||||
}
|
||||
/**
|
||||
* 发送客户端数据
|
||||
* @param data 客户端数据
|
||||
*/
|
||||
this.sendData = function(data) {
|
||||
this.webSocket.send(JSON.stringify(data))
|
||||
}
|
||||
/**
|
||||
* 用于关闭ws连接
|
||||
*/
|
||||
this.close = function() {
|
||||
console.info('关闭连接')
|
||||
if (this.webSocket.readyState === 1) {
|
||||
this.sendData([{}])
|
||||
this.webSocket.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default EasyWebSocket
|
||||
@@ -98,13 +98,14 @@ export default {
|
||||
</script>
|
||||
|
||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||
.dashboard-editor-container {
|
||||
padding: 18px 22px 22px 22px;
|
||||
background-color: rgb(240, 242, 245);
|
||||
.chart-wrapper {
|
||||
background: #fff;
|
||||
padding: 16px 16px 0;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
.dashboard-editor-container {
|
||||
padding: 18px 22px 22px 22px;
|
||||
background-color: rgb(240, 242, 245);
|
||||
|
||||
.chart-wrapper {
|
||||
background: #fff;
|
||||
padding: 16px 16px 0;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -45,23 +45,26 @@
|
||||
export default {
|
||||
name: 'SplitPaneDemo',
|
||||
methods: {
|
||||
resize() {}
|
||||
resize() {
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.wrap{
|
||||
height:300px;
|
||||
.paneL{
|
||||
background-color:red;
|
||||
height:100%;
|
||||
width:100%;
|
||||
.wrap {
|
||||
height: 300px;
|
||||
|
||||
.paneL {
|
||||
background-color: red;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
.paneR{
|
||||
|
||||
.paneR {
|
||||
background-color: blue;
|
||||
height:100%;
|
||||
width:100%;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -11,8 +11,7 @@
|
||||
</el-card>
|
||||
</template>
|
||||
<script>
|
||||
import MyWebSocket from '@/utils/websocket'
|
||||
import { mapGetters } from 'vuex'
|
||||
import CsWsClient from '@/utils/CsWsClient'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
@@ -22,12 +21,6 @@ export default {
|
||||
responseTxt: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'websocketApi',
|
||||
'user'
|
||||
])
|
||||
},
|
||||
// mounted() {},
|
||||
destroyed() {
|
||||
if (this.client) {
|
||||
@@ -39,7 +32,7 @@ export default {
|
||||
// 获取mapGetters中的值
|
||||
// console.error('userInfo', this.user)
|
||||
const that = this
|
||||
that.client = new MyWebSocket(that, that.websocketApi.replaceAll('{sid}', that.user.username))
|
||||
that.client = new CsWsClient(that)
|
||||
that.client.connect(function(event) {
|
||||
console.info('=============== MyWebSocket:event', event)
|
||||
}, function(msgEvent) {
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
import { Message } from 'element-ui'
|
||||
import { mapGetters } from 'vuex'
|
||||
import { getToken } from '@/utils/auth'
|
||||
|
||||
export default {
|
||||
name: 'CuteFileUpload',
|
||||
props: {
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
import { Message } from 'element-ui'
|
||||
import { mapGetters } from 'vuex'
|
||||
import { getToken } from '@/utils/auth'
|
||||
|
||||
export default {
|
||||
name: 'CuteFileUpload',
|
||||
props: {
|
||||
|
||||
@@ -27,6 +27,7 @@ import 'codemirror/mode/sql/sql'
|
||||
import 'codemirror/mode/vue/vue'
|
||||
import 'codemirror/mode/xml/xml'
|
||||
import { Message } from 'element-ui'
|
||||
|
||||
const SupportModeList = ['yaml', 'java', 'go', 'swift', 'dockerfile', 'groovy', 'lua', 'perl', 'python', 'ruby', 'sql', 'xml', 'vue']
|
||||
export default {
|
||||
name: 'CuteCodeEditor',
|
||||
|
||||
@@ -14,8 +14,20 @@
|
||||
@selection-change="onTableSelectionChange"
|
||||
>
|
||||
<el-table-column v-if="mode === 'multi'" type="selection" width="55" />
|
||||
<el-table-column v-for="(column, index) in crud.columns" :key="index" :label="column.label" :prop="column.prop" :formatter="column.formatter ? column.formatter : null" />
|
||||
<el-table-column v-if="crud.operateColumn" :width="crud.operateColumn.width" label="操作" :formatter="crud.operateColumn.formatter" :fixed="crud.operateColumn.fixed" />
|
||||
<el-table-column
|
||||
v-for="(column, index) in crud.columns"
|
||||
:key="index"
|
||||
:label="column.label"
|
||||
:prop="column.prop"
|
||||
:formatter="column.formatter ? column.formatter : null"
|
||||
/>
|
||||
<el-table-column
|
||||
v-if="crud.operateColumn"
|
||||
:width="crud.operateColumn.width"
|
||||
label="操作"
|
||||
:formatter="crud.operateColumn.formatter"
|
||||
:fixed="crud.operateColumn.fixed"
|
||||
/>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
:current-page="pageProps.current"
|
||||
@@ -31,6 +43,7 @@
|
||||
|
||||
<script>
|
||||
import Sortable from 'sortablejs'
|
||||
|
||||
export default {
|
||||
name: 'CuteDragTable',
|
||||
props: {
|
||||
|
||||
@@ -13,6 +13,7 @@ import 'codemirror/lib/codemirror.css'
|
||||
// 主题预览地址 https://blog.csdn.net/qq_41694291/article/details/106429772
|
||||
import 'codemirror/theme/darcula.css'
|
||||
import 'codemirror/mode/javascript/javascript'
|
||||
|
||||
export default {
|
||||
name: 'CuteJavaEditor',
|
||||
props: {
|
||||
|
||||
@@ -15,10 +15,11 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { upload } from '@/utils/upload'
|
||||
import { mapGetters } from 'vuex'
|
||||
import { mavonEditor } from 'mavon-editor'
|
||||
import 'mavon-editor/dist/css/index.css'
|
||||
import { UploadFile } from '@/utils/CsDomUtil'
|
||||
|
||||
const dynamicHeight = 160
|
||||
export default {
|
||||
name: 'CuteMarkdown',
|
||||
@@ -52,7 +53,7 @@ export default {
|
||||
methods: {
|
||||
imgAdd(pos, $file) {
|
||||
const that = this
|
||||
upload(that.imagesUploadApi, $file).then(res => {
|
||||
UploadFile(that.imagesUploadApi, $file).then(res => {
|
||||
const data = res.data
|
||||
const url = that.baseApi + '/file/' + data.type + '/' + data.realName
|
||||
that.$refs.md.$img2Url(pos, url)
|
||||
|
||||
@@ -61,7 +61,9 @@
|
||||
<el-row>
|
||||
<el-col :span="12" style="text-align: left">
|
||||
<!-- 流水线状态为fail,且节点支持重试 -->
|
||||
<div v-if="pipelineData.currentNodeStatus === 'fail' && pipelineData.retry === true">
|
||||
<div
|
||||
v-if="pipelineData.currentNodeStatus && pipelineData.currentNodeStatus === 'fail' && pipelineData.retry === true"
|
||||
>
|
||||
<div class="box-buttons">
|
||||
<el-button
|
||||
type="text"
|
||||
@@ -69,7 +71,7 @@
|
||||
:style="{
|
||||
padding: 0,
|
||||
margin: '0 10px 0 10px',
|
||||
color: statusColorConst.success.color
|
||||
color: statusColorConst.running.color
|
||||
}"
|
||||
@click="onNodeRetryClick"
|
||||
>
|
||||
@@ -79,7 +81,7 @@
|
||||
</div>
|
||||
<!-- 流水线状态为success,且有需要满足条件的操作按钮 -->
|
||||
<div
|
||||
v-else-if="pipelineData.currentNodeStatus === statusColorConst.success.code && pipelineData.buttons && pipelineData.buttons.length > 0"
|
||||
v-else-if="pipelineData.currentNodeStatus && pipelineData.currentNodeStatus === statusColorConst.success.code && pipelineData.buttons && pipelineData.buttons.length > 0"
|
||||
>
|
||||
<div class="box-buttons">
|
||||
<el-button
|
||||
@@ -90,7 +92,7 @@
|
||||
:style="{
|
||||
padding: 0,
|
||||
margin: '0 10px 0 10px',
|
||||
color: ['apply','agree','ok','success'].includes(buttonItem.code) ? 'green' : 'red',
|
||||
color: ['apply','agree','ok','success'].includes(buttonItem.code) ? statusColorConst.running.color : statusColorConst.fail.color,
|
||||
display: ['success', 'fail'].includes(buttonItem.code) && pipelineData.status === buttonItem.code ? '' : 'none'
|
||||
}"
|
||||
@click="onNodeOperationClick(buttonItem)"
|
||||
@@ -101,7 +103,7 @@
|
||||
</div>
|
||||
<!-- 流水线状态非pending,且有操作按钮 -->
|
||||
<div
|
||||
v-else-if="pipelineData.currentNodeStatus !== statusColorConst.pending.code && pipelineData.buttons && pipelineData.buttons.length > 0"
|
||||
v-else-if="pipelineData.currentNodeStatus && pipelineData.currentNodeStatus !== statusColorConst.pending.code && pipelineData.buttons && pipelineData.buttons.length > 0"
|
||||
>
|
||||
<div class="box-buttons">
|
||||
<el-button
|
||||
@@ -112,7 +114,7 @@
|
||||
:style="{
|
||||
padding: 0,
|
||||
margin: '0 10px 0 10px',
|
||||
color: ['apply','agree','ok','success'].includes(buttonItem.code) ? 'green' : 'red'
|
||||
color: ['apply','agree','ok','success'].includes(buttonItem.code) ? statusColorConst.running.color : statusColorConst.fail.color
|
||||
}"
|
||||
@click="onNodeOperationClick(buttonItem)"
|
||||
>
|
||||
@@ -160,7 +162,7 @@ export default {
|
||||
return {
|
||||
statusColorConst: {
|
||||
pending: { code: 'pending', label: '未开始', color: '#C0C4CC' },
|
||||
running: { code: 'running', label: '运行中', color: '#67C23A' },
|
||||
running: { code: 'running', label: '运行中', color: '#409EFF' },
|
||||
success: { code: 'success', label: '执行成功', color: '#67C23A' },
|
||||
fail: { code: 'fail', label: '执行失败', color: '#F56C6C' }
|
||||
},
|
||||
@@ -265,8 +267,8 @@ export default {
|
||||
</script>
|
||||
<style scoped>
|
||||
.box-card {
|
||||
width: 240px; /* 卡片宽度 */
|
||||
max-width: 240px; /* 卡片宽度 */
|
||||
width: 260px; /* 卡片宽度 */
|
||||
max-width: 260px; /* 卡片宽度 */
|
||||
padding: 10px;
|
||||
background-color: #fff; /* 背景颜色 */
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* 阴影效果 */
|
||||
|
||||
@@ -28,8 +28,9 @@
|
||||
import { mapGetters } from 'vuex'
|
||||
import '@wangeditor/editor/dist/css/style.css'
|
||||
import { Message } from 'element-ui'
|
||||
import { upload } from '@/utils/upload'
|
||||
import { Toolbar, Editor } from '@wangeditor/editor-for-vue'
|
||||
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
|
||||
import { UploadFile } from '@/utils/CsDomUtil'
|
||||
|
||||
export default {
|
||||
name: 'CuteRichTextEditor',
|
||||
components: { Toolbar, Editor },
|
||||
@@ -62,7 +63,7 @@ export default {
|
||||
allowedFileTypes: ['image/*'],
|
||||
// 自定义上传
|
||||
async customUpload(file, insertFn) { // JS 语法
|
||||
upload(that.imagesUploadApi, file).then(res => {
|
||||
UploadFile(that.imagesUploadApi, file).then(res => {
|
||||
const data = res.data
|
||||
const url = that.baseApi + '/file/' + data.dateGroup + '/' + data.realName
|
||||
// 最后插入图片
|
||||
|
||||
@@ -14,8 +14,20 @@
|
||||
@selection-change="onTableSelectionChange"
|
||||
>
|
||||
<el-table-column v-if="mode === 'multi'" type="selection" width="55" />
|
||||
<el-table-column v-for="(column, index) in crud.columns" :key="index" :label="column.label" :prop="column.prop" :formatter="column.formatter ? column.formatter : null" />
|
||||
<el-table-column v-if="crud.operateColumn" :width="crud.operateColumn.width" label="操作" :formatter="crud.operateColumn.formatter" :fixed="crud.operateColumn.fixed" />
|
||||
<el-table-column
|
||||
v-for="(column, index) in crud.columns"
|
||||
:key="index"
|
||||
:label="column.label"
|
||||
:prop="column.prop"
|
||||
:formatter="column.formatter ? column.formatter : null"
|
||||
/>
|
||||
<el-table-column
|
||||
v-if="crud.operateColumn"
|
||||
:width="crud.operateColumn.width"
|
||||
label="操作"
|
||||
:formatter="crud.operateColumn.formatter"
|
||||
:fixed="crud.operateColumn.fixed"
|
||||
/>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
:current-page="pageProps.current"
|
||||
|
||||
@@ -13,6 +13,7 @@ import 'codemirror/lib/codemirror.css'
|
||||
// 主题预览地址 https://blog.csdn.net/qq_41694291/article/details/106429772
|
||||
import 'codemirror/theme/darcula.css'
|
||||
import 'codemirror/mode/yaml/yaml'
|
||||
|
||||
export default {
|
||||
name: 'CuteYamlEditor',
|
||||
props: {
|
||||
|
||||
@@ -40,9 +40,10 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import clipboard from '@/utils/clipboard'
|
||||
import clipboard from '@/plugins/ClipboardPlugin'
|
||||
import svgIcons from './svg-icons'
|
||||
import elementIcons from './element-icons'
|
||||
|
||||
export default {
|
||||
name: 'Icons',
|
||||
data() {
|
||||
@@ -75,6 +76,7 @@ export default {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
|
||||
}
|
||||
|
||||
.icon-item {
|
||||
margin: 20px;
|
||||
height: 85px;
|
||||
@@ -85,11 +87,13 @@ export default {
|
||||
color: #24292e;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
span {
|
||||
display: block;
|
||||
font-size: 16px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.disabled {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@@ -42,9 +42,9 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { DateUtil } from '@/utils/myUtil'
|
||||
import DictService from '@/api/system/dict'
|
||||
import CuteDragTable from '@/views/components/dev/CuteDragTable.vue'
|
||||
import { FormatRowDateTimeStr } from '@/utils/CsUtil'
|
||||
|
||||
export default {
|
||||
name: 'CuteDragTableDemo',
|
||||
@@ -74,7 +74,7 @@ export default {
|
||||
columns: [
|
||||
{ prop: 'name', label: '名称' },
|
||||
{ prop: 'description', label: '描述' },
|
||||
{ prop: 'createTime', label: '创建时间', formatter: DateUtil.formatRowDateTime },
|
||||
{ prop: 'createTime', label: '创建时间', formatter: FormatRowDateTimeStr },
|
||||
{ prop: 'createBy', label: '创建人' }
|
||||
],
|
||||
operateColumn: {
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
import Clipboard from 'clipboard'
|
||||
import { Message } from 'element-ui'
|
||||
import CuteOneKeyCopy from '@/views/components/dev/CuteOneKeyCopy'
|
||||
|
||||
export default {
|
||||
components: { CuteOneKeyCopy },
|
||||
data() {
|
||||
@@ -54,6 +55,7 @@ export default {
|
||||
color: #333;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#btn:active {
|
||||
background-color: #ddd;
|
||||
color: #666;
|
||||
|
||||
@@ -1,19 +1,28 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-divider>演示:动态流水线 <el-button type="primary" @click="startPipelineTest">启动流水线</el-button></el-divider>
|
||||
<el-divider>演示:动态流水线
|
||||
<el-button
|
||||
v-prevent-re-click
|
||||
type="primary"
|
||||
:loading="dynamicStartButtonLoading"
|
||||
:disabled="dynamicStartButtonLoading"
|
||||
@click="startPipelineTest"
|
||||
>{{ dynamicStartupStatusMap[dynamicStartupStatus].label }}
|
||||
</el-button>
|
||||
</el-divider>
|
||||
<div class="box-pipeline">
|
||||
<div v-if="dynamicList && dynamicList.length > 0" class="box-pipeline-content">
|
||||
<div v-if="dynamicInstance.nodes && dynamicInstance.nodes.length > 0" class="box-pipeline-content">
|
||||
<cute-pipeline-node
|
||||
v-for="(template, index) in dynamicList"
|
||||
v-for="(template, index) in dynamicInstance.nodes"
|
||||
:key="template.code"
|
||||
:template-data.sync="dynamicList[index]"
|
||||
:template-data.sync="dynamicInstance.nodes[index]"
|
||||
/>
|
||||
</div>
|
||||
<div v-else class="box-pipeline-content">
|
||||
<cute-pipeline-node
|
||||
v-for="(template, index) in templateList"
|
||||
v-for="(template, index) in dynamicTemplate"
|
||||
:key="template.code"
|
||||
:template-data.sync="templateList[index]"
|
||||
:template-data.sync="dynamicTemplate[index]"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -28,9 +37,9 @@
|
||||
</div>
|
||||
<div v-else class="box-pipeline-content">
|
||||
<cute-pipeline-node
|
||||
v-for="(template, index) in templateList"
|
||||
v-for="(template, index) in defaultTemplate"
|
||||
:key="template.code"
|
||||
:template-data.sync="templateList[index]"
|
||||
:template-data.sync="defaultTemplate[index]"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -45,9 +54,9 @@
|
||||
</div>
|
||||
<div v-else class="box-pipeline-content">
|
||||
<cute-pipeline-node
|
||||
v-for="(template, index) in templateList"
|
||||
v-for="(template, index) in defaultTemplate"
|
||||
:key="template.code"
|
||||
:template-data.sync="templateList[index]"
|
||||
:template-data.sync="defaultTemplate[index]"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -57,15 +66,18 @@
|
||||
<script>
|
||||
|
||||
import CutePipelineNode from '@/views/components/dev/CutePipelineNode'
|
||||
import { formatDateTimeStr } from '@/utils'
|
||||
import { startPipeline, queryLastPipelineDetail } from '@/api/devops/pipeline'
|
||||
import { getPipelineTemplate } from '@/api/devops/pipelineTemplate'
|
||||
import { queryLastPipelineDetail, restartPipeline, startPipeline } from '@/api/devops/pipelineInstance'
|
||||
import { CountArraysObjectByPropKey, FormatDateTimeStr } from '@/utils/CsUtil'
|
||||
import CsMessage from '@/utils/elementui/CsMessage'
|
||||
|
||||
export default {
|
||||
name: 'CutePipelineNodeDemo',
|
||||
components: { CutePipelineNode },
|
||||
data() {
|
||||
return {
|
||||
templateList: [
|
||||
// 静态模板
|
||||
defaultTemplate: [
|
||||
{
|
||||
code: 'node_init',
|
||||
type: 'service',
|
||||
@@ -438,46 +450,96 @@ export default {
|
||||
}
|
||||
],
|
||||
// 动态流水线
|
||||
dynamicStartupStatus: 'start',
|
||||
dynamicStartupStatusMap: {
|
||||
start: { label: '启动', code: 'start' },
|
||||
restart: { label: '重新启动', code: 'restart' }
|
||||
},
|
||||
dynamicStartButtonLoading: false,
|
||||
dynamicTemplate: [],
|
||||
dynamicHook: null,
|
||||
dynamicList: [],
|
||||
dynamicInstanceId: ''
|
||||
dynamicInstance: {}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.refreshData()
|
||||
this.initPipelineTemplate(4)
|
||||
const pipelineInstanceId = sessionStorage.getItem('pipelineInstanceId')
|
||||
if (pipelineInstanceId) {
|
||||
this.fetchLastDetail(pipelineInstanceId)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
refreshData() {
|
||||
// 成功
|
||||
for (const datum of this.dataList2) {
|
||||
if (datum.status === 'running') {
|
||||
datum.updateTime = formatDateTimeStr(new Date())
|
||||
datum.updateTime = FormatDateTimeStr(new Date())
|
||||
}
|
||||
}
|
||||
this.dataList2 = [...this.dataList2]
|
||||
// 失败或重试
|
||||
for (const datum of this.dataList3) {
|
||||
if (datum.status === 'running') {
|
||||
datum.updateTime = formatDateTimeStr(new Date())
|
||||
datum.updateTime = FormatDateTimeStr(new Date())
|
||||
}
|
||||
}
|
||||
this.dataList3 = [...this.dataList3]
|
||||
},
|
||||
startPipelineTest() {
|
||||
async initPipelineTemplate(templateId) {
|
||||
const pipelineTemplate = await getPipelineTemplate(templateId)
|
||||
if (pipelineTemplate && pipelineTemplate.template) {
|
||||
try {
|
||||
this.dynamicTemplate = JSON.parse(pipelineTemplate.template)
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
},
|
||||
async fetchLastDetail(instanceId) {
|
||||
const that = this
|
||||
if (that.dynamicHook) {
|
||||
clearInterval(that.dynamicHook)
|
||||
const intervalTime = 2000
|
||||
setTimeout(() => {
|
||||
that.dynamicHook = setInterval(() => {
|
||||
queryLastPipelineDetail(instanceId).then((data) => {
|
||||
that.dynamicInstance = data
|
||||
// 判断流水线是否结束
|
||||
const successCount = CountArraysObjectByPropKey(data.nodes, 'status', 'success')
|
||||
if (that.dynamicTemplate && that.dynamicTemplate.length === successCount) {
|
||||
clearInterval(that.dynamicHook)
|
||||
that.dynamicHook = null
|
||||
that.dynamicStartupStatus = that.dynamicStartupStatusMap.start.code
|
||||
} else {
|
||||
that.dynamicStartupStatus = that.dynamicStartupStatusMap.restart.code
|
||||
}
|
||||
})
|
||||
}, intervalTime)
|
||||
that.dynamicStartButtonLoading = false
|
||||
}, 2000)
|
||||
},
|
||||
async startPipelineTest() {
|
||||
const that = this
|
||||
try {
|
||||
if (that.dynamicHook) {
|
||||
clearInterval(that.dynamicHook)
|
||||
}
|
||||
that.dynamicStartButtonLoading = true
|
||||
// 这里的 dynamicStartupStatus状态,需要后期与上下文关联后,初始化的时候带入最近一个流水线实例
|
||||
// let result
|
||||
// if (that.dynamicStartupStatus === that.dynamicStartupStatusMap.start.code) {
|
||||
// result = await restartPipeline()
|
||||
// CsMessage.Success('流水线重新启动成功')
|
||||
// } else {
|
||||
// result = await startPipeline()
|
||||
// CsMessage.Success('流水线启动成功')
|
||||
// }
|
||||
const result = await startPipeline()
|
||||
CsMessage.Success('流水线启动成功')
|
||||
await that.fetchLastDetail(result.instanceId)
|
||||
sessionStorage.setItem('pipelineInstanceId', result.instanceId)
|
||||
} catch (e) {
|
||||
that.dynamicStartButtonLoading = false
|
||||
}
|
||||
startPipeline().then((instanceId) => {
|
||||
that.dynamicInstanceId = instanceId
|
||||
setTimeout(() => {
|
||||
that.dynamicHook = setInterval(() => {
|
||||
queryLastPipelineDetail(that.dynamicInstanceId).then((data) => {
|
||||
that.dynamicList = data
|
||||
})
|
||||
}, 1000)
|
||||
}, 2000)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -489,15 +551,19 @@ export default {
|
||||
white-space: nowrap; /* 防止内容换行,使所有内容在一行显示 */
|
||||
padding: 30px 20px 30px 20px;
|
||||
}
|
||||
|
||||
.box-pipeline::-webkit-scrollbar {
|
||||
height: 5px; /* 设置水平滚动条高度 */
|
||||
}
|
||||
|
||||
.box-pipeline::-webkit-scrollbar-track {
|
||||
background: #f1f1f1; /* 滚动条底色 */
|
||||
}
|
||||
|
||||
.box-pipeline::-webkit-scrollbar-thumb {
|
||||
background: #DCDFE6; /* 滚动条颜色 */
|
||||
}
|
||||
|
||||
.box-pipeline-content {
|
||||
display: inline-block; /* 使内容水平排列 */
|
||||
white-space: nowrap; /* 防止内容换行 */
|
||||
|
||||
@@ -68,10 +68,10 @@
|
||||
|
||||
<script>
|
||||
import CuteSimpleTable from '@/views/components/dev/CuteSimpleTable'
|
||||
import { DateUtil } from '@/utils/myUtil'
|
||||
import DictService from '@/api/system/dict'
|
||||
import CuteFormDialog from '@/views/components/dev/CuteFormDialog'
|
||||
import CuteFormDrawer from '@/views/components/dev/CuteFormDrawer'
|
||||
import { FormatRowDateTimeStr } from '@/utils/CsUtil'
|
||||
|
||||
export default {
|
||||
name: 'CuteSimpleTableDemo',
|
||||
@@ -101,7 +101,7 @@ export default {
|
||||
columns: [
|
||||
{ prop: 'name', label: '名称' },
|
||||
{ prop: 'description', label: '描述' },
|
||||
{ prop: 'createTime', label: '创建时间', formatter: DateUtil.formatRowDateTime },
|
||||
{ prop: 'createTime', label: '创建时间', formatter: FormatRowDateTimeStr },
|
||||
{ prop: 'createBy', label: '创建人' }
|
||||
],
|
||||
operateColumn: {
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
require('echarts/theme/macarons') // echarts theme
|
||||
import resize from './mixins/resize'
|
||||
|
||||
require('echarts/theme/macarons') // echarts theme
|
||||
|
||||
export default {
|
||||
mixins: [resize],
|
||||
props: {
|
||||
|
||||
@@ -160,7 +160,7 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width:550px) {
|
||||
@media (max-width: 550px) {
|
||||
.card-panel-description {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { debounce } from '@/utils'
|
||||
import { DeBounce } from '@/utils/CsUtil'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
@@ -8,7 +8,7 @@ export default {
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$_resizeHandler = debounce(() => {
|
||||
this.$_resizeHandler = DeBounce(() => {
|
||||
if (this.chart) {
|
||||
this.chart.resize()
|
||||
}
|
||||
|
||||
@@ -49,41 +49,49 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.errPage-container {
|
||||
width: 800px;
|
||||
max-width: 100%;
|
||||
margin: 100px auto;
|
||||
.pan-back-btn {
|
||||
background: #008489;
|
||||
color: #fff;
|
||||
border: none!important;
|
||||
.errPage-container {
|
||||
width: 800px;
|
||||
max-width: 100%;
|
||||
margin: 100px auto;
|
||||
|
||||
.pan-back-btn {
|
||||
background: #008489;
|
||||
color: #fff;
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.pan-gif {
|
||||
margin: 0 auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.pan-img {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.text-jumbo {
|
||||
font-size: 60px;
|
||||
font-weight: 700;
|
||||
color: #484848;
|
||||
}
|
||||
|
||||
.list-unstyled {
|
||||
font-size: 14px;
|
||||
|
||||
li {
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
.pan-gif {
|
||||
margin: 0 auto;
|
||||
display: block;
|
||||
}
|
||||
.pan-img {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
}
|
||||
.text-jumbo {
|
||||
font-size: 60px;
|
||||
font-weight: 700;
|
||||
color: #484848;
|
||||
}
|
||||
.list-unstyled {
|
||||
font-size: 14px;
|
||||
li {
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
a {
|
||||
color: #008489;
|
||||
text-decoration: none;
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #008489;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -30,27 +30,32 @@ export default {
|
||||
</script>
|
||||
|
||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||
.wscn-http404-container{
|
||||
transform: translate(-50%,-50%);
|
||||
.wscn-http404-container {
|
||||
transform: translate(-50%, -50%);
|
||||
position: absolute;
|
||||
top: 40%;
|
||||
left: 50%;
|
||||
}
|
||||
|
||||
.wscn-http404 {
|
||||
position: relative;
|
||||
width: 1200px;
|
||||
padding: 0 50px;
|
||||
overflow: hidden;
|
||||
|
||||
.pic-404 {
|
||||
position: relative;
|
||||
float: left;
|
||||
width: 600px;
|
||||
overflow: hidden;
|
||||
|
||||
&__parent {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&__child {
|
||||
position: absolute;
|
||||
|
||||
&.left {
|
||||
width: 80px;
|
||||
top: 17px;
|
||||
@@ -62,6 +67,7 @@ export default {
|
||||
animation-fill-mode: forwards;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
|
||||
&.mid {
|
||||
width: 46px;
|
||||
top: 10px;
|
||||
@@ -73,6 +79,7 @@ export default {
|
||||
animation-fill-mode: forwards;
|
||||
animation-delay: 1.2s;
|
||||
}
|
||||
|
||||
&.right {
|
||||
width: 62px;
|
||||
top: 100px;
|
||||
@@ -84,6 +91,7 @@ export default {
|
||||
animation-fill-mode: forwards;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
|
||||
@keyframes cloudLeft {
|
||||
0% {
|
||||
top: 17px;
|
||||
@@ -152,12 +160,14 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bullshit {
|
||||
position: relative;
|
||||
float: left;
|
||||
width: 300px;
|
||||
padding: 30px 0;
|
||||
overflow: hidden;
|
||||
|
||||
&__oops {
|
||||
font-size: 32px;
|
||||
font-weight: bold;
|
||||
@@ -169,6 +179,7 @@ export default {
|
||||
animation-duration: 0.5s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
|
||||
&__headline {
|
||||
font-size: 20px;
|
||||
line-height: 24px;
|
||||
@@ -181,6 +192,7 @@ export default {
|
||||
animation-delay: 0.1s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
|
||||
&__info {
|
||||
font-size: 13px;
|
||||
line-height: 21px;
|
||||
@@ -192,6 +204,7 @@ export default {
|
||||
animation-delay: 0.2s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
|
||||
&__return-home {
|
||||
display: block;
|
||||
float: left;
|
||||
@@ -210,6 +223,7 @@ export default {
|
||||
animation-delay: 0.3s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
|
||||
@keyframes slideUp {
|
||||
0% {
|
||||
transform: translateY(60px);
|
||||
|
||||
@@ -36,6 +36,7 @@ import LineChart from './dashboard/LineChart'
|
||||
import RadarChart from '@/components/Echarts/RadarChart'
|
||||
import PieChart from '@/components/Echarts/PieChart'
|
||||
import BarChart from '@/components/Echarts/BarChart'
|
||||
import CsMessage from '@/utils/elementui/CsMessage'
|
||||
|
||||
const lineChartData = {
|
||||
newVisitis: {
|
||||
@@ -71,6 +72,20 @@ export default {
|
||||
lineChartData: lineChartData.newVisitis
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// setTimeout(() => {
|
||||
// CsMessage.Info('CsMessage Info')
|
||||
// }, 1000)
|
||||
// setTimeout(() => {
|
||||
// CsMessage.Warning('CsMessage Warning')
|
||||
// }, 2000)
|
||||
// setTimeout(() => {
|
||||
// CsMessage.Error('CsMessage Error')
|
||||
// }, 3000)
|
||||
// setTimeout(() => {
|
||||
// CsMessage.Success('CsMessage Success')
|
||||
// }, 4000)
|
||||
},
|
||||
methods: {
|
||||
handleSetLineChartData(type) {
|
||||
this.lineChartData = lineChartData[type]
|
||||
@@ -80,28 +95,28 @@ export default {
|
||||
</script>
|
||||
|
||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||
.dashboard-editor-container {
|
||||
padding: 32px;
|
||||
background-color: rgb(240, 242, 245);
|
||||
position: relative;
|
||||
.dashboard-editor-container {
|
||||
padding: 32px;
|
||||
background-color: rgb(240, 242, 245);
|
||||
position: relative;
|
||||
|
||||
.github-corner {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
border: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.chart-wrapper {
|
||||
background: #fff;
|
||||
padding: 16px 16px 0;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
.github-corner {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
border: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
@media (max-width:1024px) {
|
||||
.chart-wrapper {
|
||||
padding: 8px;
|
||||
}
|
||||
.chart-wrapper {
|
||||
background: #fff;
|
||||
padding: 16px 16px 0;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
.chart-wrapper {
|
||||
padding: 8px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
<template>
|
||||
<div class="login" :style="'background-image:url('+ Background +');'">
|
||||
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" label-position="left" label-width="0px" class="login-form">
|
||||
<el-form
|
||||
ref="loginForm"
|
||||
:model="loginForm"
|
||||
:rules="loginRules"
|
||||
label-position="left"
|
||||
label-width="0px"
|
||||
class="login-form"
|
||||
>
|
||||
<h3 class="title">
|
||||
CuteJava 后台管理系统
|
||||
</h3>
|
||||
@@ -10,12 +17,24 @@
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="password">
|
||||
<el-input v-model="loginForm.password" type="password" auto-complete="off" placeholder="密码" @keyup.enter.native="handleLogin">
|
||||
<el-input
|
||||
v-model="loginForm.password"
|
||||
type="password"
|
||||
auto-complete="off"
|
||||
placeholder="密码"
|
||||
@keyup.enter.native="handleLogin"
|
||||
>
|
||||
<svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon" />
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="code">
|
||||
<el-input v-model="loginForm.code" auto-complete="off" placeholder="验证码" style="width: 63%" @keyup.enter.native="handleLogin">
|
||||
<el-input
|
||||
v-model="loginForm.code"
|
||||
auto-complete="off"
|
||||
placeholder="验证码"
|
||||
style="width: 63%"
|
||||
@keyup.enter.native="handleLogin"
|
||||
>
|
||||
<svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon" />
|
||||
</el-input>
|
||||
<div class="login-code">
|
||||
@@ -26,7 +45,13 @@
|
||||
记住我
|
||||
</el-checkbox>
|
||||
<el-form-item style="width:100%;">
|
||||
<el-button :loading="loading" size="medium" type="primary" style="width:100%;" @click.native.prevent="handleLogin">
|
||||
<el-button
|
||||
:loading="loading"
|
||||
size="medium"
|
||||
type="primary"
|
||||
style="width:100%;"
|
||||
@click.native.prevent="handleLogin"
|
||||
>
|
||||
<span v-if="!loading">登 录</span>
|
||||
<span v-else>登 录 中...</span>
|
||||
</el-button>
|
||||
@@ -42,12 +67,13 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { encrypt } from '@/utils/rsaEncrypt'
|
||||
import { encrypt } from '@/utils/CsRsaUtil'
|
||||
import Config from '@/settings'
|
||||
import { getCodeImg } from '@/api/login'
|
||||
import Cookies from 'js-cookie'
|
||||
import qs from 'qs'
|
||||
import Background from '@/assets/images/background.jpeg'
|
||||
|
||||
export default {
|
||||
name: 'Login',
|
||||
data() {
|
||||
|
||||
@@ -27,7 +27,7 @@ export default {
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
.my-code a{
|
||||
color:#009688;
|
||||
}
|
||||
.my-code a {
|
||||
color: #009688;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -4,9 +4,25 @@
|
||||
<div class="head-container">
|
||||
<div v-if="crud.props.searchToggle">
|
||||
<!-- 搜索 -->
|
||||
<el-input v-model="query.name" clearable size="small" placeholder="输入部门名称搜索" style="width: 200px;" class="filter-item" @keyup.enter.native="crud.toQuery" />
|
||||
<el-input
|
||||
v-model="query.name"
|
||||
clearable
|
||||
size="small"
|
||||
placeholder="输入部门名称搜索"
|
||||
style="width: 200px;"
|
||||
class="filter-item"
|
||||
@keyup.enter.native="crud.toQuery"
|
||||
/>
|
||||
<date-range-picker v-model="query.createTime" class="date-item" />
|
||||
<el-select v-model="query.enabled" clearable size="small" placeholder="状态" class="filter-item" style="width: 90px" @change="crud.toQuery">
|
||||
<el-select
|
||||
v-model="query.enabled"
|
||||
clearable
|
||||
size="small"
|
||||
placeholder="状态"
|
||||
class="filter-item"
|
||||
style="width: 90px"
|
||||
@change="crud.toQuery"
|
||||
>
|
||||
<el-option v-for="item in enabledTypeOptions" :key="item.key" :label="item.display_name" :value="item.key" />
|
||||
</el-select>
|
||||
<rrOperation />
|
||||
@@ -14,7 +30,14 @@
|
||||
<crudOperation :permission="permission" />
|
||||
</div>
|
||||
<!--表单组件-->
|
||||
<el-dialog append-to-body :close-on-click-modal="false" :before-close="crud.cancelCU" :visible.sync="crud.status.cu > 0" :title="crud.status.title" width="500px">
|
||||
<el-dialog
|
||||
append-to-body
|
||||
:close-on-click-modal="false"
|
||||
:before-close="crud.cancelCU"
|
||||
:visible.sync="crud.status.cu > 0"
|
||||
:title="crud.status.title"
|
||||
width="500px"
|
||||
>
|
||||
<el-form ref="form" inline :model="form" :rules="rules" size="small" label-width="80px">
|
||||
<el-form-item label="部门名称" prop="name">
|
||||
<el-input v-model="form.name" style="width: 370px;" />
|
||||
@@ -44,7 +67,9 @@
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="enabled">
|
||||
<el-radio v-for="item in dict.dept_status" :key="item.id" v-model="form.enabled" :label="item.value">{{ item.label }}</el-radio>
|
||||
<el-radio v-for="item in dict.dept_status" :key="item.id" v-model="form.enabled" :label="item.value">
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
@@ -80,7 +105,13 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="createTime" label="创建日期" />
|
||||
<el-table-column v-if="checkPer(['admin','dept:edit','dept:del'])" label="操作" width="130px" align="center" fixed="right">
|
||||
<el-table-column
|
||||
v-if="checkPer(['admin','dept:edit','dept:del'])"
|
||||
label="操作"
|
||||
width="130px"
|
||||
align="center"
|
||||
fixed="right"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<udOperation
|
||||
:data="scope.row"
|
||||
@@ -96,10 +127,9 @@
|
||||
|
||||
<script>
|
||||
import crudDept from '@/api/system/dept'
|
||||
import Treeselect from '@riophae/vue-treeselect'
|
||||
import Treeselect, { LOAD_CHILDREN_OPTIONS } from '@riophae/vue-treeselect'
|
||||
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
|
||||
import { LOAD_CHILDREN_OPTIONS } from '@riophae/vue-treeselect'
|
||||
import CRUD, { presenter, header, form, crud } from '@crud/crud'
|
||||
import CRUD, { crud, form, header, presenter } from '@crud/crud'
|
||||
import rrOperation from '@crud/RR.operation'
|
||||
import crudOperation from '@crud/CRUD.operation'
|
||||
import udOperation from '@crud/UD.operation'
|
||||
@@ -254,13 +284,13 @@ export default {
|
||||
</script>
|
||||
|
||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||
::v-deep .vue-treeselect__control,::v-deep .vue-treeselect__placeholder,::v-deep .vue-treeselect__single-value {
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
}
|
||||
::v-deep .vue-treeselect__control, ::v-deep .vue-treeselect__placeholder, ::v-deep .vue-treeselect__single-value {
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
}
|
||||
</style>
|
||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||
::v-deep .el-input-number .el-input__inner {
|
||||
text-align: left;
|
||||
}
|
||||
::v-deep .el-input-number .el-input__inner {
|
||||
text-align: left;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -8,12 +8,27 @@
|
||||
<div class="head-container">
|
||||
<div v-if="crud.props.searchToggle">
|
||||
<!-- 搜索 -->
|
||||
<el-input v-model="query.label" clearable size="small" placeholder="输入字典标签查询" style="width: 200px;" class="filter-item" @keyup.enter.native="toQuery" />
|
||||
<el-input
|
||||
v-model="query.label"
|
||||
clearable
|
||||
size="small"
|
||||
placeholder="输入字典标签查询"
|
||||
style="width: 200px;"
|
||||
class="filter-item"
|
||||
@keyup.enter.native="toQuery"
|
||||
/>
|
||||
<rrOperation />
|
||||
</div>
|
||||
</div>
|
||||
<!--表单组件-->
|
||||
<el-dialog append-to-body :close-on-click-modal="false" :before-close="crud.cancelCU" :visible="crud.status.cu > 0" :title="crud.status.title" width="500px">
|
||||
<el-dialog
|
||||
append-to-body
|
||||
:close-on-click-modal="false"
|
||||
:before-close="crud.cancelCU"
|
||||
:visible="crud.status.cu > 0"
|
||||
:title="crud.status.title"
|
||||
width="500px"
|
||||
>
|
||||
<el-form ref="form" :model="form" :rules="rules" size="small" label-width="80px">
|
||||
<el-form-item label="字典标签" prop="label">
|
||||
<el-input v-model="form.label" style="width: 370px;" />
|
||||
@@ -22,7 +37,13 @@
|
||||
<el-input v-model="form.value" style="width: 370px;" />
|
||||
</el-form-item>
|
||||
<el-form-item label="排序" prop="dictSort">
|
||||
<el-input-number v-model.number="form.dictSort" :min="0" :max="999" controls-position="right" style="width: 370px;" />
|
||||
<el-input-number
|
||||
v-model.number="form.dictSort"
|
||||
:min="0"
|
||||
:max="999"
|
||||
controls-position="right"
|
||||
style="width: 370px;"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
@@ -31,14 +52,27 @@
|
||||
</div>
|
||||
</el-dialog>
|
||||
<!--表格渲染-->
|
||||
<el-table ref="table" v-loading="crud.loading" :data="crud.data" highlight-current-row style="width: 100%;" @selection-change="crud.selectionChangeHandler">
|
||||
<el-table
|
||||
ref="table"
|
||||
v-loading="crud.loading"
|
||||
:data="crud.data"
|
||||
highlight-current-row
|
||||
style="width: 100%;"
|
||||
@selection-change="crud.selectionChangeHandler"
|
||||
>
|
||||
<el-table-column label="所属字典">
|
||||
{{ query.dictName }}
|
||||
</el-table-column>
|
||||
<el-table-column prop="label" label="字典标签" />
|
||||
<el-table-column prop="value" label="字典值" />
|
||||
<el-table-column prop="dictSort" label="排序" />
|
||||
<el-table-column v-if="checkPer(['admin','dict:edit','dict:del'])" label="操作" width="130px" align="center" fixed="right">
|
||||
<el-table-column
|
||||
v-if="checkPer(['admin','dict:edit','dict:del'])"
|
||||
label="操作"
|
||||
width="130px"
|
||||
align="center"
|
||||
fixed="right"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<udOperation
|
||||
:data="scope.row"
|
||||
@@ -55,7 +89,7 @@
|
||||
|
||||
<script>
|
||||
import crudDictDetail from '@/api/system/dictDetail'
|
||||
import CRUD, { presenter, header, form } from '@crud/crud'
|
||||
import CRUD, { form, header, presenter } from '@crud/crud'
|
||||
import pagination from '@crud/Pagination'
|
||||
import rrOperation from '@crud/RR.operation'
|
||||
import udOperation from '@crud/UD.operation'
|
||||
@@ -66,7 +100,8 @@ export default {
|
||||
components: { pagination, rrOperation, udOperation },
|
||||
cruds() {
|
||||
return [
|
||||
CRUD({ title: '字典详情', url: 'api/dictDetail', query: { dictName: '' },
|
||||
CRUD({
|
||||
title: '字典详情', url: 'api/dictDetail', query: { dictName: '' },
|
||||
crudMethod: { ...crudDictDetail },
|
||||
optShow: {
|
||||
add: true,
|
||||
@@ -109,7 +144,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||
::v-deep .el-input-number .el-input__inner {
|
||||
text-align: left;
|
||||
}
|
||||
::v-deep .el-input-number .el-input__inner {
|
||||
text-align: left;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!--表单组件-->
|
||||
<el-dialog append-to-body :close-on-click-modal="false" :before-close="crud.cancelCU" :visible="crud.status.cu > 0" :title="crud.status.title" width="500px">
|
||||
<el-dialog
|
||||
append-to-body
|
||||
:close-on-click-modal="false"
|
||||
:before-close="crud.cancelCU"
|
||||
:visible="crud.status.cu > 0"
|
||||
:title="crud.status.title"
|
||||
width="500px"
|
||||
>
|
||||
<el-form ref="form" :model="form" :rules="rules" size="small" label-width="80px">
|
||||
<el-form-item label="字典名称" prop="name">
|
||||
<el-input v-model="form.name" style="width: 370px;" />
|
||||
@@ -23,17 +30,39 @@
|
||||
<div class="head-container">
|
||||
<div v-if="crud.props.searchToggle">
|
||||
<!-- 搜索 -->
|
||||
<el-input v-model="query.blurry" clearable size="small" placeholder="输入名称或者描述搜索" style="width: 200px;" class="filter-item" @keyup.enter.native="crud.toQuery" />
|
||||
<el-input
|
||||
v-model="query.blurry"
|
||||
clearable
|
||||
size="small"
|
||||
placeholder="输入名称或者描述搜索"
|
||||
style="width: 200px;"
|
||||
class="filter-item"
|
||||
@keyup.enter.native="crud.toQuery"
|
||||
/>
|
||||
<rrOperation />
|
||||
</div>
|
||||
<crudOperation :permission="permission" />
|
||||
</div>
|
||||
<!--表格渲染-->
|
||||
<el-table ref="table" v-loading="crud.loading" :data="crud.data" highlight-current-row style="width: 100%;" @selection-change="crud.selectionChangeHandler" @current-change="handleCurrentChange">
|
||||
<el-table
|
||||
ref="table"
|
||||
v-loading="crud.loading"
|
||||
:data="crud.data"
|
||||
highlight-current-row
|
||||
style="width: 100%;"
|
||||
@selection-change="crud.selectionChangeHandler"
|
||||
@current-change="handleCurrentChange"
|
||||
>
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column :show-overflow-tooltip="true" prop="name" label="名称" />
|
||||
<el-table-column :show-overflow-tooltip="true" prop="description" label="描述" />
|
||||
<el-table-column v-if="checkPer(['admin','dict:edit','dict:del'])" label="操作" width="130px" align="center" fixed="right">
|
||||
<el-table-column
|
||||
v-if="checkPer(['admin','dict:edit','dict:del'])"
|
||||
label="操作"
|
||||
width="130px"
|
||||
align="center"
|
||||
fixed="right"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<udOperation
|
||||
:data="scope.row"
|
||||
@@ -59,7 +88,8 @@
|
||||
type="primary"
|
||||
icon="el-icon-plus"
|
||||
@click="$refs.dictDetail && $refs.dictDetail.crud.toAdd()"
|
||||
>新增</el-button>
|
||||
>新增
|
||||
</el-button>
|
||||
</div>
|
||||
<dictDetail ref="dictDetail" :permission="permission" />
|
||||
</el-card>
|
||||
@@ -71,7 +101,7 @@
|
||||
<script>
|
||||
import dictDetail from './dictDetail'
|
||||
import crudDict from '@/api/system/dict'
|
||||
import CRUD, { presenter, header, form } from '@crud/crud'
|
||||
import CRUD, { form, header, presenter } from '@crud/crud'
|
||||
import crudOperation from '@crud/CRUD.operation'
|
||||
import pagination from '@crud/Pagination'
|
||||
import rrOperation from '@crud/RR.operation'
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import elFrame from '@/components/Iframe/index'
|
||||
|
||||
export default {
|
||||
name: 'DruidSqlConsole',
|
||||
components: { elFrame },
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
<script>
|
||||
import { getLastEmailConfig, modifyEmailConfig } from '@/api/system/email'
|
||||
|
||||
export default {
|
||||
name: 'Config',
|
||||
data() {
|
||||
|
||||
@@ -17,7 +17,11 @@
|
||||
# 密码(注意,某些邮箱需要为SMTP服务单独设置密码,如QQ和163等等)
|
||||
# 是否开启ssl,默认开启</pre>
|
||||
<blockquote class="my-blockquote">更多帮助</blockquote>
|
||||
<pre class="my-code">更多帮助请查看文档:<a style="color:#009688" href="http://hutool.mydoc.io/#text_319499" target="_black">hutool工具包</a></pre>
|
||||
<pre class="my-code">更多帮助请查看文档:<a
|
||||
style="color:#009688"
|
||||
href="http://hutool.mydoc.io/#text_319499"
|
||||
target="_black"
|
||||
>hutool工具包</a></pre>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
@@ -26,6 +30,7 @@
|
||||
<script>
|
||||
import Config from './config.vue'
|
||||
import Send from './send.vue'
|
||||
|
||||
export default {
|
||||
name: 'Email',
|
||||
components: { Config, Send },
|
||||
|
||||
@@ -8,16 +8,24 @@
|
||||
<el-input v-model="form.tos" style="width: 646px" placeholder="请输入收件地址,多个地址英文逗号,隔开" />
|
||||
</el-form-item>
|
||||
<div ref="editor" class="editor" />
|
||||
<el-button :loading="loading" style="margin-left:1.6%;margin-bottom: 30px" size="medium" type="primary" @click="doSubmit">发送邮件</el-button>
|
||||
<el-button
|
||||
:loading="loading"
|
||||
style="margin-left:1.6%;margin-bottom: 30px"
|
||||
size="medium"
|
||||
type="primary"
|
||||
@click="doSubmit"
|
||||
>发送邮件
|
||||
</el-button>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { sendEmail } from '@/api/system/email'
|
||||
import { upload } from '@/utils/upload'
|
||||
import { mapGetters } from 'vuex'
|
||||
import E from 'wangeditor'
|
||||
import { UploadFile } from '@/utils/CsDomUtil'
|
||||
|
||||
export default {
|
||||
name: 'Index',
|
||||
data() {
|
||||
@@ -49,7 +57,7 @@ export default {
|
||||
// files 是 input 中选中的文件列表
|
||||
// insert 是获取图片 url 后,插入到编辑器的方法
|
||||
files.forEach(image => {
|
||||
upload(_this.imagesUploadApi, image).then(res => {
|
||||
UploadFile(_this.imagesUploadApi, image).then(res => {
|
||||
const data = res.data
|
||||
const url = _this.baseApi + '/file/' + data.type + '/' + data.realName
|
||||
insert(url)
|
||||
@@ -87,12 +95,13 @@ export default {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.editor{
|
||||
text-align:left;
|
||||
margin: 20px;
|
||||
width: 730px;
|
||||
}
|
||||
::v-deep .w-e-text-container {
|
||||
height: 360px !important;
|
||||
}
|
||||
.editor {
|
||||
text-align: left;
|
||||
margin: 20px;
|
||||
width: 730px;
|
||||
}
|
||||
|
||||
::v-deep .w-e-text-container {
|
||||
height: 360px !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -6,7 +6,13 @@
|
||||
<crudOperation :permission="permission" />
|
||||
</div>
|
||||
<!--表格渲染-->
|
||||
<el-table ref="table" v-loading="crud.loading" :data="crud.data" style="width: 100%;" @selection-change="crud.selectionChangeHandler">
|
||||
<el-table
|
||||
ref="table"
|
||||
v-loading="crud.loading"
|
||||
:data="crud.data"
|
||||
style="width: 100%;"
|
||||
@selection-change="crud.selectionChangeHandler"
|
||||
>
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column prop="name" label="名称" />
|
||||
<el-table-column prop="jobSort" label="排序">
|
||||
@@ -56,6 +62,7 @@ import CRUD, { presenter } from '@crud/crud'
|
||||
import crudOperation from '@crud/CRUD.operation'
|
||||
import pagination from '@crud/Pagination'
|
||||
import udOperation from '@crud/UD.operation'
|
||||
|
||||
export default {
|
||||
name: 'Job',
|
||||
components: { eHeader, eForm, crudOperation, pagination, udOperation },
|
||||
@@ -103,7 +110,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||
::v-deep .el-input-number .el-input__inner {
|
||||
text-align: left;
|
||||
}
|
||||
::v-deep .el-input-number .el-input__inner {
|
||||
text-align: left;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -104,7 +104,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||
::v-deep .el-input-number .el-input__inner {
|
||||
text-align: left;
|
||||
}
|
||||
::v-deep .el-input-number .el-input__inner {
|
||||
text-align: left;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -2,9 +2,25 @@
|
||||
<div
|
||||
v-if="crud.props.searchToggle"
|
||||
>
|
||||
<el-input v-model="query.name" clearable size="small" placeholder="输入岗位名称搜索" style="width: 200px;" class="filter-item" @keyup.enter.native="crud.toQuery" />
|
||||
<el-input
|
||||
v-model="query.name"
|
||||
clearable
|
||||
size="small"
|
||||
placeholder="输入岗位名称搜索"
|
||||
style="width: 200px;"
|
||||
class="filter-item"
|
||||
@keyup.enter.native="crud.toQuery"
|
||||
/>
|
||||
<date-range-picker v-model="query.createTime" class="date-item" />
|
||||
<el-select v-model="query.enabled" clearable size="small" placeholder="状态" class="filter-item" style="width: 90px" @change="crud.toQuery">
|
||||
<el-select
|
||||
v-model="query.enabled"
|
||||
clearable
|
||||
size="small"
|
||||
placeholder="状态"
|
||||
class="filter-item"
|
||||
style="width: 90px"
|
||||
@change="crud.toQuery"
|
||||
>
|
||||
<el-option v-for="item in dict.dict.job_status" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
<rrOperation />
|
||||
@@ -15,6 +31,7 @@
|
||||
import { header } from '@crud/crud'
|
||||
import rrOperation from '@crud/RR.operation'
|
||||
import DateRangePicker from '@/components/DateRangePicker'
|
||||
|
||||
export default {
|
||||
components: { rrOperation, DateRangePicker },
|
||||
mixins: [header()],
|
||||
|
||||
@@ -4,14 +4,29 @@
|
||||
<div class="head-container">
|
||||
<div v-if="crud.props.searchToggle">
|
||||
<!-- 搜索 -->
|
||||
<el-input v-model="query.blurry" clearable size="small" placeholder="模糊搜索" style="width: 200px;" class="filter-item" @keyup.enter.native="crud.toQuery" />
|
||||
<el-input
|
||||
v-model="query.blurry"
|
||||
clearable
|
||||
size="small"
|
||||
placeholder="模糊搜索"
|
||||
style="width: 200px;"
|
||||
class="filter-item"
|
||||
@keyup.enter.native="crud.toQuery"
|
||||
/>
|
||||
<date-range-picker v-model="query.createTime" class="date-item" />
|
||||
<rrOperation />
|
||||
</div>
|
||||
<crudOperation :permission="permission" />
|
||||
</div>
|
||||
<!--表单渲染-->
|
||||
<el-dialog append-to-body :close-on-click-modal="false" :before-close="crud.cancelCU" :visible.sync="crud.status.cu > 0" :title="crud.status.title" width="580px">
|
||||
<el-dialog
|
||||
append-to-body
|
||||
:close-on-click-modal="false"
|
||||
:before-close="crud.cancelCU"
|
||||
:visible.sync="crud.status.cu > 0"
|
||||
:title="crud.status.title"
|
||||
width="580px"
|
||||
>
|
||||
<el-form ref="form" :inline="true" :model="form" :rules="rules" size="small" label-width="80px">
|
||||
<el-form-item label="菜单类型" prop="type">
|
||||
<el-radio-group v-model="form.type" size="mini" style="width: 178px">
|
||||
@@ -29,7 +44,13 @@
|
||||
>
|
||||
<IconSelect ref="iconSelect" @selected="selected" />
|
||||
<el-input slot="reference" v-model="form.icon" style="width: 450px;" placeholder="点击选择图标" readonly>
|
||||
<svg-icon v-if="form.icon" slot="prefix" :icon-class="form.icon" class="el-input__icon" style="height: 32px;width: 16px;" />
|
||||
<svg-icon
|
||||
v-if="form.icon"
|
||||
slot="prefix"
|
||||
:icon-class="form.icon"
|
||||
class="el-input__icon"
|
||||
style="height: 32px;width: 16px;"
|
||||
/>
|
||||
<i v-else slot="prefix" class="el-icon-search el-input__icon" />
|
||||
</el-input>
|
||||
</el-popover>
|
||||
@@ -53,24 +74,47 @@
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.type.toString() !== '2'" label="菜单标题" prop="title">
|
||||
<el-input v-model="form.title" :style=" form.type.toString() === '0' ? 'width: 450px' : 'width: 178px'" placeholder="菜单标题" />
|
||||
<el-input
|
||||
v-model="form.title"
|
||||
:style=" form.type.toString() === '0' ? 'width: 450px' : 'width: 178px'"
|
||||
placeholder="菜单标题"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.type.toString() === '2'" label="按钮名称" prop="title">
|
||||
<el-input v-model="form.title" placeholder="按钮名称" style="width: 178px;" />
|
||||
</el-form-item>
|
||||
<el-form-item v-show="form.type.toString() !== '0'" label="权限标识" prop="permission">
|
||||
<el-input v-model="form.permission" :disabled="form.iFrame.toString() === 'true'" placeholder="权限标识" style="width: 178px;" />
|
||||
<el-input
|
||||
v-model="form.permission"
|
||||
:disabled="form.iFrame.toString() === 'true'"
|
||||
placeholder="权限标识"
|
||||
style="width: 178px;"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.type.toString() !== '2'" label="路由地址" prop="path">
|
||||
<el-input v-model="form.path" placeholder="路由地址" style="width: 178px;" />
|
||||
</el-form-item>
|
||||
<el-form-item label="菜单排序" prop="menuSort">
|
||||
<el-input-number v-model.number="form.menuSort" :min="0" :max="999" controls-position="right" style="width: 178px;" />
|
||||
<el-input-number
|
||||
v-model.number="form.menuSort"
|
||||
:min="0"
|
||||
:max="999"
|
||||
controls-position="right"
|
||||
style="width: 178px;"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item v-show="form.iFrame.toString() !== 'true' && form.type.toString() === '1'" label="组件名称" prop="componentName">
|
||||
<el-form-item
|
||||
v-show="form.iFrame.toString() !== 'true' && form.type.toString() === '1'"
|
||||
label="组件名称"
|
||||
prop="componentName"
|
||||
>
|
||||
<el-input v-model="form.componentName" style="width: 450px;" placeholder="匹配组件内Name字段" />
|
||||
</el-form-item>
|
||||
<el-form-item v-show="form.iFrame.toString() !== 'true' && form.type.toString() === '1'" label="组件路径" prop="component">
|
||||
<el-form-item
|
||||
v-show="form.iFrame.toString() !== 'true' && form.type.toString() === '1'"
|
||||
label="组件路径"
|
||||
prop="component"
|
||||
>
|
||||
<el-input v-model="form.component" style="width: 450px;" placeholder="组件路径" />
|
||||
</el-form-item>
|
||||
<el-form-item label="上级类目" prop="pid">
|
||||
@@ -134,7 +178,13 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="createTime" label="创建日期" width="135px" />
|
||||
<el-table-column v-if="checkPer(['admin','menu:edit','menu:del'])" label="操作" width="130px" align="center" fixed="right">
|
||||
<el-table-column
|
||||
v-if="checkPer(['admin','menu:edit','menu:del'])"
|
||||
label="操作"
|
||||
width="130px"
|
||||
align="center"
|
||||
fixed="right"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<udOperation
|
||||
:data="scope.row"
|
||||
@@ -150,17 +200,31 @@
|
||||
<script>
|
||||
import crudMenu from '@/api/system/menu'
|
||||
import IconSelect from '@/components/IconSelect'
|
||||
import Treeselect from '@riophae/vue-treeselect'
|
||||
import Treeselect, { LOAD_CHILDREN_OPTIONS } from '@riophae/vue-treeselect'
|
||||
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
|
||||
import { LOAD_CHILDREN_OPTIONS } from '@riophae/vue-treeselect'
|
||||
import CRUD, { presenter, header, form, crud } from '@crud/crud'
|
||||
import CRUD, { crud, form, header, presenter } from '@crud/crud'
|
||||
import rrOperation from '@crud/RR.operation'
|
||||
import crudOperation from '@crud/CRUD.operation'
|
||||
import udOperation from '@crud/UD.operation'
|
||||
import DateRangePicker from '@/components/DateRangePicker'
|
||||
|
||||
// crud交由presenter持有
|
||||
const defaultForm = { id: null, title: null, menuSort: 999, path: null, component: null, componentName: null, iFrame: false, roles: [], pid: 0, icon: null, cache: false, hidden: false, type: 0, permission: null }
|
||||
const defaultForm = {
|
||||
id: null,
|
||||
title: null,
|
||||
menuSort: 999,
|
||||
path: null,
|
||||
component: null,
|
||||
componentName: null,
|
||||
iFrame: false,
|
||||
roles: [],
|
||||
pid: 0,
|
||||
icon: null,
|
||||
cache: false,
|
||||
hidden: false,
|
||||
type: 0,
|
||||
permission: null
|
||||
}
|
||||
export default {
|
||||
name: 'Menu',
|
||||
components: { Treeselect, IconSelect, crudOperation, rrOperation, udOperation, DateRangePicker },
|
||||
@@ -246,11 +310,12 @@ export default {
|
||||
</script>
|
||||
|
||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||
::v-deep .el-input-number .el-input__inner {
|
||||
text-align: left;
|
||||
}
|
||||
::v-deep .vue-treeselect__control,::v-deep .vue-treeselect__placeholder,::v-deep .vue-treeselect__single-value {
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
}
|
||||
::v-deep .el-input-number .el-input__inner {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
::v-deep .vue-treeselect__control, ::v-deep .vue-treeselect__placeholder, ::v-deep .vue-treeselect__single-value {
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -2,7 +2,15 @@
|
||||
<div class="app-container">
|
||||
<div class="head-container">
|
||||
<div v-if="crud.props.searchToggle">
|
||||
<el-input v-model="query.userName" clearable size="small" placeholder="输入用户名称查询" style="width: 200px;" class="filter-item" @keyup.enter.native="crud.toQuery" />
|
||||
<el-input
|
||||
v-model="query.userName"
|
||||
clearable
|
||||
size="small"
|
||||
placeholder="输入用户名称查询"
|
||||
style="width: 200px;"
|
||||
class="filter-item"
|
||||
@keyup.enter.native="crud.toQuery"
|
||||
/>
|
||||
<rrOperation />
|
||||
</div>
|
||||
<crudOperation>
|
||||
@@ -21,7 +29,13 @@
|
||||
</crudOperation>
|
||||
</div>
|
||||
<!--表格渲染-->
|
||||
<el-table ref="table" v-loading="crud.loading" :data="crud.data" style="width: 100%;" @selection-change="crud.selectionChangeHandler">
|
||||
<el-table
|
||||
ref="table"
|
||||
v-loading="crud.loading"
|
||||
:data="crud.data"
|
||||
style="width: 100%;"
|
||||
@selection-change="crud.selectionChangeHandler"
|
||||
>
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column :show-overflow-tooltip="true" prop="uid" label="会话编号" />
|
||||
<el-table-column prop="userName" label="用户名" />
|
||||
@@ -42,7 +56,13 @@
|
||||
<p>确定强制退出该用户吗?</p>
|
||||
<div style="text-align: right; margin: 0">
|
||||
<el-button size="mini" type="text" @click="$refs[scope.$index].doClose()">取消</el-button>
|
||||
<el-button :loading="delLoading" type="primary" size="mini" @click="delMethod(scope.row.key, scope.$index)">确定</el-button>
|
||||
<el-button
|
||||
:loading="delLoading"
|
||||
type="primary"
|
||||
size="mini"
|
||||
@click="delMethod(scope.row.key, scope.$index)"
|
||||
>确定
|
||||
</el-button>
|
||||
</div>
|
||||
<el-button slot="reference" size="mini" type="text">强退</el-button>
|
||||
</el-popover>
|
||||
@@ -56,7 +76,7 @@
|
||||
|
||||
<script>
|
||||
import { kickOutUser } from '@/api/system/online'
|
||||
import CRUD, { presenter, header, crud } from '@crud/crud'
|
||||
import CRUD, { crud, header, presenter } from '@crud/crud'
|
||||
import rrOperation from '@crud/RR.operation'
|
||||
import crudOperation from '@crud/CRUD.operation'
|
||||
import pagination from '@crud/Pagination'
|
||||
@@ -91,7 +111,8 @@ export default {
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.delMethod(datas)
|
||||
}).catch(() => {})
|
||||
}).catch(() => {
|
||||
})
|
||||
},
|
||||
// 踢出用户
|
||||
delMethod(key, index) {
|
||||
|
||||
@@ -4,7 +4,15 @@
|
||||
<div class="head-container">
|
||||
<div v-if="crud.props.searchToggle">
|
||||
<!-- 搜索 -->
|
||||
<el-input v-model="query.jobName" clearable size="small" placeholder="输入任务名称搜索" style="width: 200px;" class="filter-item" @keyup.enter.native="toQuery" />
|
||||
<el-input
|
||||
v-model="query.jobName"
|
||||
clearable
|
||||
size="small"
|
||||
placeholder="输入任务名称搜索"
|
||||
style="width: 200px;"
|
||||
class="filter-item"
|
||||
@keyup.enter.native="toQuery"
|
||||
/>
|
||||
<date-range-picker v-model="query.createTime" class="date-item" />
|
||||
<rrOperation />
|
||||
</div>
|
||||
@@ -17,12 +25,20 @@
|
||||
type="info"
|
||||
icon="el-icon-tickets"
|
||||
@click="doLog"
|
||||
>日志</el-button>
|
||||
>日志
|
||||
</el-button>
|
||||
</crudOperation>
|
||||
<Log ref="log" />
|
||||
</div>
|
||||
<!--Form表单-->
|
||||
<el-dialog :close-on-click-modal="false" :before-close="crud.cancelCU" :visible.sync="crud.status.cu > 0" :title="crud.status.title" append-to-body width="730px">
|
||||
<el-dialog
|
||||
:close-on-click-modal="false"
|
||||
:before-close="crud.cancelCU"
|
||||
:visible.sync="crud.status.cu > 0"
|
||||
:title="crud.status.title"
|
||||
append-to-body
|
||||
width="730px"
|
||||
>
|
||||
<el-form ref="form" :inline="true" :model="form" :rules="rules" size="small" label-width="100px">
|
||||
<el-form-item label="任务名称" prop="jobName">
|
||||
<el-input v-model="form.jobName" style="width: 220px;" />
|
||||
@@ -70,7 +86,13 @@
|
||||
</div>
|
||||
</el-dialog>
|
||||
<!--表格渲染-->
|
||||
<el-table ref="table" v-loading="crud.loading" :data="crud.data" style="width: 100%;" @selection-change="crud.selectionChangeHandler">
|
||||
<el-table
|
||||
ref="table"
|
||||
v-loading="crud.loading"
|
||||
:data="crud.data"
|
||||
style="width: 100%;"
|
||||
@selection-change="crud.selectionChangeHandler"
|
||||
>
|
||||
<el-table-column :selectable="checkboxT" type="selection" width="55" />
|
||||
<el-table-column :show-overflow-tooltip="true" prop="id" label="任务ID" />
|
||||
<el-table-column :show-overflow-tooltip="true" prop="jobName" label="任务名称" />
|
||||
@@ -80,16 +102,45 @@
|
||||
<el-table-column :show-overflow-tooltip="true" prop="cronExpression" label="cron表达式" />
|
||||
<el-table-column :show-overflow-tooltip="true" prop="isPause" width="90px" label="状态">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="scope.row.isPause ? 'warning' : 'success'">{{ scope.row.isPause ? '已暂停' : '运行中' }}</el-tag>
|
||||
<el-tag :type="scope.row.isPause ? 'warning' : 'success'">{{
|
||||
scope.row.isPause ? '已暂停' : '运行中'
|
||||
}}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :show-overflow-tooltip="true" prop="description" width="150px" label="描述" />
|
||||
<el-table-column :show-overflow-tooltip="true" prop="createTime" width="136px" label="创建日期" />
|
||||
<el-table-column v-if="checkPer(['admin','quartzJob:edit','quartzJob:del'])" label="操作" width="170px" align="center" fixed="right">
|
||||
<el-table-column
|
||||
v-if="checkPer(['admin','quartzJob:edit','quartzJob:del'])"
|
||||
label="操作"
|
||||
width="170px"
|
||||
align="center"
|
||||
fixed="right"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-button v-permission="['admin','quartzJob:edit']" size="mini" style="margin-right: 3px;" type="text" @click="crud.toEdit(scope.row)">编辑</el-button>
|
||||
<el-button v-permission="['admin','quartzJob:edit']" style="margin-left: -2px" type="text" size="mini" @click="execute(scope.row.id)">执行</el-button>
|
||||
<el-button v-permission="['admin','quartzJob:edit']" style="margin-left: 3px" type="text" size="mini" @click="updateStatus(scope.row.id,scope.row.isPause ? '恢复' : '暂停')">
|
||||
<el-button
|
||||
v-permission="['admin','quartzJob:edit']"
|
||||
size="mini"
|
||||
style="margin-right: 3px;"
|
||||
type="text"
|
||||
@click="crud.toEdit(scope.row)"
|
||||
>编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
v-permission="['admin','quartzJob:edit']"
|
||||
style="margin-left: -2px"
|
||||
type="text"
|
||||
size="mini"
|
||||
@click="execute(scope.row.id)"
|
||||
>执行
|
||||
</el-button>
|
||||
<el-button
|
||||
v-permission="['admin','quartzJob:edit']"
|
||||
style="margin-left: 3px"
|
||||
type="text"
|
||||
size="mini"
|
||||
@click="updateStatus(scope.row.id,scope.row.isPause ? '恢复' : '暂停')"
|
||||
>
|
||||
{{ scope.row.isPause ? '恢复' : '暂停' }}
|
||||
</el-button>
|
||||
<el-popover
|
||||
@@ -101,7 +152,8 @@
|
||||
<p>确定停止并删除该任务吗?</p>
|
||||
<div style="text-align: right; margin: 0">
|
||||
<el-button size="mini" type="text" @click="$refs[scope.row.id].doClose()">取消</el-button>
|
||||
<el-button :loading="delLoading" type="primary" size="mini" @click="delMethod(scope.row.id)">确定</el-button>
|
||||
<el-button :loading="delLoading" type="primary" size="mini" @click="delMethod(scope.row.id)">确定
|
||||
</el-button>
|
||||
</div>
|
||||
<el-button slot="reference" type="text" size="mini">删除</el-button>
|
||||
</el-popover>
|
||||
@@ -116,13 +168,26 @@
|
||||
<script>
|
||||
import crudJob from '@/api/system/quartzJob'
|
||||
import Log from './log'
|
||||
import CRUD, { presenter, header, form, crud } from '@crud/crud'
|
||||
import CRUD, { crud, form, header, presenter } from '@crud/crud'
|
||||
import rrOperation from '@crud/RR.operation'
|
||||
import crudOperation from '@crud/CRUD.operation'
|
||||
import pagination from '@crud/Pagination'
|
||||
import DateRangePicker from '@/components/DateRangePicker'
|
||||
|
||||
const defaultForm = { id: null, jobName: null, subTask: null, beanName: null, methodName: null, params: null, cronExpression: null, pauseAfterFailure: true, isPause: false, personInCharge: null, email: null, description: null }
|
||||
const defaultForm = {
|
||||
id: null,
|
||||
jobName: null,
|
||||
subTask: null,
|
||||
beanName: null,
|
||||
methodName: null,
|
||||
params: null,
|
||||
cronExpression: null,
|
||||
pauseAfterFailure: true,
|
||||
isPause: false,
|
||||
personInCharge: null,
|
||||
email: null,
|
||||
description: null
|
||||
}
|
||||
export default {
|
||||
name: 'QuartzJob',
|
||||
components: { Log, pagination, crudOperation, rrOperation, DateRangePicker },
|
||||
|
||||
@@ -2,9 +2,25 @@
|
||||
<el-dialog :visible.sync="dialog" append-to-body title="执行日志" width="88%">
|
||||
<!-- 搜索 -->
|
||||
<div class="head-container">
|
||||
<el-input v-model="query.jobName" clearable size="small" placeholder="输入任务名称搜索" style="width: 200px;" class="filter-item" @keyup.enter.native="toQuery" />
|
||||
<el-input
|
||||
v-model="query.jobName"
|
||||
clearable
|
||||
size="small"
|
||||
placeholder="输入任务名称搜索"
|
||||
style="width: 200px;"
|
||||
class="filter-item"
|
||||
@keyup.enter.native="toQuery"
|
||||
/>
|
||||
<date-range-picker v-model="query.createTime" class="date-item" />
|
||||
<el-select v-model="query.isSuccess" placeholder="日志状态" clearable size="small" class="filter-item" style="width: 110px" @change="toQuery">
|
||||
<el-select
|
||||
v-model="query.isSuccess"
|
||||
placeholder="日志状态"
|
||||
clearable
|
||||
size="small"
|
||||
class="filter-item"
|
||||
style="width: 110px"
|
||||
@change="toQuery"
|
||||
>
|
||||
<el-option v-for="item in enabledTypeOptions" :key="item.key" :label="item.displayName" :value="item.key" />
|
||||
</el-select>
|
||||
<el-button class="filter-item" size="mini" type="success" icon="el-icon-search" @click="toQuery">搜索</el-button>
|
||||
@@ -17,7 +33,8 @@
|
||||
type="warning"
|
||||
icon="el-icon-download"
|
||||
@click="downloadMethod"
|
||||
>导出</el-button>
|
||||
>导出
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<!--表格渲染-->
|
||||
@@ -29,13 +46,22 @@
|
||||
<el-table-column :show-overflow-tooltip="true" prop="cronExpression" label="cron表达式" />
|
||||
<el-table-column prop="createTime" label="异常详情" width="110px">
|
||||
<template slot-scope="scope">
|
||||
<el-button v-show="scope.row.exceptionDetail" size="mini" type="text" @click="info(scope.row.exceptionDetail)">查看详情</el-button>
|
||||
<el-button
|
||||
v-show="scope.row.exceptionDetail"
|
||||
size="mini"
|
||||
type="text"
|
||||
@click="info(scope.row.exceptionDetail)"
|
||||
>查看详情
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :show-overflow-tooltip="true" align="center" prop="time" width="100px" label="耗时(毫秒)" />
|
||||
<el-table-column align="center" prop="isSuccess" width="80px" label="状态">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="scope.row.isSuccess ? 'success' : 'danger'">{{ scope.row.isSuccess ? '成功' : '失败' }}</el-tag>
|
||||
<el-tag :type="scope.row.isSuccess ? 'success' : 'danger'">{{
|
||||
scope.row.isSuccess ? '成功' : '失败'
|
||||
}}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :show-overflow-tooltip="true" prop="createTime" label="创建日期" />
|
||||
@@ -59,6 +85,7 @@
|
||||
<script>
|
||||
import crud from '@/mixins/crud'
|
||||
import DateRangePicker from '@/components/DateRangePicker'
|
||||
|
||||
export default {
|
||||
components: { DateRangePicker },
|
||||
// Mixins 是一种包含多个组件选项的对象。可以将 mixin 作为组件的一个选项引入,从而在该组件中“混入”这个对象的选项。通过这种方式,mixins 可以帮助你实现功能复用,减少重复代码。
|
||||
@@ -96,11 +123,12 @@ export default {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.java.hljs{
|
||||
color: #444;
|
||||
background: #ffffff !important;
|
||||
}
|
||||
::v-deep .el-dialog__body{
|
||||
padding: 0 20px 10px 20px !important;
|
||||
}
|
||||
.java.hljs {
|
||||
color: #444;
|
||||
background: #ffffff !important;
|
||||
}
|
||||
|
||||
::v-deep .el-dialog__body {
|
||||
padding: 0 20px 10px 20px !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -4,14 +4,29 @@
|
||||
<div class="head-container">
|
||||
<div v-if="crud.props.searchToggle">
|
||||
<!-- 搜索 -->
|
||||
<el-input v-model="query.blurry" size="small" clearable placeholder="输入名称或者描述搜索" style="width: 200px;" class="filter-item" @keyup.enter.native="crud.toQuery" />
|
||||
<el-input
|
||||
v-model="query.blurry"
|
||||
size="small"
|
||||
clearable
|
||||
placeholder="输入名称或者描述搜索"
|
||||
style="width: 200px;"
|
||||
class="filter-item"
|
||||
@keyup.enter.native="crud.toQuery"
|
||||
/>
|
||||
<date-range-picker v-model="query.createTime" class="date-item" />
|
||||
<rrOperation />
|
||||
</div>
|
||||
<crudOperation :permission="permission" />
|
||||
</div>
|
||||
<!-- 表单渲染 -->
|
||||
<el-dialog append-to-body :close-on-click-modal="false" :before-close="crud.cancelCU" :visible.sync="crud.status.cu > 0" :title="crud.status.title" width="520px">
|
||||
<el-dialog
|
||||
append-to-body
|
||||
:close-on-click-modal="false"
|
||||
:before-close="crud.cancelCU"
|
||||
:visible.sync="crud.status.cu > 0"
|
||||
:title="crud.status.title"
|
||||
width="520px"
|
||||
>
|
||||
<el-form ref="form" :inline="true" :model="form" :rules="rules" size="small" label-width="80px">
|
||||
<el-form-item label="角色名称" prop="name">
|
||||
<el-input v-model="form.name" style="width: 380px;" />
|
||||
@@ -58,7 +73,15 @@
|
||||
<div slot="header" class="clearfix">
|
||||
<span class="role-span">角色列表</span>
|
||||
</div>
|
||||
<el-table ref="table" v-loading="crud.loading" highlight-current-row style="width: 100%;" :data="crud.data" @selection-change="crud.selectionChangeHandler" @current-change="handleCurrentChange">
|
||||
<el-table
|
||||
ref="table"
|
||||
v-loading="crud.loading"
|
||||
highlight-current-row
|
||||
style="width: 100%;"
|
||||
:data="crud.data"
|
||||
@selection-change="crud.selectionChangeHandler"
|
||||
@current-change="handleCurrentChange"
|
||||
>
|
||||
<el-table-column :selectable="checkboxT" type="selection" width="55" />
|
||||
<el-table-column prop="name" label="名称" />
|
||||
<el-table-column prop="dataScope" label="数据权限" />
|
||||
@@ -69,7 +92,13 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :show-overflow-tooltip="true" width="135px" prop="createTime" label="创建日期" />
|
||||
<el-table-column v-if="checkPer(['admin','roles:edit','roles:del'])" label="操作" width="130px" align="center" fixed="right">
|
||||
<el-table-column
|
||||
v-if="checkPer(['admin','roles:edit','roles:del'])"
|
||||
label="操作"
|
||||
width="130px"
|
||||
align="center"
|
||||
fixed="right"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<udOperation
|
||||
v-if="scope.row.level >= level"
|
||||
@@ -99,7 +128,8 @@
|
||||
style="float: right; padding: 6px 9px"
|
||||
type="primary"
|
||||
@click="saveMenu"
|
||||
>保存</el-button>
|
||||
>保存
|
||||
</el-button>
|
||||
</div>
|
||||
<el-tree
|
||||
ref="menu"
|
||||
@@ -123,15 +153,14 @@
|
||||
<script>
|
||||
import crudRoles from '@/api/system/role'
|
||||
import { queryDeptList, queryDeptSuperiorTree } from '@/api/system/dept'
|
||||
import { queryMenuListByPid, queryChildMenuSet } from '@/api/system/menu'
|
||||
import CRUD, { presenter, header, form, crud } from '@crud/crud'
|
||||
import { queryChildMenuSet, queryMenuListByPid } from '@/api/system/menu'
|
||||
import CRUD, { crud, form, header, presenter } from '@crud/crud'
|
||||
import rrOperation from '@crud/RR.operation'
|
||||
import crudOperation from '@crud/CRUD.operation'
|
||||
import udOperation from '@crud/UD.operation'
|
||||
import pagination from '@crud/Pagination'
|
||||
import Treeselect from '@riophae/vue-treeselect'
|
||||
import Treeselect, { LOAD_CHILDREN_OPTIONS } from '@riophae/vue-treeselect'
|
||||
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
|
||||
import { LOAD_CHILDREN_OPTIONS } from '@riophae/vue-treeselect'
|
||||
import DateRangePicker from '@/components/DateRangePicker'
|
||||
|
||||
const defaultForm = { id: null, name: null, depts: [], description: null, dataScope: '全部', level: 3 }
|
||||
@@ -352,21 +381,24 @@ export default {
|
||||
</script>
|
||||
|
||||
<style rel="stylesheet/scss" lang="scss">
|
||||
.role-span {
|
||||
font-weight: bold;color: #303133;
|
||||
font-size: 15px;
|
||||
}
|
||||
.role-span {
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
font-size: 15px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||
::v-deep .el-input-number .el-input__inner {
|
||||
text-align: left;
|
||||
}
|
||||
::v-deep .vue-treeselect__multi-value{
|
||||
margin-bottom: 0;
|
||||
}
|
||||
::v-deep .vue-treeselect__multi-value-item{
|
||||
border: 0;
|
||||
padding: 0;
|
||||
}
|
||||
::v-deep .el-input-number .el-input__inner {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
::v-deep .vue-treeselect__multi-value {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
::v-deep .vue-treeselect__multi-value-item {
|
||||
border: 0;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<template>
|
||||
<div v-loading="!show" element-loading-text="数据加载中..." :style="!show ? 'height: 500px' : 'height: 100%'" class="app-container">
|
||||
<div
|
||||
v-loading="!show"
|
||||
element-loading-text="数据加载中..."
|
||||
:style="!show ? 'height: 500px' : 'height: 100%'"
|
||||
class="app-container"
|
||||
>
|
||||
<div v-if="show">
|
||||
<el-card class="box-card">
|
||||
<div style="color: #666;font-size: 13px;">
|
||||
@@ -139,6 +144,7 @@ import ECharts from 'vue-echarts'
|
||||
import 'echarts/lib/chart/line'
|
||||
import 'echarts/lib/component/polar'
|
||||
import { initDataByPost } from '@/api/data'
|
||||
|
||||
export default {
|
||||
name: 'ServerMonitor',
|
||||
components: {
|
||||
@@ -251,41 +257,47 @@ export default {
|
||||
</script>
|
||||
|
||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||
::v-deep .box-card {
|
||||
margin-bottom: 5px;
|
||||
span {
|
||||
margin-right: 28px;
|
||||
}
|
||||
.el-icon-refresh {
|
||||
margin-right: 10px;
|
||||
float: right;
|
||||
cursor:pointer;
|
||||
}
|
||||
::v-deep .box-card {
|
||||
margin-bottom: 5px;
|
||||
|
||||
span {
|
||||
margin-right: 28px;
|
||||
}
|
||||
.cpu, .memory, .swap, .disk {
|
||||
width: 20%;
|
||||
float: left;
|
||||
padding-bottom: 20px;
|
||||
margin-right: 5%;
|
||||
}
|
||||
.title {
|
||||
text-align: center;
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
color: #999;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.footer {
|
||||
text-align: center;
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
color: #999;
|
||||
margin-top: -5px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.content {
|
||||
text-align: center;
|
||||
margin-top: 5px;
|
||||
margin-bottom: 5px;
|
||||
|
||||
.el-icon-refresh {
|
||||
margin-right: 10px;
|
||||
float: right;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.cpu, .memory, .swap, .disk {
|
||||
width: 20%;
|
||||
float: left;
|
||||
padding-bottom: 20px;
|
||||
margin-right: 5%;
|
||||
}
|
||||
|
||||
.title {
|
||||
text-align: center;
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
color: #999;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
text-align: center;
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
color: #999;
|
||||
margin-top: -5px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.content {
|
||||
text-align: center;
|
||||
margin-top: 5px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
<script>
|
||||
import Local from './local/index.vue'
|
||||
import Oss from './oss/index.vue'
|
||||
|
||||
export default {
|
||||
name: 'Storage',
|
||||
components: { Local, Oss },
|
||||
|
||||
@@ -4,7 +4,15 @@
|
||||
<div class="head-container">
|
||||
<div v-if="crud.props.searchToggle">
|
||||
<!-- 搜索 -->
|
||||
<el-input v-model="query.blurry" clearable size="small" placeholder="输入内容模糊搜索" style="width: 200px;" class="filter-item" @keyup.enter.native="crud.toQuery" />
|
||||
<el-input
|
||||
v-model="query.blurry"
|
||||
clearable
|
||||
size="small"
|
||||
placeholder="输入内容模糊搜索"
|
||||
style="width: 200px;"
|
||||
class="filter-item"
|
||||
@keyup.enter.native="crud.toQuery"
|
||||
/>
|
||||
<date-range-picker v-model="query.createTime" class="date-item" />
|
||||
<rrOperation />
|
||||
</div>
|
||||
@@ -23,7 +31,14 @@
|
||||
</crudOperation>
|
||||
</div>
|
||||
<!--表单组件-->
|
||||
<el-dialog append-to-body :close-on-click-modal="false" :before-close="crud.cancelCU" :visible.sync="crud.status.cu > 0" :title="crud.status.add ? '文件上传' : '编辑文件'" width="500px">
|
||||
<el-dialog
|
||||
append-to-body
|
||||
:close-on-click-modal="false"
|
||||
:before-close="crud.cancelCU"
|
||||
:visible.sync="crud.status.cu > 0"
|
||||
:title="crud.status.add ? '文件上传' : '编辑文件'"
|
||||
width="500px"
|
||||
>
|
||||
<el-form ref="form" :model="form" size="small" label-width="80px">
|
||||
<el-form-item label="文件名">
|
||||
<el-input v-model="form.name" style="width: 370px;" />
|
||||
@@ -52,7 +67,13 @@
|
||||
</div>
|
||||
</el-dialog>
|
||||
<!--表格渲染-->
|
||||
<el-table ref="table" v-loading="crud.loading" :data="crud.data" style="width: 100%;" @selection-change="crud.selectionChangeHandler">
|
||||
<el-table
|
||||
ref="table"
|
||||
v-loading="crud.loading"
|
||||
:data="crud.data"
|
||||
style="width: 100%;"
|
||||
@selection-change="crud.selectionChangeHandler"
|
||||
>
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column prop="name" label="文件名">
|
||||
<template slot-scope="scope">
|
||||
@@ -105,7 +126,7 @@
|
||||
import { mapGetters } from 'vuex'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import crudFile from '@/api/system/localStorage'
|
||||
import CRUD, { presenter, header, form, crud } from '@crud/crud'
|
||||
import CRUD, { crud, form, header, presenter } from '@crud/crud'
|
||||
import rrOperation from '@crud/RR.operation'
|
||||
import crudOperation from '@crud/CRUD.operation'
|
||||
import pagination from '@crud/Pagination'
|
||||
@@ -175,10 +196,11 @@ export default {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
::v-deep .el-image__error, .el-image__placeholder{
|
||||
background: none;
|
||||
}
|
||||
::v-deep .el-image-viewer__wrapper{
|
||||
top: 55px;
|
||||
}
|
||||
::v-deep .el-image__error, .el-image__placeholder {
|
||||
background: none;
|
||||
}
|
||||
|
||||
::v-deep .el-image-viewer__wrapper {
|
||||
top: 55px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
import { mapGetters } from 'vuex'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import crudFile from '@/api/system/ossStorage'
|
||||
import CRUD, { presenter, header, form, crud } from '@crud/crud'
|
||||
import CRUD, { crud, form, header, presenter } from '@crud/crud'
|
||||
import rrOperation from '@crud/RR.operation'
|
||||
import crudOperation from '@crud/CRUD.operation'
|
||||
import pagination from '@crud/Pagination'
|
||||
|
||||
@@ -9,7 +9,12 @@
|
||||
<div>
|
||||
<div style="text-align: center">
|
||||
<div class="el-upload">
|
||||
<img :src="user.avatarName ? baseApi + '/avatar/' + user.avatarName : Avatar" title="点击上传头像" class="avatar" @click="toggleShow">
|
||||
<img
|
||||
:src="user.avatarName ? baseApi + '/avatar/' + user.avatarName : Avatar"
|
||||
title="点击上传头像"
|
||||
class="avatar"
|
||||
@click="toggleShow"
|
||||
>
|
||||
<myUpload
|
||||
v-model="show"
|
||||
:headers="headers"
|
||||
@@ -19,13 +24,36 @@
|
||||
</div>
|
||||
</div>
|
||||
<ul class="user-info">
|
||||
<li><div style="height: 100%"><svg-icon icon-class="login" /> 登录账号<div class="user-right">{{ user.username }}</div></div></li>
|
||||
<li><svg-icon icon-class="user1" /> 用户昵称 <div class="user-right">{{ user.nickName }}</div></li>
|
||||
<li><svg-icon icon-class="dept" /> 所属部门 <div class="user-right"> {{ user.dept.name }}</div></li>
|
||||
<li><svg-icon icon-class="phone" /> 手机号码 <div class="user-right">{{ user.phone }}</div></li>
|
||||
<li><svg-icon icon-class="email" /> 用户邮箱 <div class="user-right">{{ user.email }}</div></li>
|
||||
<li>
|
||||
<svg-icon icon-class="anq" /> 安全设置
|
||||
<div style="height: 100%">
|
||||
<svg-icon icon-class="login" />
|
||||
登录账号
|
||||
<div class="user-right">{{ user.username }}</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<svg-icon icon-class="user1" />
|
||||
用户昵称
|
||||
<div class="user-right">{{ user.nickName }}</div>
|
||||
</li>
|
||||
<li>
|
||||
<svg-icon icon-class="dept" />
|
||||
所属部门
|
||||
<div class="user-right"> {{ user.dept.name }}</div>
|
||||
</li>
|
||||
<li>
|
||||
<svg-icon icon-class="phone" />
|
||||
手机号码
|
||||
<div class="user-right">{{ user.phone }}</div>
|
||||
</li>
|
||||
<li>
|
||||
<svg-icon icon-class="email" />
|
||||
用户邮箱
|
||||
<div class="user-right">{{ user.email }}</div>
|
||||
</li>
|
||||
<li>
|
||||
<svg-icon icon-class="anq" />
|
||||
安全设置
|
||||
<div class="user-right">
|
||||
<a @click="$refs.pass.dialog = true">修改密码</a>
|
||||
<a @click="$refs.email.dialog = true">修改邮箱</a>
|
||||
@@ -40,7 +68,14 @@
|
||||
<el-card class="box-card">
|
||||
<el-tabs v-model="activeName" @tab-click="handleClick">
|
||||
<el-tab-pane label="用户资料" name="first">
|
||||
<el-form ref="form" :model="form" :rules="rules" style="margin-top: 10px;" size="small" label-width="65px">
|
||||
<el-form
|
||||
ref="form"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
style="margin-top: 10px;"
|
||||
size="small"
|
||||
label-width="65px"
|
||||
>
|
||||
<el-form-item label="昵称" prop="nickName">
|
||||
<el-input v-model="form.nickName" style="width: 35%" />
|
||||
<span style="color: #C0C0C0;margin-left: 10px;">用户昵称不作为登录使用</span>
|
||||
@@ -78,7 +113,10 @@
|
||||
align="right"
|
||||
>
|
||||
<template slot="header">
|
||||
<div style="display:inline-block;float: right;cursor: pointer" @click="init">创建日期<i class="el-icon-refresh" style="margin-left: 40px" /></div>
|
||||
<div style="display:inline-block;float: right;cursor: pointer" @click="init">创建日期<i
|
||||
class="el-icon-refresh"
|
||||
style="margin-left: 40px"
|
||||
/></div>
|
||||
</template>
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.createTime }}</span>
|
||||
@@ -111,10 +149,11 @@ import updatePass from './center/updatePass'
|
||||
import updateEmail from './center/updateEmail'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import store from '@/store'
|
||||
import { isvalidPhone } from '@/utils/validate'
|
||||
import { isvalidPhone } from '@/utils/CsValidateUtil'
|
||||
import crud from '@/mixins/crud'
|
||||
import { editUser } from '@/api/system/user'
|
||||
import Avatar from '@/assets/images/avatar.png'
|
||||
|
||||
export default {
|
||||
name: 'Center',
|
||||
components: { updatePass, updateEmail, myUpload },
|
||||
@@ -159,7 +198,8 @@ export default {
|
||||
},
|
||||
created() {
|
||||
this.form = { id: this.user.id, nickName: this.user.nickName, gender: this.user.gender, phone: this.user.phone }
|
||||
store.dispatch('GetInfo').then(() => {})
|
||||
store.dispatch('GetInfo').then(() => {
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
toggleShow() {
|
||||
@@ -175,7 +215,8 @@ export default {
|
||||
return true
|
||||
},
|
||||
cropUploadSuccess(jsonData, field) {
|
||||
store.dispatch('GetInfo').then(() => {})
|
||||
store.dispatch('GetInfo').then(() => {
|
||||
})
|
||||
},
|
||||
doSubmit() {
|
||||
if (this.$refs['form']) {
|
||||
@@ -184,7 +225,8 @@ export default {
|
||||
this.saveLoading = true
|
||||
editUser(this.form).then(() => {
|
||||
this.editSuccessNotify()
|
||||
store.dispatch('GetInfo').then(() => {})
|
||||
store.dispatch('GetInfo').then(() => {
|
||||
})
|
||||
this.saveLoading = false
|
||||
}).catch(() => {
|
||||
this.saveLoading = false
|
||||
@@ -198,24 +240,28 @@ export default {
|
||||
</script>
|
||||
|
||||
<style rel="stylesheet/scss" lang="scss">
|
||||
.avatar {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
border-radius: 50%;
|
||||
.avatar {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
padding-left: 0;
|
||||
list-style: none;
|
||||
|
||||
li {
|
||||
border-bottom: 1px solid #F0F3F4;
|
||||
padding: 11px 0;
|
||||
font-size: 13px;
|
||||
}
|
||||
.user-info {
|
||||
padding-left: 0;
|
||||
list-style: none;
|
||||
li{
|
||||
border-bottom: 1px solid #F0F3F4;
|
||||
padding: 11px 0;
|
||||
font-size: 13px;
|
||||
}
|
||||
.user-right {
|
||||
float: right;
|
||||
a{
|
||||
color: #317EF3;
|
||||
}
|
||||
|
||||
.user-right {
|
||||
float: right;
|
||||
|
||||
a {
|
||||
color: #317EF3;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user