master
lion 1 year ago
parent 41f9906d4c
commit 3719b73ec4

@ -15,30 +15,30 @@
},
"dependencies": {
"@riophae/vue-treeselect": "^0.4.0",
"@vue-office/docx": "^1.6.2",
"@vue-office/excel": "^1.7.11",
"@vue-office/pdf": "^2.0.2",
"@vue/composition-api": "^1.7.2",
"axios": "0.18.1",
"echarts": "^5.0.0",
"bpmn-js": "^7.3.1",
"bpmn-js-properties-panel": "^0.37.2",
"camunda-bpmn-moddle": "^4.4.0",
"core-js": "3.6.5",
"element-ui": "2.15.14",
"echarts": "^5.0.0",
"element-resize-detector": "^1.2.4",
"element-ui": "2.15.14",
"gojs": "^2.3.11",
"js-cookie": "2.2.0",
"moment": "^2.29.4",
"normalize.css": "7.0.0",
"nprogress": "0.2.0",
"path-to-regexp": "2.4.0",
"vue": "2.6.10",
"vue-grid-layout": "^2.4.0",
"vue-router": "3.0.6",
"vuex": "3.1.0",
"vxe-table": "^3.8.22",
"wujie-vue2": "^1.0.22",
"moment": "^2.29.4",
"vue-grid-layout": "^2.4.0",
"@vue-office/docx": "^1.6.2",
"@vue-office/excel": "^1.7.11",
"@vue-office/pdf": "^2.0.2",
"@vue/composition-api": "^1.7.2"
"wujie-vue2": "^1.0.22"
},
"devDependencies": {
"@vue/cli-plugin-babel": "4.4.4",

@ -0,0 +1,179 @@
<template>
<div :class="className" :style="{height:height,width:width}" />
</template>
<script>
import * as echarts from 'echarts'
require('echarts/theme/macarons') // echarts theme
import resize from '@/mixins/resize'
export default {
mixins: [resize],
props: {
className: {
type: String,
default: ''
},
height: {
type: String,
default: '100px'
},
width: {
type: String,
default: '100px'
},
percent: {
type: [Number, String],
default: 100
},
chartData: {
type: Array,
default: () => []
},
title: {
type: String,
default: '标题'
}
},
data() {
return {
flag: true,
chart: null
}
},
computed: {
options() {
return {
legend: {
show: false,
bottom: 0,
left: 'center',
orient: 'horizontal',
itemWidth: 8,
itemHeight: 5
},
color: ['#feae42', '#e386ef', '#4771f8','#e64a43'],
series: [
{
name:this.title,
type: 'pie',
radius: ['50%', '70%'],
// center: ['50%', '36%'],
padAngle: 4,
itemStyle: {
borderRadius: 10,
padding: 10
},
label: {
show: true,
position: 'center',
formatter: `${this.title}`
},
avoidLabelOverlap: true, //
emphasis: { //
scale: true // item
},
labelLine: {
show: false
},
data: (() => {
// if (this.percent || this.percent === 0) {
// return [
// { value: parseFloat(this.percent), name: `${this.title}` },
// ]
// } else {
return this.chartData
// }
})()
}
],
graphic: {
elements: []
}
}
}
},
watch: {
chartData() {
this.setOptions()
}
},
mounted() {
this.$nextTick(() => {
this.initChart()
})
},
methods: {
initChart() {
this.chart = echarts.init(this.$el, 'macarons')
this.setOptions()
},
setOptions() {
this.chart?.setOption(this.options)
// this.setGraphics()
},
setGraphics() {
const getPointOnCircle = (angle, radiusPercent) => {
const radian = (angle - 90 - 12) * Math.PI / 180
const radius = this.chart.getWidth() / 2 * radiusPercent / 100
const x = this.chart.getWidth() / 2 + Math.cos(radian) * radius
const y = this.chart.getHeight() / 2 + Math.sin(radian) * radius - this.chart.getHeight() * 0.1
return { x: x, y: y }
}
const graphicElements = []
let total = 0
if (!this.options?.series[0]?.data) return
this.options?.series[0]?.data.forEach(function(item) {
total += item.value
})
let startAngle = 0
this.options?.series[0]?.data.forEach(function(item) {
const angle = (item.value / total) * 360
const endAngle = startAngle + angle
const middleAngle = (startAngle + endAngle) / 2
//
const pointStart = getPointOnCircle(middleAngle - angle / 2, 60)
const pointEnd = getPointOnCircle(middleAngle + angle / 2, 60)
//
graphicElements.push({
type: 'circle',
shape: {
cx: pointStart.x,
cy: pointStart.y,
r: 3
},
style: {
fill: '#fff'
},
z: 100
})
graphicElements.push({
type: 'circle',
shape: {
cx: pointEnd.x,
cy: pointEnd.y,
r: 3
},
style: {
fill: '#fff'
},
z: 100
})
startAngle += angle
})
this.chart.setOption({
graphic: {
elements: graphicElements
}
})
}
}
}
</script>
<style scoped lang="scss">
</style>

@ -52,7 +52,7 @@
</svg>
</div>
</template>
<theme-picker class="tool-item" />
<!-- <theme-picker class="tool-item" /> -->
<!-- <el-badge :is-dot="device === 'mobile'" :max="99" :value="12" class="tool-item">-->
<!-- <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon"><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M10 5a2 2 0 1 1 4 0a7 7 0 0 1 4 6v3a4 4 0 0 0 2 3h-16a4 4 0 0 0 2 -3v-3a7 7 0 0 1 4 -6" /><path d="M9 17v1a3 3 0 0 0 6 0v-1" /></svg>-->
<!-- </el-badge>-->

@ -39,6 +39,7 @@ Vue.use(ElementUI)
// vxetable
import { VxeIcon, VxeTable, VxeColumn, VxeColgroup, VxeTableEditModule, VxeTableValidatorModule, VxeModal, VxeToolbar } from 'vxe-table'
// import vxeTable from 'vxe-table'
import 'vxe-table/styles/index.scss'
Vue.use(VxeTableEditModule)
Vue.use(VxeTableValidatorModule)
@ -48,6 +49,7 @@ Vue.use(VxeColumn)
Vue.use(VxeColgroup)
Vue.use(VxeModal)
Vue.use(VxeToolbar)
// Vue.use(vxeTable)
import domZIndex from 'dom-zindex'
domZIndex.setCurrent(2000)

@ -89,6 +89,18 @@ export const constantRoutes = [
meta: { title: '首页', icon: 'dashboard' }
}]
},
{
path: '/jsc',
component: Layout,
redirect: '/jsc',
meta: { title: '驾驶舱', icon: 'dashboard' },
children: [{
path: 'jsc',
name: 'jsc',
component: () => import('@/views/jsc/jsc'),
meta: { title: '驾驶舱', icon: 'dashboard' }
}]
},
{
path: '/info',
component: Layout,

@ -67,12 +67,14 @@ export default {
computed: {},
created() {
this.$store.dispatch('app/getLayout').then(res => {
this.layoutList = res?.filter(item => layout.find(lay => lay.i === item.i)).map(item => {
layout.forEach(lay => {
lay.i === item.i ? item.component = lay.component : ''
})
return item
}) ?? []
console.log("this.layoutList",this.layoutList,'res',res)
})
},
methods: {

@ -0,0 +1,362 @@
<template>
<el-card class-name="box-card" shadow="hover">
<div slot="header" class="clearfix">
<img style="width: 31px;height:32px" src="../static/icon7.png" alt="">
<span style="padding-left: 15px">总览</span>
<div style="margin-left: auto; font-size: 20px">
<el-select style="width:250px" v-model="department_id" @change="changeDepartment" placeholder="请选择">
<el-option v-for="item in departments" :key="item.id" :label="item.name" :value="item.id">
</el-option>
</el-select>
</div>
</div>
<div v-loading="loading" class="progress-card" element-loading-text=""
element-loading-spinner="el-icon-loading" element-loading-background="rgba(255, 255, 255, 0.8)">
<div class="progress-card-left progress-card-item">
<el-table style="width: 100%;" size="mini" :header-cell-style="{
'font-weight': '600',
'background': '#fff',
'color': '#515a6e',
'text-align':'left'
}" :height="tableHeight" :data="list">
<el-table-column v-for="(item, index) in table" :key="index" :width="item.width" :label="item.title"
:prop="item.key" :show-overflow-tooltip="item['show-overflow-tooltip']" header-align="center"
:align="item.align" :formatter="item.formatter" />
</el-table>
</div>
<div class="progress-card-right progress-card-item">
<div class="progress-card-right-chart">
<MyProgress width="250px" height="250px" :title="myTitle" :chart-data="[{value:progress.chuchai,name:''},{value:progress.jiaban,name:''}
,{value:progress.qingjia,name:'请假'},{value:progress.yongche,name:'用车'}]" />
</div>
<div class="progress-card-right-card">
<div class="progress-card-right-change">
<i class="el-icon-arrow-left" @click="changeDatePara(-1)"></i>
<div>
<i class="el-icon-date"></i>
<span v-if="changeDate==item" v-for="item in changeList">{{item}}</span>
</div>
<i class="el-icon-arrow-right" @click="changeDatePara(1)"></i>
</div>
<div class="progress-card-right-count">
<div>
<span class="chuchai"></span>出差<span>{{progress.chuchai}}</span>
</div>
<div>
<span class="jiaban"></span>加班<span>{{progress.jiaban}}</span>
</div>
<div>
<span class="qingjia"></span>请假<span>{{progress.qingjia}}</span>
</div>
<div>
<span class="yongche"></span>用车<span>{{progress.yongche}}</span>
</div>
<div>
<span></span>单位人次<span></span>
</div>
</div>
<!-- <div v-for="item."></div> -->
</div>
</div>
</div>
</el-card>
</template>
<script>
import ElementResize from 'element-resize-detector'
import {
parseMoney
} from '@/utils'
import SvgIcon from '@/components/SvgIcon/index.vue'
import MyProgress from '@/components/Progress/jscindex.vue'
import axios from 'axios'
import {
getToken
} from '@/utils/auth'
export default {
name: 'All',
components: {
SvgIcon,
MyProgress
},
layout: {
x: 5,
y: 0,
w: 7,
h: 8,
i: 'All',
name: '总览'
},
data() {
return {
loading: false,
departments: [],
myTitle: '今日总览',
progress: {
chuchai: 0,
yongche: 0,
jiaban: 0,
qingjia: 0
},
changeList: ['今日', '明日', '本周', '本月', '本年'],
changeDate: '今日',
changeIndex:0,
tableHeight: 200,
department_id: 0,
list: [],
table: [{
title: '日期',
key: 'name',
align: 'center',
},
{
title: '出差',
key: 'chuchai',
align: 'center',
'show-overflow-tooltip': true,
},
{
title: '用车',
key: 'yongche',
align: 'center',
'show-overflow-tooltip': true,
},
{
title: '加班',
key: 'jiaban',
align: 'center',
'show-overflow-tooltip': true,
},
{
title: '请假',
key: 'qingjia',
align: 'center',
'show-overflow-tooltip': true,
}
]
}
},
created() {},
mounted() {
this.init()
this.getData()
},
methods: {
parseMoney,
init() {
const cardDom = this.$el
const cardTitleH = 69
const elementResize = ElementResize({
strategy: 'scroll'
})
elementResize.listenTo(cardDom, ele => {
this.tableHeight = cardDom.getBoundingClientRect().height - 40 - cardTitleH
})
},
changeDatePara(para){
this.changeIndex = parseInt(this.changeIndex+para)
this.changeDate = this.changeList[this.changeIndex]
if(this.changeIndex<0){
this.changeIndex = this.changeList.length-1
this.changeDate = this.changeList[this.changeIndex]
}
if(this.changeIndex>this.changeList.length-1){
this.changeIndex = 0
this.changeDate = this.changeList[0]
}
console.log("this.changeIndex",this.changeIndex,this.changeDate)
this.list.map(item => {
if (item.name == this.changeDate) {
this.progress = item
}
})
},
changeDepartment(e) {
this.department_id = e
this.departments.map(item => {
if (item.id == e) {
this.myTitle = item.name
}
})
this.getChartOverall()
},
//
async getChartOverall() {
try {
this.loading = true
const res = await axios.get(`${process.env.VUE_APP_BASE_API}/api/oa/chart/overall`, {
headers: {
'Authorization': `Bearer ${getToken()}`
},
params: {
department_id: this.department_id
}
})
if (res.status === 200) {
this.list = res.data?.data
this.list.map(item => {
if (item.name == '今日') {
this.progress = item
}
})
}
this.loading = false
} catch (err) {
this.loading = false
}
},
//
async getDepartment() {
try {
const res = await axios.get(`${process.env.VUE_APP_BASE_API}/api/backend/simple-department`, {
headers: {
'Authorization': `Bearer ${getToken()}`
},
params: {}
})
if (res.status === 200) {
let arr = res.data?.data
this.departments = arr.filter(item => item.name != '中心领导').filter(item => item.name != '公共')
}
} catch (err) {
this.loading = false
}
},
async getData() {
try {
this.loading = true
await this.getDepartment()
this.department_id = this.departments.length > 0 ? this.departments[0].id : ''
this.myTitle = this.departments.length > 0 ? this.departments[0].name : ''
if (this.department_id) {
await this.getChartOverall()
}
this.loading = false
} catch (err) {
this.loading = false
console.error(err)
}
}
}
}
</script>
<style scoped lang="scss">
.clearfix {
display: flex;
align-items: center;
}
::v-deep .el-card__body {
width: 100%;
height: calc(100% - 58px);
}
::v-deep .ivu-table th,
::v-deep .ivu-table td {
border-bottom-style: dashed;
}
.progress-card {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
height: 100%;
&-item {
// min-width: 120px;
width: 50%;
// margin: 10px;
height: 100%;
display: flex;
justify-content: center;
}
&-left {}
&-right {
display: flex;
justify-content: center;
&-chart {
width: 60%;
}
&-card {
width: 40%;
}
&-change {
display: flex;
align-items: center;
font-size: 14px;
width: 100%;
justify-content: center;
margin:20px 0;
&>div{
margin:0 25px;
span{
margin-left:10px;
}
}
}
&-count {
display: flex;
flex-wrap: wrap;
justify-content: center;
&>div {
display: flex;
align-items: center;
span {
display: inline-block;
margin: 10px;
}
&>span:first-child {
width: 14px;
height: 14px;
}
&>span:last-child {
margin-left: 30px
}
.chuchai {
background-color: #feae42;
}
.jiaban {
background-color: #e386ef;
}
.qingjia {
background-color: #4771f8;
}
.yongche {
background-color: #e64a43;
}
}
&>div:last-child {
color: #3b4252;
font-size: 14px;
}
}
}
}
::v-deep .el-progress--circle .el-progress__text {
white-space: break-spaces;
}
</style>

@ -0,0 +1,140 @@
<template>
<el-card id="todo-card" class="box-card" shadow="hover">
<div slot="header" class="clearfix">
<img src="../static/icon6.png" alt="">
<span style="padding-left: 15px">今日车辆去向</span>
<i class="el-icon-more" style="margin-left: auto; font-size: 20px" />
</div>
<div style="position: relative;height: 100%;width: 100%;">
<div style="position: absolute;top: 0;left: 0;right: 0;bottom: 0;">
<el-table style="width: 100%;" size="mini" :header-cell-style="{
'font-weight': '600',
'background': '#fff',
'color': '#515a6e',
'text-align':'left'
}" :height="tableHeight" :data="list">
<el-table-column v-for="(item, index) in table" :key="index" :width="item.width" :label="item.title"
:prop="item.key" :show-overflow-tooltip="item['show-overflow-tooltip']" header-align="center"
:align="item.align" :formatter="item.formatter" />
</el-table>
</div>
</div>
</el-card>
</template>
<script>
import ElementResize from 'element-resize-detector'
import {
defaultModalSize
} from '@/settings'
export default {
name: 'Car',
components: {},
props: {
myData: {
type: Array,
default: () => {
return []
}
}
},
layout: {
x: 0,
y: 12,
w: 5,
h: 7,
i: 'Car',
name: '今日车辆去向',
data_id: 'chucheqingkuang',
data: null
},
data() {
return {
defaultModalSize,
tableHeight: 120,
list: [],
total: 0,
table: [{
title: '车辆',
key: 'chepaihao',
width: 120,
align: 'left',
},
{
title: '驾驶员',
key: 'jiashiyuan',
align: 'left',
'show-overflow-tooltip': true,
width: 100,
},
{
title: '目的地',
key: 'daodadidian',
align: 'left',
'show-overflow-tooltip': true,
minWidth: 200,
},
{
title: '用车时间',
key: 'yongchekaishiriqi',
align: 'left',
'show-overflow-tooltip': true,
width: 140,
}
]
}
},
computed: {},
watch: {
myData(newval) {
console.log('newval', newval)
this.list = newval
},
},
created() {},
beforeDestroy() {},
mounted() {
this.init()
},
methods: {
init() {
const cardDom = document.getElementById('todo-card')
const cardTitleH = 59
const elementResize = ElementResize({
strategy: 'scroll'
})
elementResize.listenTo(cardDom, (ele) => {
this.tableHeight =
cardDom.getBoundingClientRect().height -
40 -
cardTitleH
})
},
}
}
</script>
<style scoped lang="scss">
::v-deep .el-card__body {
width: 100%;
height: calc(100% - 58px);
}
::v-deep .el-table th,
::v-deep .el-table td {
border-bottom-style: dashed;
}
.clearfix {
display: flex;
align-items: center;
}
::v-deep .vxe-modal--content {
padding: 0;
}
</style>

