39 changed files with 5087 additions and 165 deletions
-
BINsrc/assets/image/datav_bg2.png
-
39src/components/NoticeMsgBar/index.vue
-
40src/components/TopModules/index.vue
-
36src/router/index.js
-
6src/router/routes_datav_xm.js
-
30src/router/routes_my_work.js
-
1src/router/routes_workflow.js
-
2src/styles/variables.scss
-
3src/views/dashboard/admin/index.vue
-
29src/views/datav/xm/FullScreenLayout.vue
-
2src/views/datav/xm/branch/index.vue
-
275src/views/datav/xm/branch1/cards.vue
-
215src/views/datav/xm/branch1/digitalFlop.vue
-
104src/views/datav/xm/branch1/index.less
-
463src/views/datav/xm/branch1/index.vue
-
108src/views/datav/xm/branch1/rankingBoard.vue
-
176src/views/datav/xm/branch1/roseChart.vue
-
66src/views/datav/xm/branch1/scrollBoard.vue
-
46src/views/datav/xm/branch1/topHeader.vue
-
109src/views/datav/xm/branch1/waterLevelChart.vue
-
65src/views/datav/xm/common/index.vue
-
490src/views/datav/xm/common/theme.json
-
31src/views/datav/xm/project/index.vue
-
269src/views/datav/xm/project1/cards.vue
-
214src/views/datav/xm/project1/digitalFlop.vue
-
103src/views/datav/xm/project1/index.less
-
466src/views/datav/xm/project1/index.vue
-
102src/views/datav/xm/project1/rankingBoard.vue
-
176src/views/datav/xm/project1/roseChart.vue
-
66src/views/datav/xm/project1/scrollBoard.vue
-
109src/views/datav/xm/project1/waterLevelChart.vue
-
59src/views/datav/xm/utils/drawMixin.js
-
51src/views/datav/xm/utils/index.js
-
2src/views/layout/components/AppMain.vue
-
151src/views/layout/components/Navbar.vue
-
5src/views/layout/components/Sidebar/Logo.vue
-
4src/views/layout/components/Sidebar/index.vue
-
2src/views/xm/XmOverview.vue
-
1137src/views/xm/XmOverview2.vue
|
After Width: 1920 | Height: 1080 | Size: 289 KiB |
@ -0,0 +1,30 @@ |
|||
/* Layout */ |
|||
import Layout from '../views/layout/Layout' |
|||
const _import = require('./_import_' + process.env.NODE_ENV) |
|||
|
|||
export default { |
|||
routes: [ |
|||
{ |
|||
path: '/my/work', |
|||
component: Layout, |
|||
name: '我的工作台', |
|||
meta: { |
|||
title: 'TaskCenter', |
|||
icon: 'task' |
|||
}, |
|||
iconCls: 'fa el-icon-menu', |
|||
// leaf: true,
|
|||
children: [ |
|||
{ |
|||
path: 'updateUserInfo', |
|||
component: _import('mdp/sys/user/UpdateUserInfo'), |
|||
name: '账户设置', |
|||
meta: { |
|||
title: '修改个人信息', |
|||
icon: 'component' |
|||
} |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
@ -0,0 +1,275 @@ |
|||
<template> |
|||
<div class="d_cards"> |
|||
<div |
|||
class="card-item" |
|||
v-for="(card, i) in myData" |
|||
:key="i" |
|||
> |
|||
<div class="card-header"> |
|||
<div class="card-header-left">{{ card.title }}</div> |
|||
<div class="card-header-right">{{ '0' + (i + 1) }}</div> |
|||
</div> |
|||
<dv-charts class="ring-charts" :option="card.ring" /> |
|||
<div class="card-footer"> |
|||
<div class="card-footer-item"> |
|||
<div class="footer-title">总工作量</div> |
|||
<div class="footer-detail"> |
|||
<dv-digital-flop :config="card.total" style="width:70%;height:35px;" />人月 |
|||
</div> |
|||
</div> |
|||
<div class="card-footer-item"> |
|||
<div class="footer-title">当前进度</div> |
|||
<div class="footer-detail"> |
|||
<dv-digital-flop :config="card.num" style="width:70%;height:35px;" />% |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: 'Cards', |
|||
props:['data'], |
|||
computed:{ |
|||
myData(){ |
|||
if(this.data && this.data.length>0){ |
|||
var cards= this.data.map(i=>{ |
|||
var card=JSON.parse(JSON.stringify(this.cardConfig)) |
|||
card.title=i.productName |
|||
card.total.number=[i.planWorkload/8/20];//累计工作量 人月 |
|||
card.num.number=[i.finishRate];//当前进度 |
|||
//资金占比 |
|||
card.ring.series[0].data[0].value=(i.planWorkload/i.totalPlanWorkload) //工作量占比 |
|||
return card |
|||
}); |
|||
if(cards.length<5){ |
|||
var count=5-cards.length |
|||
for(var i=0;i<count;i++){ |
|||
cards.push(this.cards[i]); |
|||
} |
|||
} |
|||
return cards; |
|||
}else{ |
|||
return this.cards; |
|||
} |
|||
} |
|||
}, |
|||
data () { |
|||
return { |
|||
cards: [], |
|||
cardConfig:{ |
|||
title: '', |
|||
total: { |
|||
number: [10], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#ea6027', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
num: { |
|||
number: [20], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#26fcd8', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
ring: { |
|||
series: [ |
|||
{ |
|||
type: 'gauge', |
|||
startAngle: -Math.PI / 2, |
|||
endAngle: Math.PI * 1.5, |
|||
arcLineWidth: 13, |
|||
radius: '80%', |
|||
data: [ |
|||
{ name: '工作量占比', value: 22 } |
|||
], |
|||
axisLabel: { |
|||
show: false |
|||
}, |
|||
axisTick: { |
|||
show: false |
|||
}, |
|||
pointer: { |
|||
show: false |
|||
}, |
|||
backgroundArc: { |
|||
style: { |
|||
stroke: '#224590' |
|||
} |
|||
}, |
|||
details: { |
|||
show: true, |
|||
formatter: '工作量占比{value}%', |
|||
style: { |
|||
fill: '#1ed3e5', |
|||
fontSize: 20 |
|||
} |
|||
} |
|||
} |
|||
], |
|||
color: ['#03d3ec'] |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
methods: { |
|||
createData () { |
|||
const { randomExtend } = this |
|||
const productNames=['商城','营销','项目管理工具','支付','智慧党建'] |
|||
this.cards = new Array(5).fill(0).map((foo, i) => ({ |
|||
title: productNames[i], |
|||
total: { |
|||
number: [randomExtend(90, 100)], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#ea6027', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
num: { |
|||
number: [randomExtend(30, 60)], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#26fcd8', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
ring: { |
|||
series: [ |
|||
{ |
|||
type: 'gauge', |
|||
startAngle: -Math.PI / 2, |
|||
endAngle: Math.PI * 1.5, |
|||
arcLineWidth: 13, |
|||
radius: '80%', |
|||
data: [ |
|||
{ name: '资金占比', value: randomExtend(40, 60) } |
|||
], |
|||
axisLabel: { |
|||
show: false |
|||
}, |
|||
axisTick: { |
|||
show: false |
|||
}, |
|||
pointer: { |
|||
show: false |
|||
}, |
|||
backgroundArc: { |
|||
style: { |
|||
stroke: '#224590' |
|||
} |
|||
}, |
|||
details: { |
|||
show: true, |
|||
formatter: '资金占比{value}%', |
|||
style: { |
|||
fill: '#1ed3e5', |
|||
fontSize: 20 |
|||
} |
|||
} |
|||
} |
|||
], |
|||
color: ['#03d3ec'] |
|||
} |
|||
})) |
|||
}, |
|||
randomExtend (minNum, maxNum) { |
|||
if (arguments.length === 1) { |
|||
return parseInt(Math.random() * minNum + 1, 10) |
|||
} else { |
|||
return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10) |
|||
} |
|||
} |
|||
}, |
|||
|
|||
mounted () { |
|||
const { createData } = this |
|||
createData() |
|||
setInterval(this.createData, 300) |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="less"> |
|||
.d_cards { |
|||
display: flex; |
|||
width: 100%; |
|||
justify-content: space-between; |
|||
height: 100%; |
|||
margin-left: 15px; |
|||
margin-top: 10px; |
|||
|
|||
.card-item { |
|||
background-color: rgba(6, 30, 93, 0.5); |
|||
border-top: 2px solid rgba(1, 153, 209, .5); |
|||
width: 19%; |
|||
display: flex; |
|||
flex-direction: column; |
|||
justify-content: space-around; |
|||
} |
|||
|
|||
.card-header { |
|||
display: flex; |
|||
height: 20%; |
|||
align-items: center; |
|||
justify-content: space-between; |
|||
|
|||
.card-header-left { |
|||
font-size: 18px; |
|||
font-weight: bold; |
|||
padding-left: 20px; |
|||
} |
|||
|
|||
.card-header-right { |
|||
padding-right: 20px; |
|||
font-size: 40px; |
|||
color: #03d3ec; |
|||
} |
|||
} |
|||
|
|||
.ring-charts { |
|||
height: 55%; |
|||
} |
|||
|
|||
.card-footer { |
|||
height: 25%; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: space-around; |
|||
} |
|||
|
|||
.card-footer-item { |
|||
padding: 5px 10px 0px 10px; |
|||
box-sizing: border-box; |
|||
width: 40%; |
|||
background-color: rgba(6, 30, 93, 0.7); |
|||
border-radius: 3px; |
|||
|
|||
.footer-title { |
|||
font-size: 15px; |
|||
margin-bottom: 5px; |
|||
} |
|||
|
|||
.footer-detail { |
|||
font-size: 20px; |
|||
color: #1294fb; |
|||
display: flex; |
|||
font-size: 18px; |
|||
align-items: center; |
|||
|
|||
.dv-digital-flop { |
|||
margin-right: 5px; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,215 @@ |
|||
<template> |
|||
<div class="flop"> |
|||
<div |
|||
class="digital-flop-item" |
|||
v-for="item in myData" |
|||
:key="item.title" |
|||
> |
|||
<p class="digital-flop-title">{{ item.title }}</p> |
|||
<div class="digital-flop"> |
|||
<dv-digital-flop |
|||
:config="item.number" |
|||
style="width:100px; height:50px;" |
|||
/> |
|||
<span class="unit">{{ item.unit }}</span> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: 'DigitalFlop', |
|||
data () { |
|||
return { |
|||
defaultDigitalFlopData: [] |
|||
} |
|||
}, |
|||
computed:{ |
|||
myData(){ |
|||
if(this.data){ |
|||
return this.data |
|||
}else{ |
|||
return this.defaultDigitalFlopData |
|||
} |
|||
} |
|||
}, |
|||
props:['data'], |
|||
methods: { |
|||
createData () { |
|||
const { randomExtend } = this |
|||
|
|||
this.defaultDigitalFlopData = [ |
|||
{ |
|||
title: '累计金额', |
|||
number: { |
|||
number: [randomExtend(5000000, 10000000000000)], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#40faee', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '元' |
|||
}, |
|||
{ |
|||
title: '发布总任务数', |
|||
number: { |
|||
number: [randomExtend(20000, 30000)], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#4d99fc', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '个' |
|||
}, |
|||
{ |
|||
title: '项目', |
|||
number: { |
|||
number: [randomExtend(200, 300)], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#f46827', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '个' |
|||
}, |
|||
{ |
|||
title: '参与人数', |
|||
number: { |
|||
number: [randomExtend(2000, 3000)], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#40faee', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '个' |
|||
}, |
|||
{ |
|||
title: '客户', |
|||
number: { |
|||
number: [randomExtend(100, 200)], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#4d99fc', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '个' |
|||
}, |
|||
{ |
|||
title: '需求', |
|||
number: { |
|||
number: [randomExtend(5000, 100000)], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#f46827', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '个' |
|||
}, |
|||
{ |
|||
title: '产品', |
|||
number: { |
|||
number: [randomExtend(50, 100)], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#40faee', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '个' |
|||
}, |
|||
{ |
|||
title: '测试用例', |
|||
number: { |
|||
number: [randomExtend(5000, 100000)], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#4d99fc', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '个' |
|||
}, |
|||
{ |
|||
title: '迭代', |
|||
number: { |
|||
number: [randomExtend(500, 10000)], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#f46827', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '个' |
|||
} |
|||
] |
|||
}, |
|||
randomExtend (minNum, maxNum) { |
|||
if (arguments.length === 1) { |
|||
return parseInt(Math.random() * minNum + 1, 10) |
|||
} else { |
|||
return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10) |
|||
} |
|||
} |
|||
}, |
|||
mounted () { |
|||
const { createData } = this |
|||
|
|||
createData() |
|||
|
|||
setInterval(createData, 30000) |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="less" scoped> |
|||
.flop { |
|||
width: 100%; |
|||
height: 120px; |
|||
display: flex; |
|||
justify-content: space-between; |
|||
background-color: rgba(13,20,39,0.5); |
|||
.digital-flop-item { |
|||
flex: 1; |
|||
display: flex; |
|||
flex-direction: column; |
|||
justify-content: center; |
|||
align-items: center; |
|||
border-left: 3px solid rgb(6, 30, 93); |
|||
border-right: 3px solid rgb(6, 30, 93); |
|||
} |
|||
|
|||
.digital-flop-title { |
|||
font-size: 24px; |
|||
margin:20px 20px 10px 20px; |
|||
} |
|||
|
|||
.digital-flop { |
|||
display: flex; |
|||
text-align: center; |
|||
} |
|||
|
|||
.unit { |
|||
margin-left: 10px; |
|||
display: flex; |
|||
align-items: flex-end; |
|||
box-sizing: border-box; |
|||
padding-bottom: 13px; |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,104 @@ |
|||
#data-branch { |
|||
color: #d3d6dd; |
|||
width: 1920px; |
|||
height: 1080px; |
|||
position: absolute; |
|||
top: 50%; |
|||
left: 50%; |
|||
transform: translate(-50%, -50%); |
|||
transform-origin: left top; |
|||
overflow: hidden; |
|||
.bg { |
|||
width: 100%; |
|||
height: 100%; |
|||
padding: 16px 16px 0 16px; |
|||
background-image: url("../../../../assets/image/datav_bg2.png"); |
|||
background-size: cover; |
|||
background-position: center center; |
|||
} |
|||
|
|||
.row_1 { |
|||
display: flex; |
|||
.dv-dec-10, |
|||
.dv-dec-10-s { |
|||
width: 33.3%; |
|||
height: 5px; |
|||
} |
|||
.dv-dec-10-s { |
|||
transform: rotateY(180deg); |
|||
} |
|||
.middle { |
|||
display: flex; |
|||
.dv-dec-8 { |
|||
width: 200px; |
|||
height: 30px; |
|||
} |
|||
.title { |
|||
position: relative; |
|||
width: 500px; |
|||
height: 40px; |
|||
text-align: center; |
|||
background-size: cover; |
|||
background-repeat: no-repeat; |
|||
line-height: 40px; |
|||
.title-text { |
|||
font-size: 36px; |
|||
position: absolute; |
|||
bottom: 0; |
|||
left: 50%; |
|||
width: 500px; |
|||
transform: translate(-50%); |
|||
} |
|||
.dv-dec-6 { |
|||
position: absolute; |
|||
bottom: -30px; |
|||
left: 50%; |
|||
width: 250px; |
|||
height: 8px; |
|||
transform: translate(-50%); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
.row_2 { |
|||
display: flex; |
|||
margin-top: 42px; |
|||
} |
|||
|
|||
.row_3 { |
|||
display: flex; |
|||
margin-top: 10px; |
|||
.left { |
|||
width: 300px; |
|||
height: 826px; |
|||
} |
|||
.right { |
|||
flex: 1; |
|||
height: 820px; |
|||
display: flex; |
|||
flex-direction: column; |
|||
.r_top { |
|||
display: flex; |
|||
flex: 1; |
|||
.top_1, .top_2, .top_3 { |
|||
height: 400px; |
|||
} |
|||
.top_1 { |
|||
width: 480px; |
|||
} |
|||
.top_2 { |
|||
width: 325px; |
|||
} |
|||
.top_3 { |
|||
width: 772px; |
|||
} |
|||
} |
|||
.r_bottom { |
|||
display: flex; |
|||
flex: 1; |
|||
} |
|||
} |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,463 @@ |
|||
<template> |
|||
<div id="data-branch" ref="appRef"> |
|||
<div class="bg"> |
|||
<dv-loading v-if="loading">加载中</dv-loading> |
|||
<div v-else class="host-body"> |
|||
<!-- 第一行 --> |
|||
<div class="row_1"> |
|||
<dv-decoration-10 class="dv-dec-10" /> |
|||
<div class="middle"> |
|||
<dv-decoration-8 class="dv-dec-8" :color="['#568aea', '#000000']" /> |
|||
<div class="title"> |
|||
<span class="title-text">唛盟项目管理综合数据监控</span> |
|||
<dv-decoration-6 class="dv-dec-6" :reverse="true" :color="['#50e3c2', '#67a1e5']"></dv-decoration-6> |
|||
</div> |
|||
<dv-decoration-8 class="dv-dec-8" :reverse="true" :color="['#568aea', '#000000']" /> |
|||
</div> |
|||
<dv-decoration-10 class="dv-dec-10-s" /> |
|||
</div> |
|||
|
|||
<!-- 第二行 --> |
|||
<div class="row_2"> |
|||
<digital-flop :data="digitalFlopData" :title="'汇总数据'"/> |
|||
</div> |
|||
|
|||
<!-- 第三行 --> |
|||
<div class="row_3"> |
|||
<div class="left"> |
|||
<ranking-board :data="rankingBoardData" :title="'项目进度'" /> |
|||
</div> |
|||
<div class="right"> |
|||
<div class="r_top"> |
|||
<div class="top_1"> |
|||
<rose-chart :data="roseChartData" :title="'资金分布'"/> |
|||
</div> |
|||
<div class="top_2"> |
|||
<water-level-chart :data="waterLevelChartData" :title="'计划资金累计完成情况'"/> |
|||
</div> |
|||
<div class="top_3"> |
|||
<scroll-board :data="scrollBoardData" :title="'动态'" :header="['时间','操作人','动作','备注']"/> |
|||
</div> |
|||
</div> |
|||
<div class="r_bottom"> |
|||
<cards :data="cardsData" :title="'产品'" /> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import Vue from 'vue' |
|||
import topHeader from './topHeader' |
|||
import digitalFlop from './digitalFlop' |
|||
import rankingBoard from './rankingBoard' |
|||
import roseChart from './roseChart' |
|||
import waterLevelChart from './waterLevelChart' |
|||
import scrollBoard from './scrollBoard' |
|||
import cards from './cards' |
|||
import dataV from '@jiaminghi/data-view' |
|||
Vue.use(dataV) |
|||
import { listOption } from '@/api/mdp/meta/itemOption';//下拉框数据查询 |
|||
import { listXmBranchState } from '@/api/xm/core/xmBranchState'; |
|||
import { listXmProjectState} from '@/api/xm/core/xmProjectState'; |
|||
import { listXmBranchTaskTypeState } from '@/api/xm/core/xmBranchTaskTypeState'; |
|||
import { listXmRecord } from '@/api/xm/core/xmRecord'; |
|||
import { listXmProductState } from '@/api/xm/core/xmProductState'; |
|||
import { mapGetters } from 'vuex' |
|||
import drawMixin from "../utils/drawMixin"; |
|||
|
|||
|
|||
export default { |
|||
name: 'BranchDataView', |
|||
mixins: [ drawMixin ], |
|||
components: { |
|||
topHeader, |
|||
digitalFlop, |
|||
rankingBoard, |
|||
roseChart, |
|||
waterLevelChart, |
|||
scrollBoard, |
|||
cards |
|||
}, |
|||
computed: { |
|||
...mapGetters([ |
|||
'userInfo' |
|||
]), |
|||
digitalFlopData(){ |
|||
if(!this.xmBranchState){ |
|||
return null; |
|||
} |
|||
var digitalFlopData = [ |
|||
{ |
|||
title: '累计金额', |
|||
number: { |
|||
number: [(this.floatValue(this.xmBranchState.totalBudgetNouserAmount) + this.floatValue(this.xmBranchState.totalBudgetIuserAmount) + this.floatValue(this.xmBranchState.totalBudgetOuserAmount))/10000], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#40faee', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '万元' |
|||
}, |
|||
{ |
|||
title: '发布总任务数', |
|||
number: { |
|||
number: [this.xmBranchState.totalTaskCnt ], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#4d99fc', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '个' |
|||
}, |
|||
{ |
|||
title: '项目', |
|||
number: { |
|||
number: [this.xmBranchState.projectCnt ], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#f46827', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '个' |
|||
}, |
|||
{ |
|||
title: '参与人数', |
|||
number: { |
|||
number: [this.xmBranchState.totalStaffCnt], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#40faee', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '人' |
|||
}, |
|||
{ |
|||
title: '客户', |
|||
number: { |
|||
number: [this.xmBranchState.productCnt], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#4d99fc', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '个' |
|||
}, |
|||
{ |
|||
title: '需求', |
|||
number: { |
|||
number: [this.xmBranchState.menuCnt], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#f46827', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '个' |
|||
}, |
|||
{ |
|||
title: '产品', |
|||
number: { |
|||
number: [this.xmBranchState.productCnt], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#40faee', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '个' |
|||
}, |
|||
{ |
|||
title: '测试用例', |
|||
number: { |
|||
number: [this.xmBranchState.testCases], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#4d99fc', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '个' |
|||
}, |
|||
{ |
|||
title: '迭代', |
|||
number: { |
|||
number: [this.xmBranchState.iterationCnt], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#f46827', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '个' |
|||
} |
|||
] |
|||
return digitalFlopData; |
|||
}, |
|||
rankingBoardData(){ |
|||
if( !this.xmProjectStates || this.xmProjectStates.length==0 ){ |
|||
return []; |
|||
} |
|||
var rankingBoardData=this.xmProjectStates.map(i=>{ |
|||
return {name:i.projectName,value:i.totalProgress+'%'} |
|||
}) |
|||
return rankingBoardData |
|||
}, |
|||
roseChartData(){ |
|||
var taskTypeList=this.options.taskType |
|||
if(this.xmBranchTaskTypeStates && this.xmBranchTaskTypeStates.length>0){ |
|||
var xmBranchTaskTypeStates=this.xmBranchTaskTypeStates.filter(i=>i.planAmount>0); |
|||
var roseChartData=xmBranchTaskTypeStates.map(i=>{ |
|||
|
|||
if(!taskTypeList || taskTypeList.length==0){ |
|||
return { |
|||
name:i.taskType?i.taskType:'其它', |
|||
value:i.planAmount?i.planAmount:0 |
|||
} |
|||
}else{ |
|||
var taskTypes=taskTypeList.filter(k=>k.optionValue==i.taskType) |
|||
if(taskTypes && taskTypes.length>0){ |
|||
var taskType=taskTypes[0] |
|||
return { |
|||
name:taskType.optionName, |
|||
value:i.planAmount?i.planAmount:0 |
|||
} |
|||
}else{ |
|||
return { |
|||
name:i.taskType?i.taskType:'其它', |
|||
value:i.planAmount?i.planAmount:0 |
|||
} |
|||
} |
|||
} |
|||
}) |
|||
return roseChartData |
|||
}else{ |
|||
return null; |
|||
} |
|||
|
|||
}, |
|||
waterLevelChartData(){ |
|||
if(this.xmBranchState){ |
|||
var data={} |
|||
var allAmount=this.floatValue(this.xmBranchState.totalBudgetNouserAmount) + this.floatValue(this.xmBranchState.totalBudgetIuserAmount) + this.floatValue(this.xmBranchState.totalBudgetOuserAmount); |
|||
data.finishNum= this.floatValue(this.xmBranchState.totalCostNouserAmount) + this.floatValue(this.xmBranchState.totalCostIuserAmount) +this.floatValue(this.xmBranchState.totalCostOuserAmount) |
|||
data.finishPercent= parseFloat(data.finishNum/allAmount * 100).toFixed(0) |
|||
return data; |
|||
}else{ |
|||
return null; |
|||
} |
|||
}, |
|||
scrollBoardData(){ |
|||
if(this.xmRecords && this.xmRecords.length>0){ |
|||
var data = this.xmRecords.map(i=>{ |
|||
return [i.operTime,i.operUsername,i.action,i.remarks] |
|||
}) |
|||
return data; |
|||
}else{ |
|||
return null; |
|||
} |
|||
}, |
|||
|
|||
cardsData(){ |
|||
if(this.xmProductStates && this.xmProductStates.length>0){ |
|||
var totalPlanWorkload=this.floatValue(this.xmBranchState.totalPlanWorkload) |
|||
this.xmProductStates.map(i=>{ |
|||
i.totalPlanWorkload=totalPlanWorkload |
|||
return i; |
|||
}) |
|||
return this.xmProductStates.slice(0, 5); |
|||
}else{ |
|||
return null; |
|||
} |
|||
} |
|||
}, |
|||
|
|||
data () { |
|||
return { |
|||
loading: true, |
|||
xmBranchState:null, |
|||
xmProjectStates:[], |
|||
xmBranchTaskTypeStates:[], |
|||
xmRecords:[], |
|||
xmProductStates:[], |
|||
options:{ |
|||
taskType:[], |
|||
}, |
|||
|
|||
xmRecordPageInfo:{//分页数据 |
|||
total:0,//服务器端收到0时,会自动计算总记录数,如果上传>0的不自动计算。 |
|||
pageSize:20,//每页数据 |
|||
count:false,//是否需要重新计算总记录数 |
|||
pageNum:1,//当前页码、从1开始计算 |
|||
orderFields:["oper_time"],//排序列 如 ['sex','student_id'],必须为数据库字段 |
|||
orderDirs:["desc"]//升序 asc,降序desc 如 性别 升序、学生编号降序 ['asc','desc'] |
|||
}, |
|||
|
|||
xmProjectStatePageInfo:{//分页数据 |
|||
total:0,//服务器端收到0时,会自动计算总记录数,如果上传>0的不自动计算。 |
|||
pageSize:20,//每页数据 |
|||
count:false,//是否需要重新计算总记录数 |
|||
pageNum:1,//当前页码、从1开始计算 |
|||
orderFields:["calc_time"],//排序列 如 ['sex','student_id'],必须为数据库字段 |
|||
orderDirs:["desc"]//升序 asc,降序desc 如 性别 升序、学生编号降序 ['asc','desc'] |
|||
}, |
|||
|
|||
|
|||
xmProductStatePageInfo:{//分页数据 |
|||
total:0,//服务器端收到0时,会自动计算总记录数,如果上传>0的不自动计算。 |
|||
pageSize:20,//每页数据 |
|||
count:false,//是否需要重新计算总记录数 |
|||
pageNum:1,//当前页码、从1开始计算 |
|||
orderFields:["calc_time"],//排序列 如 ['sex','student_id'],必须为数据库字段 |
|||
orderDirs:["desc"]//升序 asc,降序desc 如 性别 升序、学生编号降序 ['asc','desc'] |
|||
}, |
|||
} |
|||
}, |
|||
methods: { |
|||
getXmBranchState(){ |
|||
var params = { |
|||
branchId:this.userInfo.branchId |
|||
} |
|||
listXmBranchState(params).then(res=>{ |
|||
var tips = res.data.tips; |
|||
if(tips.isOk){ |
|||
if(res.data.data.length>0){ |
|||
this.xmBranchState=res.data.data[0] |
|||
} |
|||
setTimeout(() => { |
|||
this.loading = false; |
|||
}, 100); |
|||
} |
|||
}); |
|||
}, |
|||
getXmProjectStates(){ |
|||
let params = { |
|||
pageSize: this.xmProjectStatePageInfo.pageSize, |
|||
pageNum: this.xmProjectStatePageInfo.pageNum, |
|||
total: this.xmProjectStatePageInfo.total, |
|||
count:this.xmProjectStatePageInfo.count |
|||
}; |
|||
if(this.xmProjectStatePageInfo.orderFields!=null && this.xmProjectStatePageInfo.orderFields.length>0){ |
|||
let orderBys=[]; |
|||
for(var i=0;i<this.xmProjectStatePageInfo.orderFields.length;i++){ |
|||
orderBys.push(this.xmProjectStatePageInfo.orderFields[i]+" "+this.xmProjectStatePageInfo.orderDirs[i]) |
|||
} |
|||
params.orderBy= orderBys.join(",") |
|||
} |
|||
params.branchId=this.userInfo.branchId |
|||
listXmProjectState(params).then(res=>{ |
|||
var tips = res.data.tips; |
|||
if(tips.isOk){ |
|||
if(res.data.data.length>0){ |
|||
this.xmProjectStates=res.data.data |
|||
} |
|||
} |
|||
}); |
|||
}, |
|||
|
|||
getXmBranchTaskTypeStates(){ |
|||
var params = { |
|||
branchId:this.userInfo.branchId |
|||
} |
|||
listXmBranchTaskTypeState(params).then(res=>{ |
|||
var tips = res.data.tips; |
|||
if(tips.isOk){ |
|||
if(res.data.data.length>0){ |
|||
this.xmBranchTaskTypeStates=res.data.data |
|||
} |
|||
} |
|||
}); |
|||
},//获取列表 XmRecord xm_record |
|||
getXmRecords() { |
|||
let params = { |
|||
pageSize: this.xmRecordPageInfo.pageSize, |
|||
pageNum: this.xmRecordPageInfo.pageNum, |
|||
total: this.xmRecordPageInfo.total, |
|||
count:this.xmRecordPageInfo.count |
|||
}; |
|||
if(this.xmRecordPageInfo.orderFields!=null && this.xmRecordPageInfo.orderFields.length>0){ |
|||
let orderBys=[]; |
|||
for(var i=0;i<this.xmRecordPageInfo.orderFields.length;i++){ |
|||
orderBys.push(this.xmRecordPageInfo.orderFields[i]+" "+this.xmRecordPageInfo.orderDirs[i]) |
|||
} |
|||
params.orderBy= orderBys.join(",") |
|||
} |
|||
listXmRecord(params).then((res) => { |
|||
var tips=res.data.tips; |
|||
if(tips.isOk){ |
|||
this.xmRecordPageInfo.total = res.data.total; |
|||
this.xmRecordPageInfo.count=false; |
|||
this.xmRecords = res.data.data; |
|||
}else{ |
|||
} |
|||
}) ; |
|||
}, |
|||
//获取列表 XmProductState 功能状态表,无需前端维护,所有数据由汇总统计得出 |
|||
getXmProductStates() { |
|||
let params = { |
|||
pageSize: this.xmProductStatePageInfo.pageSize, |
|||
pageNum: this.xmProductStatePageInfo.pageNum, |
|||
total: this.xmProductStatePageInfo.total, |
|||
count:this.xmProductStatePageInfo.count |
|||
}; |
|||
if(this.xmProductStatePageInfo.orderFields!=null && this.xmProductStatePageInfo.orderFields.length>0){ |
|||
let orderBys=[]; |
|||
for(var i=0;i<this.xmProductStatePageInfo.orderFields.length;i++){ |
|||
orderBys.push(this.xmProductStatePageInfo.orderFields[i]+" "+this.xmProductStatePageInfo.orderDirs[i]) |
|||
} |
|||
params.orderBy= orderBys.join(",") |
|||
} |
|||
params.branchId=this.userInfo.branchId |
|||
listXmProductState(params).then((res) => { |
|||
var tips=res.data.tips; |
|||
if(tips.isOk){ |
|||
this.xmProductStatePageInfo.total = res.data.total; |
|||
this.xmProductStatePageInfo.count=false; |
|||
this.xmProductStates = res.data.data; |
|||
}else{ |
|||
} |
|||
}) ; |
|||
}, |
|||
floatValue(value){ |
|||
if(!value){ |
|||
return 0.0; |
|||
}else{ |
|||
return value |
|||
} |
|||
} |
|||
}, |
|||
mounted(){ |
|||
this.getXmBranchState(); |
|||
this.getXmProjectStates(); |
|||
this.getXmBranchTaskTypeStates(); |
|||
this.getXmRecords(); |
|||
this.getXmProductStates(); |
|||
listOption([{categoryId:'all',itemCode:'taskType'}] ).then(res=>{ |
|||
if(res.data.tips.isOk){ |
|||
this.options=res.data.data |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="less"> |
|||
@import './index.less'; |
|||
</style> |
|||
@ -0,0 +1,108 @@ |
|||
<template> |
|||
<div class="ranking-board"> |
|||
<span class="ranking-board-title">{{title}}</span> |
|||
<dv-scroll-ranking-board :config="config" style="height: 500px;" /> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: 'RankingBoard', |
|||
props:['data','title'], |
|||
computed:{ |
|||
config(){ |
|||
if( !this.data || this.data.length==0){ |
|||
return this.defaultConfig; |
|||
}else{ |
|||
var data=this.data; |
|||
if(data.length<5){ |
|||
const count = 5-data.length; |
|||
for(var i=0;i< count;i++){ |
|||
var defaultOne=JSON.parse(JSON.stringify(this.defaultConfig.data[i])) |
|||
data.push(defaultOne); |
|||
} |
|||
} |
|||
data.forEach(element => { |
|||
element.name = `<span style="font-size:16px;">${element.name}</span>` |
|||
}); |
|||
var config={ |
|||
data:data |
|||
} |
|||
return config |
|||
} |
|||
} |
|||
}, |
|||
data () { |
|||
return { |
|||
defaultConfig: { |
|||
data: [ |
|||
{ |
|||
name: '商城项目', |
|||
value: '30%' |
|||
}, |
|||
{ |
|||
name: '营销项目', |
|||
value: '40%' |
|||
}, |
|||
{ |
|||
name: '支付项目', |
|||
value: '50%' |
|||
}, |
|||
{ |
|||
name: '短信项目', |
|||
value: '60%' |
|||
}, |
|||
{ |
|||
name: '党建项目', |
|||
value: '50%' |
|||
}, |
|||
{ |
|||
name: '协同办公项目', |
|||
value: '90%' |
|||
}, |
|||
{ |
|||
name: '即聊项目', |
|||
value: '40%' |
|||
}, |
|||
{ |
|||
name: '审计项目', |
|||
value: '60%' |
|||
}, |
|||
{ |
|||
name: '溯源项目', |
|||
value: '90%' |
|||
} |
|||
], |
|||
rowNum: 9 |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="less" scoped> |
|||
.ranking-board { |
|||
width: 300px; |
|||
height: 100%; |
|||
box-shadow: 0 0 3px blue; |
|||
display: flex; |
|||
flex-direction: column; |
|||
background-color: rgba(10, 13, 28, 0.5); |
|||
border-top: 2px solid rgba(1, 153, 209, .5); |
|||
box-sizing: border-box; |
|||
padding: 0px 30px; |
|||
|
|||
.ranking-board-title { |
|||
font-weight: bold; |
|||
height: 50px; |
|||
display: flex; |
|||
align-items: center; |
|||
font-size: 20px; |
|||
font-weight: 700; |
|||
} |
|||
|
|||
.dv-scroll-ranking-board { |
|||
flex: 1; |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,176 @@ |
|||
<template> |
|||
<div class="rose-chart"> |
|||
<div class="rose-chart-title">{{title}}</div> |
|||
<Echart |
|||
:options="option" |
|||
id="dv_roseChart" |
|||
height="340px" |
|||
width="100%" |
|||
></Echart> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import Echart from '../common' |
|||
export default { |
|||
name: 'RoseChart', |
|||
props:['data','title'], |
|||
components: {Echart}, |
|||
computed:{ |
|||
option(){ |
|||
if( !this.data || this.data.length==0){ |
|||
return this.defaultOption; |
|||
}else{ |
|||
this.createData() |
|||
let tempData = this.data.slice(0, 5); |
|||
let obj = {name: '其它', value : 0}; |
|||
let v = 0; |
|||
this.data.forEach((element,index) => { |
|||
if(index > 5) { |
|||
v += element.value; |
|||
} |
|||
}); |
|||
obj.value = v; |
|||
if(obj.value > 0) { |
|||
tempData.push(obj); |
|||
} |
|||
var option = JSON.parse(JSON.stringify(this.options)) |
|||
option.series[0].data = tempData |
|||
option.legend.data = tempData |
|||
return option |
|||
} |
|||
} |
|||
}, |
|||
data () { |
|||
return { |
|||
defaultOption: {}, |
|||
options : { |
|||
color: [ |
|||
"#37a2da", |
|||
"#32c5e9", |
|||
"#9fe6b8", |
|||
"#ffdb5c", |
|||
"#ff9f7f", |
|||
"#fb7293", |
|||
"#e7bcf3" |
|||
], |
|||
tooltip: { |
|||
trigger: "item", |
|||
formatter: "{b} : {c} ({d}%)" |
|||
}, |
|||
legend: { |
|||
orient: "horizontal", |
|||
icon: "circle", |
|||
bottom: 0, |
|||
x: "center", |
|||
data: |
|||
[ |
|||
{ value: 40, name: 'rose 1' }, |
|||
{ value: 38, name: 'rose 2' }, |
|||
{ value: 32, name: 'rose 3' }, |
|||
{ value: 30, name: 'rose 4' }, |
|||
{ value: 28, name: 'rose 5' }, |
|||
], |
|||
textStyle: { |
|||
color: "#fff", |
|||
fontSize: 18 |
|||
} |
|||
}, |
|||
calculable: true, |
|||
series: [ |
|||
{ |
|||
type: 'pie', |
|||
radius: [35, 80], |
|||
center: ['50%', '45%'], |
|||
roseType: 'area', |
|||
data: [ |
|||
{ value: 40, name: 'rose 1' }, |
|||
{ value: 38, name: 'rose 2' }, |
|||
{ value: 32, name: 'rose 3' }, |
|||
{ value: 30, name: 'rose 4' }, |
|||
{ value: 28, name: 'rose 5' }, |
|||
] |
|||
} |
|||
] |
|||
} |
|||
} |
|||
}, |
|||
methods: { |
|||
createData () { |
|||
const { randomExtend } = this |
|||
|
|||
this.defaultOption = { |
|||
series: [ |
|||
{ |
|||
type: 'pie', |
|||
radius: '50%', |
|||
roseSort: false, |
|||
data: [ |
|||
{ name: '需求', value: randomExtend(40, 70) }, |
|||
{ name: '开发', value: randomExtend(20, 30) }, |
|||
{ name: '测试', value: randomExtend(10, 50) }, |
|||
{ name: '设计', value: randomExtend(5, 20) }, |
|||
{ name: '运营', value: randomExtend(40, 50) }, |
|||
{ name: '客服', value: randomExtend(20, 30) }, |
|||
{ name: '管理', value: randomExtend(5, 10) }, |
|||
{ name: '产品', value: randomExtend(20, 35) }, |
|||
{ name: '运维', value: randomExtend(5, 10) } |
|||
], |
|||
insideLabel: { |
|||
show: false |
|||
}, |
|||
outsideLabel: { |
|||
formatter: '{name} {percent}%', |
|||
labelLineEndLength: 20, |
|||
style: { |
|||
fill: '#fff' |
|||
}, |
|||
labelLineStyle: { |
|||
stroke: '#fff' |
|||
} |
|||
}, |
|||
roseType: true |
|||
} |
|||
], |
|||
color: ['#da2f00', '#fa3600', '#ff4411', '#ff724c', '#541200', '#801b00', '#a02200', '#5d1400', '#b72700'] |
|||
} |
|||
}, |
|||
randomExtend (minNum, maxNum) { |
|||
if (arguments.length === 1) { |
|||
return parseInt(Math.random() * minNum + 1, 10) |
|||
} else { |
|||
return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10) |
|||
} |
|||
} |
|||
}, |
|||
mounted () { |
|||
const { createData } = this |
|||
createData() |
|||
setInterval(createData, 30000) |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="less"> |
|||
.rose-chart { |
|||
width: 450px; |
|||
height: 400px; |
|||
margin: 0 0px 0 15px; |
|||
background-color: rgba(6, 30, 93, 0.5); |
|||
border-top: 2px solid rgba(1, 153, 209, .5); |
|||
box-sizing: border-box; |
|||
.rose-chart-title { |
|||
height: 50px; |
|||
font-weight: bold; |
|||
text-indent: 20px; |
|||
font-size: 20px; |
|||
display: flex; |
|||
align-items: center; |
|||
} |
|||
|
|||
.dv-charts-container { |
|||
height: calc(~"100% - 20px"); |
|||
} |
|||
} |
|||
</style> |
|||
|
|||
@ -0,0 +1,66 @@ |
|||
<template> |
|||
<div class="scroll-board"> |
|||
<dv-scroll-board :config="myConfig" /> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: 'ScrollBoard', |
|||
props:['data','header'], |
|||
computed:{ |
|||
myConfig(){ |
|||
if(this.data && this.data.length>0){ |
|||
var config=JSON.parse(JSON.stringify(this.config)); |
|||
this.data.forEach(d => { |
|||
d.forEach((text, index) => { |
|||
d[index] = `<span style="font-size:16px;">${text}</span>`; |
|||
}); |
|||
}); |
|||
config.header=this.header |
|||
config.data=this.data |
|||
return config; |
|||
}else{ |
|||
return this.config |
|||
} |
|||
} |
|||
}, |
|||
data () { |
|||
return { |
|||
config: { |
|||
header: ['时间', '项目', '金额', '变动情况'], |
|||
data: [ |
|||
['2019-07-01 19:25:00', '唛萌项目管理工具', '500万元', '立项'], |
|||
['2019-07-02 17:25:00', '唛盟商城项目', '300万元', '通过验收'], |
|||
['2019-07-03 16:25:00', '唛萌营销项目', '200万元', '测试完成'], |
|||
['2019-07-04 15:25:00', '组织管理系统项目', '100万', '竞标中'], |
|||
['2019-07-05 14:25:00', '支付管理系统', '700万元', '完成第一里程碑'], |
|||
['2019-07-06 13:25:00', '溯源系统', '300万元', '系统对接完成'], |
|||
['2019-07-07 12:25:00', '智能办公系统', '400万元', '试运行中'], |
|||
['2019-07-08 11:25:00', '数据可视化系统', '600万元', '开发中'], |
|||
['2019-07-09 10:25:00', '党建系统', '500万元', '上线成功'], |
|||
['2019-07-10 09:25:00', '智慧社区系统', '300万元', '运营中'] |
|||
], |
|||
index: true, |
|||
columnWidth: [50, 150, 100,200,200], |
|||
align: ['center'], |
|||
rowNum: 7, |
|||
headerBGC: '#1981f6', |
|||
headerHeight: 45, |
|||
oddRowBGC: 'rgba(0, 44, 81, 0.8)', |
|||
evenRowBGC: 'rgba(10, 29, 50, 0.8)' |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="less"> |
|||
.scroll-board { |
|||
width: 100%; |
|||
box-sizing: border-box; |
|||
margin-left: 10px; |
|||
height: 100%; |
|||
overflow: hidden; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,46 @@ |
|||
<template> |
|||
<div id="top-header"> |
|||
<dv-decoration-8 class="header-left-decoration" /> |
|||
<dv-decoration-5 class="header-center-decoration" /> |
|||
<dv-decoration-8 class="header-right-decoration" :reverse="true" /> |
|||
<div class="center-title">{{title}}</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: 'TopHeader', |
|||
props:['title'], |
|||
} |
|||
</script> |
|||
|
|||
<style lang="less"> |
|||
#top-header { |
|||
position: relative; |
|||
width: 100%; |
|||
height: 100px; |
|||
display: flex; |
|||
justify-content: space-between; |
|||
flex-shrink: 0; |
|||
|
|||
.header-center-decoration { |
|||
width: 40%; |
|||
height: 60px; |
|||
margin-top: 30px; |
|||
} |
|||
|
|||
.header-left-decoration, .header-right-decoration { |
|||
width: 25%; |
|||
height: 60px; |
|||
} |
|||
|
|||
.center-title { |
|||
position: absolute; |
|||
font-size: 30px; |
|||
font-weight: bold; |
|||
left: 50%; |
|||
top: 15px; |
|||
transform: translateX(-50%); |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,109 @@ |
|||
<template> |
|||
<div class="water-level-chart"> |
|||
<div class="water-level-chart-title">{{title}}</div> |
|||
|
|||
<div class="water-level-chart-details"> |
|||
累计完成<span>{{myData.finishNum}}</span>元 |
|||
</div> |
|||
|
|||
<div class="chart-container"> |
|||
<dv-water-level-pond :config="myData.config" /> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: 'WaterLevelChart', |
|||
props:['data','title'], |
|||
computed:{ |
|||
myData(){ |
|||
if(this.data){ |
|||
|
|||
var config=JSON.parse(JSON.stringify( this.config)) |
|||
config.data=[this.data.finishPercent] |
|||
return { |
|||
finishNum:this.data.finishNum, |
|||
config:config |
|||
} |
|||
} else{ |
|||
return { |
|||
finishNum:12350, |
|||
config:this.config |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
data () { |
|||
return { |
|||
config: { |
|||
data: [45], |
|||
shape: 'round', |
|||
waveHeight: 25, |
|||
waveNum: 2 |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="less"> |
|||
.water-level-chart { |
|||
width: 100%; |
|||
height: 100%; |
|||
box-sizing: border-box; |
|||
margin-right: 20px; |
|||
background-color: rgba(6, 30, 93, 0.5); |
|||
border-top: 2px solid rgba(1, 153, 209, .5); |
|||
display: flex; |
|||
flex-direction: column; |
|||
|
|||
.water-level-chart-title { |
|||
font-weight: bold; |
|||
height: 50px; |
|||
display: flex; |
|||
align-items: center; |
|||
font-size: 20px; |
|||
justify-content: center; |
|||
} |
|||
|
|||
.water-level-chart-details { |
|||
height: 15%; |
|||
display: flex; |
|||
justify-content: center; |
|||
font-size: 17px; |
|||
align-items: flex-end; |
|||
|
|||
span { |
|||
font-size: 35px; |
|||
font-weight: bold; |
|||
color: #58a1ff; |
|||
margin: 0 5px; |
|||
margin-bottom: -5px; |
|||
} |
|||
} |
|||
|
|||
.chart-container { |
|||
flex: 1; |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
} |
|||
|
|||
.dv-water-pond-level { |
|||
max-width: 90%; |
|||
width: 200px; |
|||
height: 200px; |
|||
border: 10px solid #19c3eb; |
|||
border-radius: 50%; |
|||
|
|||
ellipse { |
|||
stroke: transparent !important; |
|||
} |
|||
|
|||
text { |
|||
font-size: 40px; |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,65 @@ |
|||
<template> |
|||
<div :id="id" :class="className" :style="{ height: height, width: width }" /> |
|||
</template> |
|||
|
|||
<script> |
|||
import tdTheme from './theme.json' // 引入默认主题 |
|||
|
|||
export default { |
|||
name: 'echart', |
|||
props: { |
|||
className: { |
|||
type: String, |
|||
default: 'chart' |
|||
}, |
|||
id: { |
|||
type: String, |
|||
default: 'chart' |
|||
}, |
|||
width: { |
|||
type: String, |
|||
default: '100%' |
|||
}, |
|||
height: { |
|||
type: String, |
|||
default: '2.5rem' |
|||
}, |
|||
options: { |
|||
type: Object, |
|||
default: ()=>({}) |
|||
} |
|||
}, |
|||
data () { |
|||
return { |
|||
chart: null |
|||
} |
|||
}, |
|||
watch: { |
|||
options: { |
|||
handler (options) { |
|||
// 设置true清空echart缓存 |
|||
this.chart.setOption(options, true) |
|||
}, |
|||
deep: true |
|||
} |
|||
}, |
|||
mounted () { |
|||
this.$echarts.registerTheme('tdTheme', tdTheme); // 覆盖默认主题 |
|||
this.initChart(); |
|||
}, |
|||
beforeDestroy () { |
|||
this.chart.dispose() |
|||
this.chart = null |
|||
}, |
|||
methods: { |
|||
initChart () { |
|||
// 初始化echart |
|||
this.chart = this.$echarts.init(this.$el, 'tdTheme') |
|||
this.chart.setOption(this.options, true) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style> |
|||
</style> |
|||
@ -0,0 +1,490 @@ |
|||
{ |
|||
"color": [ |
|||
"#2d8cf0", |
|||
"#19be6b", |
|||
"#ff9900", |
|||
"#E46CBB", |
|||
"#9A66E4", |
|||
"#ed3f14" |
|||
], |
|||
"backgroundColor": "rgba(0,0,0,0)", |
|||
"textStyle": {}, |
|||
"title": { |
|||
"textStyle": { |
|||
"color": "#516b91" |
|||
}, |
|||
"subtextStyle": { |
|||
"color": "#93b7e3" |
|||
} |
|||
}, |
|||
"line": { |
|||
"itemStyle": { |
|||
"normal": { |
|||
"borderWidth": "2" |
|||
} |
|||
}, |
|||
"lineStyle": { |
|||
"normal": { |
|||
"width": "2" |
|||
} |
|||
}, |
|||
"symbolSize": "6", |
|||
"symbol": "emptyCircle", |
|||
"smooth": true |
|||
}, |
|||
"radar": { |
|||
"itemStyle": { |
|||
"normal": { |
|||
"borderWidth": "2" |
|||
} |
|||
}, |
|||
"lineStyle": { |
|||
"normal": { |
|||
"width": "2" |
|||
} |
|||
}, |
|||
"symbolSize": "6", |
|||
"symbol": "emptyCircle", |
|||
"smooth": true |
|||
}, |
|||
"bar": { |
|||
"itemStyle": { |
|||
"normal": { |
|||
"barBorderWidth": 0, |
|||
"barBorderColor": "#ccc" |
|||
}, |
|||
"emphasis": { |
|||
"barBorderWidth": 0, |
|||
"barBorderColor": "#ccc" |
|||
} |
|||
} |
|||
}, |
|||
"pie": { |
|||
"itemStyle": { |
|||
"normal": { |
|||
"borderWidth": 0, |
|||
"borderColor": "#ccc" |
|||
}, |
|||
"emphasis": { |
|||
"borderWidth": 0, |
|||
"borderColor": "#ccc" |
|||
} |
|||
} |
|||
}, |
|||
"scatter": { |
|||
"itemStyle": { |
|||
"normal": { |
|||
"borderWidth": 0, |
|||
"borderColor": "#ccc" |
|||
}, |
|||
"emphasis": { |
|||
"borderWidth": 0, |
|||
"borderColor": "#ccc" |
|||
} |
|||
} |
|||
}, |
|||
"boxplot": { |
|||
"itemStyle": { |
|||
"normal": { |
|||
"borderWidth": 0, |
|||
"borderColor": "#ccc" |
|||
}, |
|||
"emphasis": { |
|||
"borderWidth": 0, |
|||
"borderColor": "#ccc" |
|||
} |
|||
} |
|||
}, |
|||
"parallel": { |
|||
"itemStyle": { |
|||
"normal": { |
|||
"borderWidth": 0, |
|||
"borderColor": "#ccc" |
|||
}, |
|||
"emphasis": { |
|||
"borderWidth": 0, |
|||
"borderColor": "#ccc" |
|||
} |
|||
} |
|||
}, |
|||
"sankey": { |
|||
"itemStyle": { |
|||
"normal": { |
|||
"borderWidth": 0, |
|||
"borderColor": "#ccc" |
|||
}, |
|||
"emphasis": { |
|||
"borderWidth": 0, |
|||
"borderColor": "#ccc" |
|||
} |
|||
} |
|||
}, |
|||
"funnel": { |
|||
"itemStyle": { |
|||
"normal": { |
|||
"borderWidth": 0, |
|||
"borderColor": "#ccc" |
|||
}, |
|||
"emphasis": { |
|||
"borderWidth": 0, |
|||
"borderColor": "#ccc" |
|||
} |
|||
} |
|||
}, |
|||
"gauge": { |
|||
"itemStyle": { |
|||
"normal": { |
|||
"borderWidth": 0, |
|||
"borderColor": "#ccc" |
|||
}, |
|||
"emphasis": { |
|||
"borderWidth": 0, |
|||
"borderColor": "#ccc" |
|||
} |
|||
} |
|||
}, |
|||
"candlestick": { |
|||
"itemStyle": { |
|||
"normal": { |
|||
"color": "#edafda", |
|||
"color0": "transparent", |
|||
"borderColor": "#d680bc", |
|||
"borderColor0": "#8fd3e8", |
|||
"borderWidth": "2" |
|||
} |
|||
} |
|||
}, |
|||
"graph": { |
|||
"itemStyle": { |
|||
"normal": { |
|||
"borderWidth": 0, |
|||
"borderColor": "#ccc" |
|||
} |
|||
}, |
|||
"lineStyle": { |
|||
"normal": { |
|||
"width": 1, |
|||
"color": "#aaa" |
|||
} |
|||
}, |
|||
"symbolSize": "6", |
|||
"symbol": "emptyCircle", |
|||
"smooth": true, |
|||
"color": [ |
|||
"#2d8cf0", |
|||
"#19be6b", |
|||
"#f5ae4a", |
|||
"#9189d5", |
|||
"#56cae2", |
|||
"#cbb0e3" |
|||
], |
|||
"label": { |
|||
"normal": { |
|||
"textStyle": { |
|||
"color": "#eee" |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
"map": { |
|||
"itemStyle": { |
|||
"normal": { |
|||
"areaColor": "#f3f3f3", |
|||
"borderColor": "#516b91", |
|||
"borderWidth": 0.5 |
|||
}, |
|||
"emphasis": { |
|||
"areaColor": "rgba(165,231,240,1)", |
|||
"borderColor": "#516b91", |
|||
"borderWidth": 1 |
|||
} |
|||
}, |
|||
"label": { |
|||
"normal": { |
|||
"textStyle": { |
|||
"color": "#000" |
|||
} |
|||
}, |
|||
"emphasis": { |
|||
"textStyle": { |
|||
"color": "rgb(81,107,145)" |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
"geo": { |
|||
"itemStyle": { |
|||
"normal": { |
|||
"areaColor": "#f3f3f3", |
|||
"borderColor": "#516b91", |
|||
"borderWidth": 0.5 |
|||
}, |
|||
"emphasis": { |
|||
"areaColor": "rgba(165,231,240,1)", |
|||
"borderColor": "#516b91", |
|||
"borderWidth": 1 |
|||
} |
|||
}, |
|||
"label": { |
|||
"normal": { |
|||
"textStyle": { |
|||
"color": "#000" |
|||
} |
|||
}, |
|||
"emphasis": { |
|||
"textStyle": { |
|||
"color": "rgb(81,107,145)" |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
"categoryAxis": { |
|||
"axisLine": { |
|||
"show": true, |
|||
"lineStyle": { |
|||
"color": "#cccccc" |
|||
} |
|||
}, |
|||
"axisTick": { |
|||
"show": false, |
|||
"lineStyle": { |
|||
"color": "#333" |
|||
} |
|||
}, |
|||
"axisLabel": { |
|||
"show": true, |
|||
"textStyle": { |
|||
"color": "#fff" |
|||
} |
|||
}, |
|||
"splitLine": { |
|||
"show": false, |
|||
"lineStyle": { |
|||
"color": [ |
|||
"#eeeeee" |
|||
] |
|||
} |
|||
}, |
|||
"splitArea": { |
|||
"show": false, |
|||
"areaStyle": { |
|||
"color": [ |
|||
"rgba(250,250,250,0.05)", |
|||
"rgba(200,200,200,0.02)" |
|||
] |
|||
} |
|||
} |
|||
}, |
|||
"valueAxis": { |
|||
"axisLine": { |
|||
"show": true, |
|||
"lineStyle": { |
|||
"color": "#cccccc" |
|||
} |
|||
}, |
|||
"axisTick": { |
|||
"show": false, |
|||
"lineStyle": { |
|||
"color": "#333" |
|||
} |
|||
}, |
|||
"axisLabel": { |
|||
"show": true, |
|||
"textStyle": { |
|||
"color": "#fff" |
|||
} |
|||
}, |
|||
"splitLine": { |
|||
"show": false, |
|||
"lineStyle": { |
|||
"color": [ |
|||
"#eeeeee" |
|||
] |
|||
} |
|||
}, |
|||
"splitArea": { |
|||
"show": false, |
|||
"areaStyle": { |
|||
"color": [ |
|||
"rgba(250,250,250,0.05)", |
|||
"rgba(200,200,200,0.02)" |
|||
] |
|||
} |
|||
} |
|||
}, |
|||
"logAxis": { |
|||
"axisLine": { |
|||
"show": true, |
|||
"lineStyle": { |
|||
"color": "#cccccc" |
|||
} |
|||
}, |
|||
"axisTick": { |
|||
"show": false, |
|||
"lineStyle": { |
|||
"color": "#333" |
|||
} |
|||
}, |
|||
"axisLabel": { |
|||
"show": true, |
|||
"textStyle": { |
|||
"color": "#999999" |
|||
} |
|||
}, |
|||
"splitLine": { |
|||
"show": true, |
|||
"lineStyle": { |
|||
"color": [ |
|||
"#eeeeee" |
|||
] |
|||
} |
|||
}, |
|||
"splitArea": { |
|||
"show": false, |
|||
"areaStyle": { |
|||
"color": [ |
|||
"rgba(250,250,250,0.05)", |
|||
"rgba(200,200,200,0.02)" |
|||
] |
|||
} |
|||
} |
|||
}, |
|||
"timeAxis": { |
|||
"axisLine": { |
|||
"show": true, |
|||
"lineStyle": { |
|||
"color": "#cccccc" |
|||
} |
|||
}, |
|||
"axisTick": { |
|||
"show": false, |
|||
"lineStyle": { |
|||
"color": "#333" |
|||
} |
|||
}, |
|||
"axisLabel": { |
|||
"show": true, |
|||
"textStyle": { |
|||
"color": "#999999" |
|||
} |
|||
}, |
|||
"splitLine": { |
|||
"show": true, |
|||
"lineStyle": { |
|||
"color": [ |
|||
"#eeeeee" |
|||
] |
|||
} |
|||
}, |
|||
"splitArea": { |
|||
"show": false, |
|||
"areaStyle": { |
|||
"color": [ |
|||
"rgba(250,250,250,0.05)", |
|||
"rgba(200,200,200,0.02)" |
|||
] |
|||
} |
|||
} |
|||
}, |
|||
"toolbox": { |
|||
"iconStyle": { |
|||
"normal": { |
|||
"borderColor": "#999" |
|||
}, |
|||
"emphasis": { |
|||
"borderColor": "#666" |
|||
} |
|||
} |
|||
}, |
|||
"legend": { |
|||
"textStyle": { |
|||
"color": "#fff" |
|||
} |
|||
}, |
|||
"tooltip": { |
|||
"axisPointer": { |
|||
"lineStyle": { |
|||
"color": "#ccc", |
|||
"width": 1 |
|||
}, |
|||
"crossStyle": { |
|||
"color": "#ccc", |
|||
"width": 1 |
|||
} |
|||
} |
|||
}, |
|||
"timeline": { |
|||
"lineStyle": { |
|||
"color": "#8fd3e8", |
|||
"width": 1 |
|||
}, |
|||
"itemStyle": { |
|||
"normal": { |
|||
"color": "#8fd3e8", |
|||
"borderWidth": 1 |
|||
}, |
|||
"emphasis": { |
|||
"color": "#8fd3e8" |
|||
} |
|||
}, |
|||
"controlStyle": { |
|||
"normal": { |
|||
"color": "#8fd3e8", |
|||
"borderColor": "#8fd3e8", |
|||
"borderWidth": 0.5 |
|||
}, |
|||
"emphasis": { |
|||
"color": "#8fd3e8", |
|||
"borderColor": "#8fd3e8", |
|||
"borderWidth": 0.5 |
|||
} |
|||
}, |
|||
"checkpointStyle": { |
|||
"color": "#8fd3e8", |
|||
"borderColor": "rgba(138,124,168,0.37)" |
|||
}, |
|||
"label": { |
|||
"normal": { |
|||
"textStyle": { |
|||
"color": "#8fd3e8" |
|||
} |
|||
}, |
|||
"emphasis": { |
|||
"textStyle": { |
|||
"color": "#8fd3e8" |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
"visualMap": { |
|||
"color": [ |
|||
"#516b91", |
|||
"#59c4e6", |
|||
"#a5e7f0" |
|||
] |
|||
}, |
|||
"dataZoom": { |
|||
"backgroundColor": "rgba(0,0,0,0)", |
|||
"dataBackgroundColor": "rgba(255,255,255,0.3)", |
|||
"fillerColor": "rgba(167,183,204,0.4)", |
|||
"handleColor": "#a7b7cc", |
|||
"handleSize": "100%", |
|||
"textStyle": { |
|||
"color": "#333" |
|||
} |
|||
}, |
|||
"markPoint": { |
|||
"label": { |
|||
"normal": { |
|||
"textStyle": { |
|||
"color": "#eee" |
|||
} |
|||
}, |
|||
"emphasis": { |
|||
"textStyle": { |
|||
"color": "#eee" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,269 @@ |
|||
<template> |
|||
<div class="d_cards"> |
|||
<div |
|||
class="card-item" |
|||
v-for="(card, i) in myData" |
|||
:key="card.title" |
|||
> |
|||
<div class="card-header"> |
|||
<div class="card-header-left">{{ card.title }}</div> |
|||
<div class="card-header-right">{{ '0' + (i + 1) }}</div> |
|||
</div> |
|||
<dv-charts class="ring-charts" :option="card.ring" /> |
|||
<div class="card-footer"> |
|||
<div class="card-footer-item"> |
|||
<div class="footer-title">总工作量</div> |
|||
<div class="footer-detail"> |
|||
<dv-digital-flop :config="card.total" style="width:65%;height:35px;" /> |
|||
<span style="font-size: 16px">人时</span> |
|||
</div> |
|||
</div> |
|||
<div class="card-footer-item"> |
|||
<div class="footer-title">当前进度</div> |
|||
<div class="footer-detail"> |
|||
<dv-digital-flop :config="card.num" style="width:65%;height:35px;" />% |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: 'Cards', |
|||
props:['data'], |
|||
computed:{ |
|||
myData(){ |
|||
if(this.data && this.data.length>0){ |
|||
var cards= this.data.map(i=>{ |
|||
var card=JSON.parse(JSON.stringify(this.cardConfig)) |
|||
card.title=i.name |
|||
card.total.number=[i.budgetWorkload];//累计工作量 人月 |
|||
card.num.number=[i.actRate];//当前进度 |
|||
//资金占比 |
|||
card.ring.series[0].data[0].value=(i.budgetWorkload/i.totalPlanWorkload) //工作量占比 |
|||
console.log(card, ""); |
|||
return card |
|||
}); |
|||
return cards; |
|||
}else{ |
|||
return this.cards; |
|||
} |
|||
} |
|||
}, |
|||
data () { |
|||
return { |
|||
cards: [], |
|||
cardConfig:{ |
|||
title: '', |
|||
total: { |
|||
number: [10], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#ea6027', |
|||
fontWeight: 'bold', |
|||
fontSize: 24 |
|||
} |
|||
}, |
|||
num: { |
|||
number: [20], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#26fcd8', |
|||
fontWeight: 'bold', |
|||
fontSize: 26 |
|||
} |
|||
}, |
|||
ring: { |
|||
series: [ |
|||
{ |
|||
type: 'gauge', |
|||
startAngle: -Math.PI / 2, |
|||
endAngle: Math.PI * 1.5, |
|||
arcLineWidth: 13, |
|||
radius: '80%', |
|||
data: [ |
|||
{ name: '工作量占比', value: 22 } |
|||
], |
|||
axisLabel: { |
|||
show: false |
|||
}, |
|||
axisTick: { |
|||
show: false |
|||
}, |
|||
pointer: { |
|||
show: false |
|||
}, |
|||
backgroundArc: { |
|||
style: { |
|||
stroke: '#224590' |
|||
} |
|||
}, |
|||
details: { |
|||
show: true, |
|||
formatter: '工作量占比{value}%', |
|||
style: { |
|||
fill: '#1ed3e5', |
|||
fontSize: 20 |
|||
} |
|||
} |
|||
} |
|||
], |
|||
color: ['#03d3ec'] |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
methods: { |
|||
createData () { |
|||
const { randomExtend } = this |
|||
const productNames=['商城','营销','项目管理工具','支付','智慧党建'] |
|||
this.cards = new Array(5).fill(0).map((foo, i) => ({ |
|||
title: productNames[i], |
|||
total: { |
|||
number: [randomExtend(90, 100)], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#ea6027', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
num: { |
|||
number: [randomExtend(30, 60)], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#26fcd8', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
ring: { |
|||
series: [ |
|||
{ |
|||
type: 'gauge', |
|||
startAngle: -Math.PI / 2, |
|||
endAngle: Math.PI * 1.5, |
|||
arcLineWidth: 13, |
|||
radius: '80%', |
|||
data: [ |
|||
{ name: '资金占比', value: randomExtend(40, 60) } |
|||
], |
|||
axisLabel: { |
|||
show: false |
|||
}, |
|||
axisTick: { |
|||
show: false |
|||
}, |
|||
pointer: { |
|||
show: false |
|||
}, |
|||
backgroundArc: { |
|||
style: { |
|||
stroke: '#224590' |
|||
} |
|||
}, |
|||
details: { |
|||
show: true, |
|||
formatter: '资金占比{value}%', |
|||
style: { |
|||
fill: '#1ed3e5', |
|||
fontSize: 20 |
|||
} |
|||
} |
|||
} |
|||
], |
|||
color: ['#03d3ec'] |
|||
} |
|||
})) |
|||
}, |
|||
randomExtend (minNum, maxNum) { |
|||
if (arguments.length === 1) { |
|||
return parseInt(Math.random() * minNum + 1, 10) |
|||
} else { |
|||
return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10) |
|||
} |
|||
} |
|||
}, |
|||
mounted () { |
|||
const { createData } = this |
|||
createData() |
|||
setInterval(this.createData, 300) |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="less"> |
|||
.d_cards { |
|||
display: flex; |
|||
width: 100%; |
|||
justify-content: space-between; |
|||
height: 100%; |
|||
margin-left: 15px; |
|||
margin-top: 10px; |
|||
|
|||
.card-item { |
|||
background-color: rgba(6, 30, 93, 0.5); |
|||
border-top: 2px solid rgba(1, 153, 209, .5); |
|||
width: 19%; |
|||
display: flex; |
|||
flex-direction: column; |
|||
justify-content: space-around; |
|||
} |
|||
|
|||
.card-header { |
|||
display: flex; |
|||
height: 20%; |
|||
align-items: center; |
|||
justify-content: space-between; |
|||
|
|||
.card-header-left { |
|||
font-size: 18px; |
|||
font-weight: bold; |
|||
padding-left: 20px; |
|||
} |
|||
|
|||
.card-header-right { |
|||
padding-right: 20px; |
|||
font-size: 40px; |
|||
color: #03d3ec; |
|||
} |
|||
} |
|||
|
|||
.ring-charts { |
|||
height: 55%; |
|||
} |
|||
|
|||
.card-footer { |
|||
height: 25%; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: space-around; |
|||
} |
|||
|
|||
.card-footer-item { |
|||
// padding: 5px 5px 0px 10px; |
|||
box-sizing: border-box; |
|||
width: 46% !important; |
|||
background-color: rgba(6, 30, 93, 0.7); |
|||
border-radius: 3px; |
|||
|
|||
.footer-title { |
|||
font-size: 15px; |
|||
margin-bottom: 5px; |
|||
} |
|||
.footer-detail { |
|||
color: #1294fb; |
|||
display: flex; |
|||
font-size: 18px; |
|||
align-items: center; |
|||
.dv-digital-flop { |
|||
margin-right: 5px; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,214 @@ |
|||
<template> |
|||
<div class="flop"> |
|||
<div |
|||
class="digital-flop-item" |
|||
v-for="item in myData" |
|||
:key="item.title" |
|||
> |
|||
<p class="digital-flop-title">{{ item.title }}</p> |
|||
<div class="digital-flop"> |
|||
<dv-digital-flop |
|||
:config="item.number" |
|||
style="width:140px; height:50px;" |
|||
/> |
|||
<span class="unit">{{ item.unit }}</span> |
|||
</div> |
|||
|
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: 'DigitalFlop', |
|||
data () { |
|||
return { |
|||
defaultDigitalFlopData: [] |
|||
} |
|||
}, |
|||
computed:{ |
|||
myData(){ |
|||
if(this.data){ |
|||
return this.data |
|||
}else{ |
|||
return this.defaultDigitalFlopData |
|||
} |
|||
} |
|||
}, |
|||
props:['data'], |
|||
methods: { |
|||
createData () { |
|||
const { randomExtend } = this |
|||
|
|||
this.defaultDigitalFlopData = [ |
|||
{ |
|||
title: '累计金额', |
|||
number: { |
|||
number: [randomExtend(50000, 10000000)], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#40faee', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '元' |
|||
}, |
|||
{ |
|||
title: '发布总任务数', |
|||
number: { |
|||
number: [randomExtend(20000, 30000)], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#4d99fc', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '个' |
|||
}, |
|||
{ |
|||
title: '项目', |
|||
number: { |
|||
number: [randomExtend(200, 300)], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#f46827', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '个' |
|||
}, |
|||
{ |
|||
title: '参与人数', |
|||
number: { |
|||
number: [randomExtend(2000, 3000)], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#40faee', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '个' |
|||
}, |
|||
{ |
|||
title: '客户', |
|||
number: { |
|||
number: [randomExtend(100, 200)], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#4d99fc', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '个' |
|||
}, |
|||
{ |
|||
title: '需求', |
|||
number: { |
|||
number: [randomExtend(5000, 100000)], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#f46827', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '个' |
|||
}, |
|||
{ |
|||
title: '产品', |
|||
number: { |
|||
number: [randomExtend(50, 100)], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#40faee', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '个' |
|||
}, |
|||
{ |
|||
title: '测试用例', |
|||
number: { |
|||
number: [randomExtend(5000, 100000)], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#4d99fc', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '个' |
|||
}, |
|||
{ |
|||
title: '迭代', |
|||
number: { |
|||
number: [randomExtend(500, 10000)], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#f46827', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '个' |
|||
} |
|||
] |
|||
}, |
|||
randomExtend (minNum, maxNum) { |
|||
if (arguments.length === 1) { |
|||
return parseInt(Math.random() * minNum + 1, 10) |
|||
} else { |
|||
return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10) |
|||
} |
|||
} |
|||
}, |
|||
mounted () { |
|||
const { createData } = this |
|||
createData() |
|||
setInterval(createData, 30000) |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="less" scoped> |
|||
.flop { |
|||
width: 100%; |
|||
height: 120px; |
|||
display: flex; |
|||
justify-content: space-between; |
|||
background-color: rgba(13,20,39,0.5); |
|||
.digital-flop-item { |
|||
flex: 1; |
|||
display: flex; |
|||
flex-direction: column; |
|||
justify-content: center; |
|||
align-items: center; |
|||
border-left: 3px solid rgb(6, 30, 93); |
|||
border-right: 3px solid rgb(6, 30, 93); |
|||
} |
|||
|
|||
.digital-flop-title { |
|||
font-size: 24px; |
|||
margin:20px 20px 10px 20px; |
|||
} |
|||
|
|||
.digital-flop { |
|||
display: flex; |
|||
text-align: center; |
|||
} |
|||
|
|||
.unit { |
|||
margin-left: 10px; |
|||
display: flex; |
|||
align-items: flex-end; |
|||
box-sizing: border-box; |
|||
padding-bottom: 13px; |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,103 @@ |
|||
#index { |
|||
color: #d3d6dd; |
|||
width: 1920px; |
|||
height: 1080px; |
|||
position: absolute; |
|||
top: 50%; |
|||
left: 50%; |
|||
transform: translate(-50%, -50%); |
|||
transform-origin: left top; |
|||
overflow: hidden; |
|||
.bg { |
|||
width: 100%; |
|||
height: 100%; |
|||
padding: 16px 16px 0 16px; |
|||
background-image: url("../../../../assets/image/datav_bg2.png"); |
|||
background-size: cover; |
|||
background-position: center center; |
|||
} |
|||
|
|||
.row_1 { |
|||
display: flex; |
|||
.dv-dec-10, |
|||
.dv-dec-10-s { |
|||
width: 33.3%; |
|||
height: 5px; |
|||
} |
|||
.dv-dec-10-s { |
|||
transform: rotateY(180deg); |
|||
} |
|||
.middle { |
|||
display: flex; |
|||
.dv-dec-8 { |
|||
width: 200px; |
|||
height: 30px; |
|||
} |
|||
.title { |
|||
position: relative; |
|||
width: 500px; |
|||
height: 40px; |
|||
text-align: center; |
|||
background-size: cover; |
|||
background-repeat: no-repeat; |
|||
line-height: 40px; |
|||
.title-text { |
|||
font-size: 36px; |
|||
position: absolute; |
|||
bottom: 0; |
|||
left: 50%; |
|||
transform: translate(-50%); |
|||
} |
|||
.dv-dec-6 { |
|||
position: absolute; |
|||
bottom: -30px; |
|||
left: 50%; |
|||
width: 250px; |
|||
height: 8px; |
|||
transform: translate(-50%); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
.row_2 { |
|||
display: flex; |
|||
margin-top: 42px; |
|||
} |
|||
|
|||
.row_3 { |
|||
display: flex; |
|||
margin-top: 20px; |
|||
.left { |
|||
width: 300px; |
|||
height: 826px; |
|||
} |
|||
.right { |
|||
flex: 1; |
|||
height: 820px; |
|||
display: flex; |
|||
flex-direction: column; |
|||
.r_top { |
|||
display: flex; |
|||
flex: 1; |
|||
.top_1, .top_2, .top_3 { |
|||
height: 400px; |
|||
} |
|||
.top_1 { |
|||
width: 480px; |
|||
} |
|||
.top_2 { |
|||
width: 325px; |
|||
} |
|||
.top_3 { |
|||
width: 772px; |
|||
} |
|||
} |
|||
.r_bottom { |
|||
display: flex; |
|||
flex: 1; |
|||
} |
|||
} |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,466 @@ |
|||
<template> |
|||
<div id="index" ref="appRef"> |
|||
<div class="bg"> |
|||
<dv-loading v-if="loading">加载中</dv-loading> |
|||
<div v-else class="host-body"> |
|||
<!-- 第一行 --> |
|||
<div class="row_1"> |
|||
<dv-decoration-10 class="dv-dec-10" /> |
|||
<div class="middle"> |
|||
<dv-decoration-8 class="dv-dec-8" :color="['#568aea', '#000000']" /> |
|||
<div class="title"> |
|||
<span class="title-text">综合数据监控</span> |
|||
<dv-decoration-6 class="dv-dec-6" :reverse="true" :color="['#50e3c2', '#67a1e5']"></dv-decoration-6> |
|||
</div> |
|||
<dv-decoration-8 class="dv-dec-8" :reverse="true" :color="['#568aea', '#000000']" /> |
|||
</div> |
|||
<dv-decoration-10 class="dv-dec-10-s" /> |
|||
</div> |
|||
|
|||
<!-- 第二行 --> |
|||
<div class="row_2"> |
|||
<digital-flop /> |
|||
</div> |
|||
|
|||
<!-- 第三行 --> |
|||
<div class="row_3"> |
|||
<div class="left"> |
|||
<ranking-board :data="rankingBoardData" :title="'团队进度'" /> |
|||
</div> |
|||
<div class="right"> |
|||
<div class="r_top"> |
|||
<div class="top_1"> |
|||
<rose-chart :data="roseChartData" :title="'资金分布'"/> |
|||
</div> |
|||
<div class="top_2"> |
|||
<water-level-chart :data="waterLevelChartData" :title="'计划资金累计完成情况'"/> |
|||
</div> |
|||
<div class="top_3"> |
|||
<scroll-board :data="scrollBoardData" :title="'动态'" :header="['时间','操作人','动作','备注']"/> |
|||
</div> |
|||
</div> |
|||
<div class="r_bottom"> |
|||
<cards :data="cardsData" :title="'阶段计划'" /> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import digitalFlop from './digitalFlop'; |
|||
import drawMixin from "../utils/drawMixin"; |
|||
import rankingBoard from './rankingBoard' |
|||
import roseChart from './roseChart' |
|||
import waterLevelChart from './waterLevelChart' |
|||
import scrollBoard from './scrollBoard' |
|||
import cards from './cards' |
|||
import { listOption } from '@/api/mdp/meta/itemOption';//下拉框数据查询 |
|||
import { listXmProjectState } from '@/api/xm/core/xmProjectState'; |
|||
import { listXmGroupState} from '@/api/xm/core/xmGroupState'; |
|||
import { listXmProjectTaskTypeState } from '@/api/xm/core/xmProjectTaskTypeState'; |
|||
import { listXmRecord } from '@/api/xm/core/xmRecord'; |
|||
import { listXmPhase } from '@/api/xm/core/xmPhase'; |
|||
import { mapGetters } from 'vuex' |
|||
|
|||
import Vue from 'vue' |
|||
import dataV from '@jiaminghi/data-view' |
|||
Vue.use(dataV) |
|||
|
|||
export default { |
|||
mixins: [ drawMixin ], |
|||
components: {digitalFlop, rankingBoard, roseChart, waterLevelChart, scrollBoard, cards}, |
|||
computed: { |
|||
|
|||
...mapGetters([ |
|||
'userInfo' |
|||
]), |
|||
digitalFlopData(){ |
|||
if(!this.xmProjectState){ |
|||
return null; |
|||
} |
|||
var digitalFlopData = [ |
|||
{ |
|||
title: '累计金额', |
|||
number: { |
|||
number: [(this.floatValue(this.xmProjectState.totalBudgetNouserAmount) + this.floatValue(this.xmProjectState.totalBudgetIuserAmount) + this.floatValue(this.xmProjectState.totalBudgetOuserAmount))/10000], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#40faee', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '万元' |
|||
}, |
|||
{ |
|||
title: '发布总任务数', |
|||
number: { |
|||
number: [this.xmProjectState.totalTaskCnt ], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#4d99fc', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '个' |
|||
}, |
|||
{ |
|||
title: '项目进度', |
|||
number: { |
|||
number: [this.xmProjectState.totalProgress ], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#f46827', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '%' |
|||
}, |
|||
{ |
|||
title: '参与人数', |
|||
number: { |
|||
number: [this.xmProjectState.totalStaffCnt], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#40faee', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '人' |
|||
}, |
|||
{ |
|||
title: '客户', |
|||
number: { |
|||
number: [this.xmProjectState.productCnt], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#4d99fc', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '个' |
|||
}, |
|||
{ |
|||
title: '需求', |
|||
number: { |
|||
number: [this.xmProjectState.menuCnt], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#f46827', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '个' |
|||
}, |
|||
{ |
|||
title: '产品', |
|||
number: { |
|||
number: [this.xmProjectState.productCnt], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#40faee', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '个' |
|||
}, |
|||
{ |
|||
title: '测试用例', |
|||
number: { |
|||
number: [this.xmProjectState.testCases], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#4d99fc', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '个' |
|||
}, |
|||
{ |
|||
title: '迭代', |
|||
number: { |
|||
number: [this.xmProjectState.iterationCnt], |
|||
content: '{nt}', |
|||
textAlign: 'right', |
|||
style: { |
|||
fill: '#f46827', |
|||
fontWeight: 'bold' |
|||
} |
|||
}, |
|||
unit: '个' |
|||
} |
|||
] |
|||
return digitalFlopData; |
|||
}, |
|||
rankingBoardData(){ |
|||
if( !this.xmGroupStates || this.xmGroupStates.length==0 ){ |
|||
return []; |
|||
} |
|||
var rankingBoardData=this.xmGroupStates.map(i=>{ |
|||
return {name:i.groupName,value:i.finishRate+'%'} |
|||
}) |
|||
return rankingBoardData |
|||
}, |
|||
roseChartData(){ |
|||
var taskTypeList=this.options.taskType |
|||
if(this.xmProjectTaskTypeStates && this.xmProjectTaskTypeStates.length>0){ |
|||
var xmProjectTaskTypeStates=this.xmProjectTaskTypeStates.filter(i=>i.planAmount>0); |
|||
var roseChartData=xmProjectTaskTypeStates.map(i=>{ |
|||
|
|||
if(!taskTypeList || taskTypeList.length==0){ |
|||
return { |
|||
name:i.taskType?i.taskType:'其它', |
|||
value:i.planAmount?i.planAmount:0 |
|||
} |
|||
}else{ |
|||
var taskTypes=taskTypeList.filter(k=>k.optionValue==i.taskType) |
|||
if(taskTypes && taskTypes.length>0){ |
|||
var taskType=taskTypes[0] |
|||
return { |
|||
name:taskType.optionName, |
|||
value:i.planAmount?i.planAmount:0 |
|||
} |
|||
}else{ |
|||
return { |
|||
name:i.taskType?i.taskType:'其它', |
|||
value:i.planAmount?i.planAmount:0 |
|||
} |
|||
} |
|||
} |
|||
}) |
|||
return roseChartData |
|||
}else{ |
|||
return null; |
|||
} |
|||
|
|||
}, |
|||
waterLevelChartData(){ |
|||
if(this.xmProjectState){ |
|||
var data={} |
|||
var allAmount=this.floatValue(this.xmProjectState.totalBudgetNouserAmount) + this.floatValue(this.xmProjectState.totalBudgetIuserAmount) + this.floatValue(this.xmProjectState.totalBudgetOuserAmount); |
|||
data.finishNum= this.floatValue(this.xmProjectState.totalCostNouserAmount) + this.floatValue(this.xmProjectState.totalCostIuserAmount) +this.floatValue(this.xmProjectState.totalCostOuserAmount) |
|||
data.finishPercent= parseFloat(data.finishNum/allAmount * 100).toFixed(0) |
|||
return data; |
|||
}else{ |
|||
return null; |
|||
} |
|||
}, |
|||
scrollBoardData(){ |
|||
if(this.xmRecords && this.xmRecords.length>0){ |
|||
var data = this.xmRecords.map(i=>{ |
|||
return [i.operTime,i.operUsername,i.action,i.remarks] |
|||
}) |
|||
return data; |
|||
}else{ |
|||
return null; |
|||
} |
|||
}, |
|||
cardsData(){ |
|||
if(this.xmPhases && this.xmPhases.length>0){ |
|||
var totalPlanWorkload=this.floatValue(this.xmProjectState.totalPlanWorkload) |
|||
return this.xmPhases.map(i=>{ |
|||
i.totalPlanWorkload=totalPlanWorkload |
|||
return i; |
|||
}) |
|||
}else{ |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
}, |
|||
data () { |
|||
return { |
|||
loading: true, |
|||
filters:{ |
|||
projectId:null, |
|||
}, |
|||
xmProjectState:null, |
|||
xmGroupStates:[], |
|||
xmProjectTaskTypeStates:[], |
|||
xmRecords:[], |
|||
xmPhases:[], |
|||
options:{ |
|||
taskType:[], |
|||
}, |
|||
xmRecordPageInfo:{//分页数据 |
|||
total:0,//服务器端收到0时,会自动计算总记录数,如果上传>0的不自动计算。 |
|||
pageSize:20,//每页数据 |
|||
count:false,//是否需要重新计算总记录数 |
|||
pageNum:1,//当前页码、从1开始计算 |
|||
orderFields:["oper_time"],//排序列 如 ['sex','student_id'],必须为数据库字段 |
|||
orderDirs:["desc"]//升序 asc,降序desc 如 性别 升序、学生编号降序 ['asc','desc'] |
|||
}, |
|||
|
|||
xmGroupStatePageInfo:{//分页数据 |
|||
total:0,//服务器端收到0时,会自动计算总记录数,如果上传>0的不自动计算。 |
|||
pageSize:5,//每页数据 |
|||
count:false,//是否需要重新计算总记录数 |
|||
pageNum:1,//当前页码、从1开始计算 |
|||
orderFields:["calc_time"],//排序列 如 ['sex','student_id'],必须为数据库字段 |
|||
orderDirs:["desc"]//升序 asc,降序desc 如 性别 升序、学生编号降序 ['asc','desc'] |
|||
}, |
|||
|
|||
|
|||
xmPhasePageInfo:{//分页数据 |
|||
total:0,//服务器端收到0时,会自动计算总记录数,如果上传>0的不自动计算。 |
|||
pageSize:5,//每页数据 |
|||
count:false,//是否需要重新计算总记录数 |
|||
pageNum:1,//当前页码、从1开始计算 |
|||
orderFields:["calc_time"],//排序列 如 ['sex','student_id'],必须为数据库字段 |
|||
orderDirs:["desc"]//升序 asc,降序desc 如 性别 升序、学生编号降序 ['asc','desc'] |
|||
}, |
|||
} |
|||
}, |
|||
methods: { |
|||
getXmProjectState(){ |
|||
var params = { |
|||
projectId:this.filters.projectId |
|||
} |
|||
listXmProjectState(params).then(res=>{ |
|||
var tips = res.data.tips; |
|||
if(tips.isOk){ |
|||
if(res.data.data.length>0){ |
|||
this.xmProjectState=res.data.data[0] |
|||
} |
|||
setTimeout(() => { |
|||
this.loading = false; |
|||
}, 100); |
|||
} |
|||
}); |
|||
}, |
|||
getXmGroupStates(){ |
|||
let params = { |
|||
pageSize: this.xmGroupStatePageInfo.pageSize, |
|||
pageNum: this.xmGroupStatePageInfo.pageNum, |
|||
total: this.xmGroupStatePageInfo.total, |
|||
count:this.xmGroupStatePageInfo.count |
|||
}; |
|||
if(this.xmGroupStatePageInfo.orderFields!=null && this.xmGroupStatePageInfo.orderFields.length>0){ |
|||
let orderBys=[]; |
|||
for(var i=0;i<this.xmGroupStatePageInfo.orderFields.length;i++){ |
|||
orderBys.push(this.xmGroupStatePageInfo.orderFields[i]+" "+this.xmGroupStatePageInfo.orderDirs[i]) |
|||
} |
|||
params.orderBy= orderBys.join(",") |
|||
} |
|||
params.branchId=this.userInfo.branchId |
|||
params.projectId=this.filters.projectId |
|||
listXmGroupState(params).then(res=>{ |
|||
var tips = res.data.tips; |
|||
if(tips.isOk){ |
|||
if(res.data.data.length>0){ |
|||
this.xmGroupStates=res.data.data |
|||
} |
|||
} |
|||
}); |
|||
}, |
|||
|
|||
getXmProjectTaskTypeStates(){ |
|||
var params = { |
|||
} |
|||
params.projectId=this.filters.projectId |
|||
|
|||
listXmProjectTaskTypeState(params).then(res=>{ |
|||
var tips = res.data.tips; |
|||
if(tips.isOk){ |
|||
if(res.data.data.length>0){ |
|||
this.xmProjectTaskTypeStates=res.data.data |
|||
} |
|||
} |
|||
}); |
|||
},//获取列表 XmRecord xm_record |
|||
getXmRecords() { |
|||
let params = { |
|||
pageSize: this.xmRecordPageInfo.pageSize, |
|||
pageNum: this.xmRecordPageInfo.pageNum, |
|||
total: this.xmRecordPageInfo.total, |
|||
count:this.xmRecordPageInfo.count |
|||
}; |
|||
params.projectId=this.filters.projectId |
|||
|
|||
if(this.xmRecordPageInfo.orderFields!=null && this.xmRecordPageInfo.orderFields.length>0){ |
|||
let orderBys=[]; |
|||
for(var i=0;i<this.xmRecordPageInfo.orderFields.length;i++){ |
|||
orderBys.push(this.xmRecordPageInfo.orderFields[i]+" "+this.xmRecordPageInfo.orderDirs[i]) |
|||
} |
|||
params.orderBy= orderBys.join(",") |
|||
} |
|||
listXmRecord(params).then((res) => { |
|||
var tips=res.data.tips; |
|||
if(tips.isOk){ |
|||
this.xmRecordPageInfo.total = res.data.total; |
|||
this.xmRecordPageInfo.count=false; |
|||
this.xmRecords = res.data.data; |
|||
}else{ |
|||
} |
|||
}) ; |
|||
}, |
|||
//获取列表 XmPhase 功能状态表,无需前端维护,所有数据由汇总统计得出 |
|||
getXmPhases() { |
|||
let params = { |
|||
pageSize: this.xmPhasePageInfo.pageSize, |
|||
pageNum: this.xmPhasePageInfo.pageNum, |
|||
total: this.xmPhasePageInfo.total, |
|||
count:this.xmPhasePageInfo.count |
|||
}; |
|||
if(this.xmPhasePageInfo.orderFields!=null && this.xmPhasePageInfo.orderFields.length>0){ |
|||
let orderBys=[]; |
|||
for(var i=0;i<this.xmPhasePageInfo.orderFields.length;i++){ |
|||
orderBys.push(this.xmPhasePageInfo.orderFields[i]+" "+this.xmPhasePageInfo.orderDirs[i]) |
|||
} |
|||
params.orderBy= orderBys.join(",") |
|||
} |
|||
|
|||
params.projectId=this.filters.projectId |
|||
listXmPhase(params).then((res) => { |
|||
var tips=res.data.tips; |
|||
if(tips.isOk){ |
|||
this.xmPhasePageInfo.total = res.data.total; |
|||
this.xmPhasePageInfo.count=false; |
|||
this.xmPhases = res.data.data; |
|||
}else{ |
|||
} |
|||
}) ; |
|||
}, |
|||
floatValue(value){ |
|||
if(!value){ |
|||
return 0.0; |
|||
}else{ |
|||
return value |
|||
} |
|||
} |
|||
}, |
|||
|
|||
mounted(){ |
|||
if(this.$route.params){ |
|||
this.filters.projectId=this.$route.params.projectId; |
|||
} |
|||
|
|||
this.getXmProjectState(); |
|||
this.getXmGroupStates(); |
|||
this.getXmProjectTaskTypeStates(); |
|||
this.getXmRecords(); |
|||
this.getXmPhases(); |
|||
|
|||
listOption([{categoryId:'all',itemCode:'taskType'}] ).then(res=>{ |
|||
if(res.data.tips.isOk){ |
|||
this.options=res.data.data |
|||
} |
|||
}); |
|||
}, |
|||
} |
|||
</script> |
|||
|
|||
<style lang="less"> |
|||
@import './index.less'; |
|||
</style> |
|||
@ -0,0 +1,102 @@ |
|||
<template> |
|||
<div class="ranking-board"> |
|||
<span class="ranking-board-title">{{title}}</span> |
|||
<dv-scroll-ranking-board :config="config"/> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: 'RankingBoard', |
|||
props:['data','title'], |
|||
computed:{ |
|||
config(){ |
|||
if( !this.data || this.data.length==0){ |
|||
return this.defaultConfig; |
|||
}else{ |
|||
var data=this.data; |
|||
data.forEach(element => { |
|||
element.name = `<span style="font-size:16px;">${element.name}</span>` |
|||
}); |
|||
var config={ |
|||
data:data, |
|||
carousel: "page" |
|||
} |
|||
return config |
|||
} |
|||
} |
|||
}, |
|||
data () { |
|||
return { |
|||
defaultConfig: { |
|||
data: [ |
|||
{ |
|||
name: '商城项目', |
|||
value: '30%' |
|||
}, |
|||
{ |
|||
name: '营销项目', |
|||
value: '40%' |
|||
}, |
|||
{ |
|||
name: '支付项目', |
|||
value: '50%' |
|||
}, |
|||
{ |
|||
name: '短信项目', |
|||
value: '60%' |
|||
}, |
|||
{ |
|||
name: '党建项目', |
|||
value: '50%' |
|||
}, |
|||
{ |
|||
name: '协同办公项目', |
|||
value: '90%' |
|||
}, |
|||
{ |
|||
name: '即聊项目', |
|||
value: '40%' |
|||
}, |
|||
{ |
|||
name: '审计项目', |
|||
value: '60%' |
|||
}, |
|||
{ |
|||
name: '溯源项目', |
|||
value: '90%' |
|||
} |
|||
], |
|||
rowNum: 9, |
|||
|
|||
} |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="less" scoped> |
|||
.ranking-board { |
|||
width: 300px; |
|||
height: 100%; |
|||
box-shadow: 0 0 3px blue; |
|||
display: flex; |
|||
flex-direction: column; |
|||
background-color: rgba(10, 13, 28, 0.5); |
|||
border-top: 2px solid rgba(1, 153, 209, .5); |
|||
box-sizing: border-box; |
|||
padding: 0px 30px; |
|||
|
|||
.ranking-board-title { |
|||
height: 50px; |
|||
display: flex; |
|||
align-items: center; |
|||
font-size: 20px; |
|||
font-weight: 700; |
|||
} |
|||
|
|||
.dv-scroll-ranking-board { |
|||
flex: 1; |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,176 @@ |
|||
<template> |
|||
<div class="rose-chart"> |
|||
<div class="rose-chart-title">{{title}}</div> |
|||
<Echart |
|||
:options="option" |
|||
id="dv_roseChart" |
|||
height="340px" |
|||
width="100%" |
|||
></Echart> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import Echart from '../common' |
|||
export default { |
|||
name: 'RoseChart1', |
|||
components: {Echart}, |
|||
props:['data','title'], |
|||
computed:{ |
|||
option(){ |
|||
if( !this.data || this.data.length==0){ |
|||
return this.defaultOption; |
|||
}else{ |
|||
this.createData() |
|||
let tempData = this.data.slice(0, 5); |
|||
let obj = {name: '其它', value : 0}; |
|||
let v = 0; |
|||
this.data.forEach((element,index) => { |
|||
if(index > 5) { |
|||
v += element.value; |
|||
} |
|||
}); |
|||
obj.value = v; |
|||
if(obj.value > 0) { |
|||
tempData.push(obj); |
|||
} |
|||
var option = JSON.parse(JSON.stringify(this.options)) |
|||
option.series[0].data = tempData |
|||
option.legend.data = tempData |
|||
return option |
|||
} |
|||
} |
|||
|
|||
|
|||
}, |
|||
data () { |
|||
return { |
|||
defaultOption: {}, |
|||
options : { |
|||
color: [ |
|||
"#37a2da", |
|||
"#32c5e9", |
|||
"#9fe6b8", |
|||
"#ffdb5c", |
|||
"#ff9f7f", |
|||
"#fb7293", |
|||
"#e7bcf3" |
|||
], |
|||
tooltip: { |
|||
trigger: "item", |
|||
formatter: "{b} : {c} ({d}%)" |
|||
}, |
|||
legend: { |
|||
orient: "horizontal", |
|||
icon: "circle", |
|||
bottom: 0, |
|||
x: "center", |
|||
data: |
|||
[ |
|||
{ value: 40, name: 'rose 1' }, |
|||
{ value: 38, name: 'rose 2' }, |
|||
{ value: 32, name: 'rose 3' }, |
|||
{ value: 30, name: 'rose 4' }, |
|||
{ value: 28, name: 'rose 5' }, |
|||
], |
|||
textStyle: { |
|||
color: "#fff", |
|||
fontSize: 18 |
|||
} |
|||
}, |
|||
calculable: true, |
|||
series: [ |
|||
{ |
|||
type: 'pie', |
|||
radius: [35, 80], |
|||
center: ['50%', '45%'], |
|||
roseType: 'area', |
|||
data: [ |
|||
{ value: 40, name: 'rose 1' }, |
|||
{ value: 38, name: 'rose 2' }, |
|||
{ value: 32, name: 'rose 3' }, |
|||
{ value: 30, name: 'rose 4' }, |
|||
{ value: 28, name: 'rose 5' }, |
|||
] |
|||
} |
|||
] |
|||
} |
|||
} |
|||
}, |
|||
methods: { |
|||
createData () { |
|||
const { randomExtend } = this |
|||
this.defaultOption = { |
|||
series: [ |
|||
{ |
|||
type: 'pie', |
|||
radius: '50%', |
|||
roseSort: false, |
|||
data: [ |
|||
{ name: '需求', value: randomExtend(40, 70) }, |
|||
{ name: '开发', value: randomExtend(20, 30) }, |
|||
{ name: '测试', value: randomExtend(10, 50) }, |
|||
{ name: '设计', value: randomExtend(5, 20) }, |
|||
{ name: '运营', value: randomExtend(40, 50) }, |
|||
{ name: '客服', value: randomExtend(20, 30) }, |
|||
{ name: '管理', value: randomExtend(5, 10) }, |
|||
{ name: '产品', value: randomExtend(20, 35) }, |
|||
{ name: '运维', value: randomExtend(5, 10) } |
|||
], |
|||
insideLabel: { |
|||
show: false |
|||
}, |
|||
outsideLabel: { |
|||
formatter: '{name} {percent}%', |
|||
labelLineEndLength: 20, |
|||
style: { |
|||
fill: '#fff' |
|||
}, |
|||
labelLineStyle: { |
|||
stroke: '#fff' |
|||
} |
|||
}, |
|||
roseType: true |
|||
} |
|||
], |
|||
color: ['#da2f00', '#fa3600', '#ff4411', '#ff724c', '#541200', '#801b00', '#a02200', '#5d1400', '#b72700'] |
|||
} |
|||
}, |
|||
randomExtend (minNum, maxNum) { |
|||
if (arguments.length === 1) { |
|||
return parseInt(Math.random() * minNum + 1, 10) |
|||
} else { |
|||
return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10) |
|||
} |
|||
} |
|||
}, |
|||
mounted () { |
|||
// const { createData } = this |
|||
// createData() |
|||
// setInterval(createData, 30000) |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="less"> |
|||
.rose-chart { |
|||
width: 450px; |
|||
height: 400px; |
|||
margin: 0 15px 0 15px; |
|||
background-color: rgba(6, 30, 93, 0.5); |
|||
border-top: 2px solid rgba(1, 153, 209, .5); |
|||
box-sizing: border-box; |
|||
.rose-chart-title { |
|||
height: 50px; |
|||
font-weight: bold; |
|||
text-indent: 20px; |
|||
font-size: 20px; |
|||
display: flex; |
|||
align-items: center; |
|||
} |
|||
|
|||
.dv-charts-container { |
|||
height: calc(~"100% - 20px"); |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,66 @@ |
|||
<template> |
|||
<div class="scroll-board"> |
|||
<dv-scroll-board :config="myConfig" /> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: 'ScrollBoard1', |
|||
props:['data','header'], |
|||
computed:{ |
|||
myConfig(){ |
|||
if(this.data && this.data.length>0){ |
|||
var config=JSON.parse(JSON.stringify(this.config)); |
|||
this.data.forEach(d => { |
|||
d.forEach((text, index) => { |
|||
d[index] = `<span style="font-size:16px;">${text}</span>`; |
|||
}); |
|||
}); |
|||
config.header=this.header |
|||
config.data=this.data |
|||
return config; |
|||
}else{ |
|||
return this.config |
|||
} |
|||
} |
|||
}, |
|||
data () { |
|||
return { |
|||
config: { |
|||
header: ['时间', '项目', '金额', '变动情况'], |
|||
data: [ |
|||
['2019-07-01 19:25:00', '唛萌项目管理工具', '500万元', '立项'], |
|||
['2019-07-02 17:25:00', '唛盟商城项目', '300万元', '通过验收'], |
|||
['2019-07-03 16:25:00', '唛萌营销项目', '200万元', '测试完成'], |
|||
['2019-07-04 15:25:00', '组织管理系统项目', '100万', '竞标中'], |
|||
['2019-07-05 14:25:00', '支付管理系统', '700万元', '完成第一里程碑'], |
|||
['2019-07-06 13:25:00', '溯源系统', '300万元', '系统对接完成'], |
|||
['2019-07-07 12:25:00', '智能办公系统', '400万元', '试运行中'], |
|||
['2019-07-08 11:25:00', '数据可视化系统', '600万元', '开发中'], |
|||
['2019-07-09 10:25:00', '党建系统', '500万元', '上线成功'], |
|||
['2019-07-10 09:25:00', '智慧社区系统', '300万元', '运营中'] |
|||
], |
|||
index: true, |
|||
columnWidth: [50, 150, 100,200,200], |
|||
align: ['center'], |
|||
rowNum: 7, |
|||
headerBGC: '#1981f6', |
|||
headerHeight: 45, |
|||
oddRowBGC: 'rgba(0, 44, 81, 0.8)', |
|||
evenRowBGC: 'rgba(10, 29, 50, 0.8)', |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="less"> |
|||
.scroll-board { |
|||
width: 100%; |
|||
box-sizing: border-box; |
|||
margin-left: 10px; |
|||
height: 100%; |
|||
overflow: hidden; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,109 @@ |
|||
<template> |
|||
<div class="water-level-chart"> |
|||
<div class="water-level-chart-title">{{title}}</div> |
|||
|
|||
<div class="water-level-chart-details"> |
|||
累计完成<span>{{myData.finishNum}}</span>元 |
|||
</div> |
|||
|
|||
<div class="chart-container"> |
|||
<dv-water-level-pond :config="myData.config" /> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: 'WaterLevelChart1', |
|||
props:['data','title'], |
|||
computed:{ |
|||
myData(){ |
|||
if(this.data){ |
|||
|
|||
var config=JSON.parse(JSON.stringify( this.config)) |
|||
config.data=[this.data.finishPercent] |
|||
return { |
|||
finishNum:this.data.finishNum, |
|||
config:config |
|||
} |
|||
} else{ |
|||
return { |
|||
finishNum:12350, |
|||
config:this.config |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
data () { |
|||
return { |
|||
config: { |
|||
data: [45], |
|||
shape: 'round', |
|||
waveHeight: 25, |
|||
waveNum: 2 |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="less"> |
|||
.water-level-chart { |
|||
width: 100%; |
|||
height: 100%; |
|||
box-sizing: border-box; |
|||
margin-right: 20px; |
|||
background-color: rgba(6, 30, 93, 0.5); |
|||
border-top: 2px solid rgba(1, 153, 209, .5); |
|||
display: flex; |
|||
flex-direction: column; |
|||
|
|||
.water-level-chart-title { |
|||
font-weight: bold; |
|||
height: 50px; |
|||
display: flex; |
|||
align-items: center; |
|||
font-size: 20px; |
|||
justify-content: center; |
|||
} |
|||
|
|||
.water-level-chart-details { |
|||
height: 15%; |
|||
display: flex; |
|||
justify-content: center; |
|||
font-size: 17px; |
|||
align-items: flex-end; |
|||
|
|||
span { |
|||
font-size: 35px; |
|||
font-weight: bold; |
|||
color: #58a1ff; |
|||
margin: 0 5px; |
|||
margin-bottom: -5px; |
|||
} |
|||
} |
|||
|
|||
.chart-container { |
|||
flex: 1; |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
} |
|||
|
|||
.dv-water-pond-level { |
|||
max-width: 90%; |
|||
width: 200px; |
|||
height: 200px; |
|||
border: 10px solid #19c3eb; |
|||
border-radius: 50%; |
|||
|
|||
ellipse { |
|||
stroke: transparent !important; |
|||
} |
|||
|
|||
text { |
|||
font-size: 40px; |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,59 @@ |
|||
// 屏幕适配 mixin 函数
|
|||
|
|||
// * 默认缩放值
|
|||
const scale = { |
|||
width: '1', |
|||
height: '1', |
|||
} |
|||
|
|||
// * 设计稿尺寸(px)
|
|||
const baseWidth = 1920 |
|||
const baseHeight = 1080 |
|||
|
|||
// * 需保持的比例(默认1.77778)
|
|||
// const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))
|
|||
const baseProportion = 1.91 |
|||
|
|||
export default { |
|||
data() { |
|||
return { |
|||
// * 定时函数
|
|||
drawTiming: null |
|||
} |
|||
}, |
|||
mounted () { |
|||
this.calcRate() |
|||
window.addEventListener('resize', this.resize) |
|||
}, |
|||
beforeDestroy () { |
|||
window.removeEventListener('resize', this.resize) |
|||
}, |
|||
methods: { |
|||
calcRate () { |
|||
console.log(window.innerWidth, window.innerHeight); |
|||
const appRef = this.$refs["appRef"] |
|||
if (!appRef) return |
|||
// 当前宽高比
|
|||
const currentRate = parseFloat((window.innerWidth / window.innerHeight).toFixed(5)) |
|||
if (appRef) { |
|||
if (currentRate > baseProportion) { |
|||
// 表示更宽
|
|||
scale.width = ((window.innerHeight * baseProportion) / baseWidth).toFixed(5) |
|||
scale.height = (window.innerHeight / baseHeight).toFixed(5) |
|||
appRef.style.transform = `scale(${scale.width}, ${scale.height}) translate(-50%, -50%)` |
|||
} else { |
|||
// 表示更高
|
|||
scale.height = ((window.innerWidth / baseProportion) / baseHeight).toFixed(5) |
|||
scale.width = (window.innerWidth / baseWidth).toFixed(5) |
|||
appRef.style.transform = `scale(${scale.width}, ${scale.height}) translate(-50%, -50%)` |
|||
} |
|||
} |
|||
}, |
|||
resize () { |
|||
clearTimeout(this.drawTiming) |
|||
this.drawTiming = setTimeout(() => { |
|||
this.calcRate() |
|||
}, 200) |
|||
} |
|||
}, |
|||
} |
|||
@ -0,0 +1,51 @@ |
|||
/** |
|||
* @param {Function} fn 防抖函数 |
|||
* @param {Number} delay 延迟时间 |
|||
*/ |
|||
export function debounce(fn, delay) { |
|||
var timer; |
|||
return function () { |
|||
var context = this; |
|||
var args = arguments; |
|||
clearTimeout(timer); |
|||
timer = setTimeout(function () { |
|||
fn.apply(context, args); |
|||
}, delay); |
|||
}; |
|||
} |
|||
|
|||
/** |
|||
* @param {date} time 需要转换的时间 |
|||
* @param {String} fmt 需要转换的格式 如 yyyy-MM-dd、yyyy-MM-dd HH:mm:ss |
|||
*/ |
|||
export function formatTime(time, fmt) { |
|||
if (!time) return ''; |
|||
else { |
|||
const date = new Date(time); |
|||
const o = { |
|||
'M+': date.getMonth() + 1, |
|||
'd+': date.getDate(), |
|||
'H+': date.getHours(), |
|||
'm+': date.getMinutes(), |
|||
's+': date.getSeconds(), |
|||
'q+': Math.floor((date.getMonth() + 3) / 3), |
|||
S: date.getMilliseconds(), |
|||
}; |
|||
if (/(y+)/.test(fmt)) |
|||
fmt = fmt.replace( |
|||
RegExp.$1, |
|||
(date.getFullYear() + '').substr(4 - RegExp.$1.length) |
|||
); |
|||
for (const k in o) { |
|||
if (new RegExp('(' + k + ')').test(fmt)) { |
|||
fmt = fmt.replace( |
|||
RegExp.$1, |
|||
RegExp.$1.length === 1 |
|||
? o[k] |
|||
: ('00' + o[k]).substr(('' + o[k]).length) |
|||
); |
|||
} |
|||
} |
|||
return fmt; |
|||
} |
|||
} |
|||
1137
src/views/xm/XmOverview2.vue
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
Write
Preview
Loading…
Cancel
Save
Reference in new issue