@ -0,0 +1,150 @@
<template>
<el-card id="evection-card" class="box-card" shadow="hover">
<div slot="header" class="clearfix">
<img src="../static/icon5.png" alt="">
<span
style="padding-left: 15px"
>今日出差明细</span>
<i class="el-icon-more" style="margin-left: auto; font-size: 20px" />
</div>
<div style="position: relative;height: 100%;width: 100%;">
<div style="position: absolute;top: 0;left: 0;right: 0;bottom: 0;">
<el-table
style="width: 100%;"
size="mini"
:header-cell-style="{
'font-weight': '600',
'background': '#fff',
'color': '#515a6e',
'text-align':'left'
}"
:height="tableHeight"
:data="list"
>
<el-table-column
v-for="(item, index) in table"
:key="index"
:width="item.width"
:label="item.title"
:prop="item.key"
:show-overflow-tooltip="item['show-overflow-tooltip']"
header-align="center"
:align="item.align"
:formatter="item.formatter"
/>
</el-table>
</div>
</div>
</el-card>
</template>
<script>
import ElementResize from 'element-resize-detector'
import { defaultModalSize } from '@/settings'
export default {
name: 'Evection',
components: {
},
props:{
myData:{
type:Array,
default:()=>{
return []
}
}
},
layout: {
x: 0,
y: 5,
w: 5,
h: 7,
i: 'Evection',
name: '今日出差明细',
data_id:'chuchaiListToday',
data:null
},
data() {
return {
defaultModalSize,
timer: null,
tableHeight: 120,
list: [],
table: [
{
title: '人员',
key: 'flow.creator.name',
width: 120,
align: 'left',
},
{
title: '去向',
key: 'mudidi',
align: 'left',
'show-overflow-tooltip': true,
minWidth: 120
},
{
title: '交通方式',
key: 'jiaotongfangshi',
align: 'left',
'show-overflow-tooltip': true,
minWidth: 120
},
{
title: '出差说明',
key: 'chuchaishiyou',
align: 'left',
'show-overflow-tooltip': true,
}
]
}
},
computed: {},
watch: {
myData(newval){
this.list = newval
},
},
created() {
},
mounted() {
this.init()
},
methods: {
init() {
const cardDom = document.getElementById('evection-card')
const cardTitleH = 59
const elementResize = ElementResize({
strategy: 'scroll'
})
elementResize.listenTo(cardDom, (ele) => {
this.tableHeight =
cardDom.getBoundingClientRect().height -
40 -
cardTitleH
})
},
}
}
</script>
<style scoped lang="scss">
::v-deep .el-card__body {
width: 100%;
height: calc(100% - 58px);
}
::v-deep .el-table th,::v-deep .el-table td {
border-bottom-style: dashed;
}
.clearfix {
display: flex;
align-items: center;
}
::v-deep .vxe-modal--content {
padding: 0;
}
</style>

@ -0,0 +1,146 @@
<template>
<el-card id="level-card" class="box-card" shadow="hover">
<div slot="header" class="clearfix">
<img src="../static/icon8.png" alt="">
<span
style="padding-left: 15px"
>今日请假情况</span>
<i class="el-icon-more" style="margin-left: auto; font-size: 20px" />
</div>
<div style="position: relative;height: 100%;width: 100%;">
<div style="position: absolute;top: 0;left: 0;right: 0;bottom: 0;">
<el-table
style="width: 100%;"
size="mini"
:header-cell-style="{
'font-weight': '600',
'background': '#fff',
'color': '#515a6e',
'text-align':'left'
}"
:height="tableHeight"
:data="list"
>
<el-table-column
v-for="(item, index) in table"
:key="index"
:width="item.width"
:label="item.title"
:prop="item.key"
:show-overflow-tooltip="item['show-overflow-tooltip']"
header-align="center"
:align="item.align"
:formatter="item.formatter"
/>
</el-table>
</div>
</div>
</el-card>
</template>
<script>
import ElementResize from 'element-resize-detector'
import { defaultModalSize } from '@/settings'
export default {
name: 'Level',
components: {
},
props:{
myData:{
type:Array,
default:()=>{
return []
}
}
},
layout: {
x: 5,
y: 8,
w: 3.5,
h: 11,
i: 'Level',
name: '今日请假情况',
data_id:'qingjiaListToday',
data:null
},
data() {
return {
defaultModalSize,
tableHeight: 120,
list: [],
table: [
{
title: '人员',
key: 'flow.creator.name',
width: 100,
align: 'left',
},
{
title: '事由',
key: 'qingjiashiyou',
align: 'left',
'show-overflow-tooltip': true,
minWidth: 200
},
{
title: '时间',
key: 'kaishishijian',
align: 'left',
'show-overflow-tooltip': true,
width: 140,
},
]
}
},
computed: {},
watch: {
myData(newval){
this.list = newval
},
},
created() {
},
beforeDestroy() {
},
mounted() {
this.init()
},
methods: {
init() {
const cardDom = document.getElementById('level-card')
const cardTitleH = 59
const elementResize = ElementResize({
strategy: 'scroll'
})
elementResize.listenTo(cardDom, (ele) => {
this.tableHeight =
cardDom.getBoundingClientRect().height -
40 -
cardTitleH
})
},
}
}
</script>
<style scoped lang="scss">
::v-deep .el-card__body {
width: 100%;
height: calc(100% - 58px);
}
::v-deep .el-table th,::v-deep .el-table td {
border-bottom-style: dashed;
}
.clearfix {
display: flex;
align-items: center;
}
::v-deep .vxe-modal--content {
padding: 0;
}
</style>

@ -0,0 +1,147 @@
<template>
<el-card id="overtime-card" class="box-card" shadow="hover">
<div slot="header" class="clearfix">
<img style="width: 31px;height:32px" src="../static/icon9.png" alt="">
<span
style="padding-left: 15px"
>今日加班情况</span>
<i class="el-icon-more" style="margin-left: auto; font-size: 20px" />
</div>
<div style="position: relative;height: 100%;width: 100%;">
<div style="position: absolute;top: 0;left: 0;right: 0;bottom: 0;">
<el-table
style="width: 100%;"
size="mini"
:header-cell-style="{
'font-weight': '600',
'background': '#fff',
'color': '#515a6e',
'text-align':'left'
}"
:height="tableHeight"
:data="list"
>
<el-table-column
v-for="(item, index) in table"
:key="index"
:width="item.width"
:label="item.title"
:prop="item.key"
:show-overflow-tooltip="item['show-overflow-tooltip']"
header-align="center"
:align="item.align"
:formatter="item.formatter"
/>
</el-table>
</div>
</div>
</el-card>
</template>
<script>
import ElementResize from 'element-resize-detector'
import { defaultModalSize } from '@/settings'
export default {
name: 'Overtime',
components: {
},
props: {
myData: {
type: Array,
default: () => {
return []
}
}
},
layout: {
x: 8.5,
y: 8,
w: 3.5,
h: 11,
i: 'Overtime',
name: '今日加班情况',
data_id:'jiabanListToday',
data:null
},
data() {
return {
defaultModalSize,
tableHeight: 120,
list: [],
total: 0,
table: [
{
title: '人员',
key: 'flow.creator.name',
width: 100,
align: 'left',
},
{
title: '原因',
key: 'yuanyinshuoming',
align: 'left',
'show-overflow-tooltip': true,
minWidth: 200
},
{
title: '时间',
key: 'kaishiriqi',
align: 'left',
'show-overflow-tooltip': true,
width: 140
}
]
}
},
computed: {},
watch: {
myData(newval) {
console.log('newval', newval)
this.list = newval
},
},
created() {
},
beforeDestroy() {
},
mounted() {
this.init()
},
methods: {
init() {
const cardDom = document.getElementById('overtime-card')
const cardTitleH = 59
const elementResize = ElementResize({
strategy: 'scroll'
})
elementResize.listenTo(cardDom, (ele) => {
this.tableHeight =
cardDom.getBoundingClientRect().height -
40 -
cardTitleH
})
},
}
}
</script>
<style scoped lang="scss">
::v-deep .el-card__body {
width: 100%;
height: calc(100% - 58px);
}
::v-deep .el-table th,::v-deep .el-table td {
border-bottom-style: dashed;
}
.clearfix {
display: flex;
align-items: center;
}
::v-deep .vxe-modal--content {
padding: 0;
}
</style>

@ -0,0 +1,153 @@
<template>
<el-card class-name="box-card" shadow="hover">
<div class="progress-card">
<div class="progress-card-item" v-for="item in totalList">
<div class="worker-progress__icon">
<img :src="item.icon" alt="">
</div>
<div class="progress-card-item__num">{{ item.total }}</div>
<div class="progress-card-item__label">{{item.name}}</div>
</div>
</div>
</el-card>
</template>
<script>
import ElementResize from 'element-resize-detector'
export default {
name: 'Total',
components: {
},
props:{
myData:{
type:Object,
default:()=>{
return {
level:0,
normal:0,
chuchai:0
}
}
}
},
layout: {
x: 0,
y: 0,
w: 5,
h: 5,
i: 'Total',
name: '当日情况',
data_id:'attendance',
data:null
},
data() {
return {
totalList: [{
icon: require('../static/icon1.png'),
total: 0,
name: '当日在岗',
id:'normal'
},{
icon: require('../static/icon2.png'),
total: 0,
name: '当日请假',
id:'leave'
},{
icon: require('../static/icon3.png'),
total: 0,
name: '当日出差',
id:'chuchai'
}
// ,{
// icon: require('../static/icon4.png'),
// total: 0,
// name: ''
// }
],
tableHeight: 200
}
},
created() {},
mounted() {
},
watch:{
myData(newval){
this.totalList.map(item=>{
item.total = newval[item.id]
})
},
},
methods: {
init() {
const cardDom = this.$el
const cardTitleH = 69
const elementResize = ElementResize({
strategy: 'scroll'
})
elementResize.listenTo(cardDom, ele => {
this.tableHeight = cardDom.getBoundingClientRect().height - 40 - cardTitleH
})
},
}
}
</script>
<style scoped lang="scss">
.clearfix {
display: flex;
align-items: center;
}
::v-deep .el-card__body {
width: 100%;
height: calc(100% - 58px);
}
::v-deep .ivu-table th,
::v-deep .ivu-table td {
border-bottom-style: dashed;
}
.progress-card {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
&-item {
min-width: 120px;
margin: 10px;
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
&__label {
font-size: 15px;
color: #000000;
padding-top: 20px;
}
&__num {
font-size: 20px;
line-height: 7px;
color: #000000;
font-weight: bold;
padding-top: 18px;
}
.worker-progress__icon {
border-radius: 20px;
display: flex;
align-items: center;
justify-content: center;
width: 92px;
height: 92px;
}
}
}
::v-deep .el-progress--circle .el-progress__text {
white-space: break-spaces;
}
</style>

@ -0,0 +1,124 @@
<template>
<div v-loading="loading" class="progress-card" element-loading-text=""
element-loading-spinner="el-icon-loading" element-loading-background="rgba(255, 255, 255, 0.8)">
<grid-layout id="grid-card" class="gird-card" :layout.sync="layoutList" :col-num="12" :row-height="40"
:is-draggable="false" :is-resizable="false" :is-mirrored="false" :vertical-compact="true" :margin="[10, 10]"
:auto-size="true" :use-css-transforms="true">
<grid-item v-for="item in layoutList" :key="item.i" :x="item.x" :y="item.y" :w="item.w" :h="item.h" :i="item.i"
style="touch-action: none">
<component :is="item.component" style="position: absolute; inset: 0 0 0 0" :myData="item.data"
@send-data="sendData" />
</grid-item>
</grid-layout>
</div>
</template>
<script>
import VueGridLayout from 'vue-grid-layout'
import request from '@/utils/request'
import {
getToken
} from '@/utils/auth'
import axios from 'axios'
const files = require.context(
'@/views/jsc/components',
false,
/.vue$/
)
const cpns = files.keys().map((key) => {
return files(key).default || files(key)
})
const layout = cpns.filter(item => !item.layout.disabled).map((item) => {
return {
...item.layout,
component: item
}
})
export default {
components: {
'GridLayout': VueGridLayout.GridLayout,
'GridItem': VueGridLayout.GridItem
},
data() {
return {
loading: true,
layoutList: [],
data: {
statistic: {}
}
}
},
computed: {},
created() {
this.layoutList = layout.map(item => {
layout.forEach(lay => {
lay.i === item.i ? item.component = lay.component : ''
})
return item
}) ?? []
console.log("this.", this.layoutList)
this.getChartToday()
},
methods: {
sendData(data) {
this.data.statistic = data
},
//
async getChartToday(loading = false) {
try {
if (loading) {
this.loading = true
}
const res = await axios.get(`${process.env.VUE_APP_BASE_API}/api/oa/chart/today`, {
headers: {
'Authorization': `Bearer ${getToken()}`
},
params: {
}
})
console.log("res", res)
if (res.status === 200) {
let list = res.data?.data
this.layoutList.map(item => {
//
if(item.data_id=='chucheqingkuang'){
let carList = []
let arr = list['chuchaiListToday']
arr.map(a=>{
if(a.chucheqingkuang){
carList.push(...JSON.parse(a.chucheqingkuang))
}
})
item['data'] = carList
}else{
item['data'] = list[item.data_id]
}
})
}
console.log("this.layoutList", this.layoutList)
this.loading = false
} catch (err) {
console.error(err)
this.loading = false
}
},
}
}
</script>
<style scoped lang="scss">
@media (max-width: 768px) {
::v-deep .vue-grid-item {
width: 100% !important;
position: relative !important;
transform: none !important;
margin-bottom: 10px;
touch-action: auto !important;
}
//#grid-card {
// overflow-y: scroll;
//}
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 643 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 626 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 753 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 755 B

Loading…
Cancel
Save