2025-02-25 16:24:44 +08:00

878 lines
37 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div>
<!-- <el-scrollbar :style="'height:'+`${contentHeight}`+'px'"> -->
<div class="layout-content-wrap flex-column">
<div class="work-hello">
<span>你好{{userInfo.realName || userInfo.showName ||'-'}}</span>
</div>
<div class="flex-row justify-content-between work-main p-16">
<div class="flex-column ">
<div class="border-radius-4 flex-column casework1">
<div class="flex-row justify-content-between case-title">
<span>案件进展情况</span>
<span>
<el-select v-model="queryParamJZ.id"
placeholder="请选择案件包"
class="width100" size="mini" @change="progressChange">
<el-option
v-for="item in casePkOptions"
:key="item.id"
:label="item.pkgName"
:value="item.id">
</el-option>
</el-select>
</span>
</div>
<div class="p-16 case-progress-cont">
<div class="case-progress">
<span class="case-pro1">
<p>案件总量</p>
<p><a>{{caseprogressObj.caseTotal}}</a></p>
<img src="../../assets/image/workbench/progress1.png">
</span>
<span class="case-pro2">
<p>案件待分</p>
<p><a>{{caseprogressObj.unassignTotal}}</a></p>
<img src="../../assets/image/workbench/progress8.png">
</span>
<span class="case-pro3">
<p>未触达</p>
<p><a>{{caseprogressObj.notReachTotal}}</a></p>
<img src="../../assets/image/workbench/progress3.png">
</span>
<span class="case-pro4">
<p>调解中</p>
<p><a>{{caseprogressObj.mediatingTotal}}</a></p>
<img src="../../assets/image/workbench/progress2.png">
</span>
<span class="case-pro5">
<p>调解成功</p>
<p><a>{{caseprogressObj.mediateSuccess}}</a></p>
<img src="../../assets/image/workbench/progress5.png">
</span>
<span class="case-pro6">
<p>已签署协议</p>
<p><a>{{caseprogressObj.signTotal}}</a></p>
<img src="../../assets/image/workbench/progress6.png">
</span>
<span class="case-pro7">
<p>已司法确认</p>
<p><a>{{caseprogressObj.judicialTotal}}</a></p>
<img src="../../assets/image/workbench/progress4.png">
</span>
<span class="case-pro8">
<p>已赋强公证</p>
<p><a>{{caseprogressObj.notarizationTotal}}</a></p>
<img src="../../assets/image/workbench/progress7.png">
</span>
</div>
</div>
</div>
<div class="flex-column casework-1 p-16">
<div class="flex-row justify-content-between case-pk-title">
<span class="f18 f-weight500">办案量排行榜</span>
</div>
<div class="case-pk-cont flex-column">
<div id="echartsCaserank" style="width: 370px; height: 285px; ">
</div>
</div>
</div>
</div>
<div class="casework2">
<div class="border-radius-4 flex-column casework2-1">
<div class="flex-row justify-content-between case-pk-title">
<span>待办案件包</span>
<div class="flex-row">
<span>
<el-select v-model="queryParamFP.pkgName"
clearable placeholder="请选择案件包"
@change="handleSearch()"
class="width100" size="mini">
<el-option
v-for="item in casePkOptions"
:key="item.pkgName"
:label="item.pkgName"
:value="item.pkgName">
</el-option>
</el-select>
</span>
<span class="case-pk-btn ml-16" @click="handleImport"><i class="el-icon-upload2"></i>批量导入</span>
<!-- <span class="case-pk-btn"><i class="el-icon-plus"></i>添加案件</span> -->
</div>
</div>
<div class="case-pk-cont flex-column">
<el-scrollbar :style="'height:'+`${leftContentHeight}`+'px'">
<div v-for="(item,index) in tableData" :key="index" class="case-pk-list">
<div class="flex-row justify-content-between mb-8">
<span class="f20 f-weight500">{{item.pkgName}}</span>
<span class="cursor-pointer" @click="jumpUrl(`/case-management?dataKey=casepack&pkgName=${item.pkgName}`)">查看详情&nbsp;></span>
</div>
<div class="flex-row mb-16">
<span>{{item.entrustingAgencyName}}</span>
<span class="ml-16">委案日期{{item.planStartTime | formaDate('yyyy-MM-dd')}}</span>
</div>
<div class="flex-row justify-content-between case-pk-num mb-16">
<span>
<p><a>{{item.caseTotal}}</a></p>
案件总量
</span>
<span>
<p><a>{{item.assignTotal}}</a></p>
已分案件数
</span>
<span>
<p><a>{{item.caseTotal - item.assignTotal}}</a></p>
待分案件数
</span>
<span>
<p><a>{{item.months}}</a>个月</p>
委案期限
</span>
</div>
<div class="flex-row justify-content-end mb-8">
<el-button size="mini" type="primary" @click="handleCaseAllocation(item)">案件分配</el-button>
<!-- <el-button size="mini" @click="handleEdit(scope)">预设还款方案</el-button> -->
</div>
</div>
</el-scrollbar>
</div>
</div>
<div class="border-radius-4 flex-column casework2-2 p-16">
<div class="flex-row justify-content-between case-pk-title">
<span class="f18 f-weight500">预约回款情况</span>
</div>
<div class="case-pk-cont flex-column">
<div id="echartsCaserefund" style="width: 100%; height: 285px; ">
</div>
</div>
</div>
</div>
<div class="border-radius-4 flex-column casework3">
<div class="flex-column item-trace">
<div class="flex-row justify-content-between case-pk-title">
<span>事项追踪</span>
</div>
<div class="case-pk-cont">
<div class="flex-row justify-content-between cursor-pointer" @click="eventTraDialog={traceType:0,title:'发送短信追踪'}">
<span><i class="el-icon-message f16 mr-4"></i>发送短信</span><span><a>{{traceData.smsTrackingCount.failed ? traceData.smsTrackingCount.failed :'0'}}</a>/<a>{{traceData.smsTrackingCount.total}}</a></span>
</div>
<div class="flex-row justify-content-between cursor-pointer" @click="eventTraDialog={traceType:1,title:'智能电话外呼追踪'}">
<span><i class="el-icon-service f16 mr-4"></i>智能电话外呼</span><span><a>{{traceData.intelligentCallTrackingCount.failed ? traceData.intelligentCallTrackingCount.failed :'0'}}</a>/<a>{{traceData.intelligentCallTrackingCount.total}}</a></span>
</div>
<div class="flex-row justify-content-between cursor-pointer" @click="eventTraDialog={traceType:2,title:'在线视频调解追踪'}">
<span><i class="el-icon-video-camera f16 mr-4"></i>在线视频调解</span><span><a>{{traceData.videoAppointmentTrackingCount.failed ? traceData.videoAppointmentTrackingCount.failed :'0'}}</a>/<a>{{traceData.videoAppointmentTrackingCount.total}}</a></span>
</div>
<div class="flex-row justify-content-between cursor-pointer" @click="eventTraDialog={traceType:3,title:'文书生成追踪'}">
<span><i class="el-icon-document-checked f16 mr-4"></i>文书生成</span><span><a>{{traceData.documentGenerationTrackingCount.failed ? traceData.documentGenerationTrackingCount.failed :'0'}}</a>/<a>{{traceData.documentGenerationTrackingCount.total}}</a></span>
</div>
<div class="flex-row justify-content-between cursor-pointer" @click="eventTraDialog={traceType:4,title:'文书签字追踪'}">
<span><i class="el-icon-reading f16 mr-4"></i>文书签字</span><span><a>{{traceData.documentSignatureTrackingCount.failed ? traceData.documentSignatureTrackingCount.failed :'0'}}</a>/<a>{{traceData.documentSignatureTrackingCount.total}}</a></span>
</div>
<div class="flex-row justify-content-between cursor-pointer" @click="eventTraDialog={traceType:5,title:'协议文书签章追踪'}">
<span><i class="el-icon-coordinate f16 mr-4"></i>协议文书签章</span><span><a>{{traceData.electronicSealTrackingCount.failed ? traceData.electronicSealTrackingCount.failed :'0'}}</a>/<a>{{traceData.electronicSealTrackingCount.total}}</a></span>
</div>
<div class="flex-row justify-content-between cursor-pointer" @click="eventTraDialog={traceType:6,title:'文书送达追踪'}">
<span><i class="el-icon-mobile-phone f16 mr-4"></i>文书送达</span><span><a>{{traceData.documentDeliveryTrackingCount.failed ? traceData.documentDeliveryTrackingCount.failed :'0'}}</a>/<a>{{traceData.documentDeliveryTrackingCount.total}}</a></span>
</div>
<div class="flex-row justify-content-between cursor-pointer" @click="eventTraDialog={traceType:7,title:'还款凭证登记'}">
<span><i class="el-icon-school f16 mr-4"></i>还款凭证登记</span><span><a>{{traceData.repaymentRecordTrackingCount.failed ? traceData.repaymentRecordTrackingCount.failed :'0'}}</a>/<a>{{traceData.repaymentRecordTrackingCount.total}}</a></span>
</div>
</div>
</div>
<div class="flex-column pie-chart">
<div class="flex-row justify-content-between case-pk-title">
<span>调解成功率</span>
<div class="flex-row">
<span>
<el-select v-model="queryParamCGL.id"
placeholder="请选择案件包"
class="width100" size="mini" @change="SuccessRateChange">
<el-option
v-for="item in casePkOptions"
:key="item.id"
:label="item.pkgName"
:value="item.id">
</el-option>
</el-select>
</span>
</div>
</div>
<div class="case-pk-cont flex-column">
<div>
<div id="echartsSankey" style="width: 370px; height: 216px; margin-left: 10px">
</div>
<span class="resultplan" v-if="mediation_success_rate.caseTotal > 0 ">{{ (mediation_success_rate.mediateSuccess/mediation_success_rate.caseTotal).toFixed(2) }} %</span>
<span class="resultplan" v-else>0 %</span>
</div>
<div class="flex-row justify-content-between">
<span class="flex-column align-items-center color-86909C"><a class="color-000 f16">{{mediation_success_rate.caseTotal}}</a><a>总案件数</a></span>
<span class="flex-column align-items-center color-86909C"><a class="color-000 f16">{{mediation_success_rate.mediateSuccess}}</a><a>调解成功</a></span>
<span class="flex-column align-items-center color-86909C"><a class="color-000 f16">{{mediation_success_rate.mediateFail}}</a><a>调解失败</a></span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- </el-scrollbar> -->
<!-- 导入 -->
<importPackageDialog v-if="importCaseDialog" :importCaseDialog.sync="importCaseDialog" />
<!-- 案件分配-->
<caseAllocationDialog v-if="caseAllocationDialog" :caseAllocationDialog.sync="caseAllocationDialog" />
<!-- 事项追踪 -->
<eventTracingDialog v-if="eventTraDialog" :eventTraDialog.sync="eventTraDialog" />
</div>
</template>
<script>
import api from "@/services/caseManagement";
import workApi from "@/services/workbenchApi";
import pkapi from "@/services/casePackageManagement";
import { color } from "echarts";
export default {
components: {
importPackageDialog: () => import('../case-package/components/importPackageDialog'),//导入
caseAllocationDialog: () => import('../case-package/components/caseAllocationDialog'),//案件分配
eventTracingDialog: () => import('../event-tracing/index.vue'),//事项追踪
},
data() {
return {
userInfo:{},
eventTraDialog:null,//事项追踪
casePkOptions:[],//案件包
queryParamJZ: {
pkgName:'',//案件包名称
id:'',
allCase:true
},
caseprogressObj:{},
queryParamFP: {
pkgName:'',//案件包名称
id:'',
},
queryParamCGL: {
pkgName:'',//案件包名称
id:'',
},
identifier:this.$store.state.userinfo.identifier,
detailDrawer:null,
editCaseDrawer:null,//编辑
tableData: [],
caseAllocationDialog:null,//案件分配弹框
importCaseDialog:null,//导入
myEcharts: null,
traceData:{
"smsTrackingCount": {
"total": 0,
"failed": 0
},
"intelligentCallTrackingCount": {
"total": 0,
"failed": 0
},
"repaymentRecordTrackingCount": {
"total": 0,
"failed": 0
},
"documentSignatureTrackingCount": {
"total": 1,
"failed": 0
},
"documentDeliveryTrackingCount": {
"total": 0,
"failed": 0
},
"electronicSealTrackingCount": {
"total": 0,
"failed": 0
},
"documentGenerationTrackingCount": {
"total": 0,
"failed": 0
},
"videoAppointmentTrackingCount": {
"total": 0,
"failed": 0
}
},
mediation_success_rate:{caseTotal:0,mediateSuccess:0,mediateFail:0},
};
},
watch: {
},
computed:{
// 获取抽屉drawer的内容高度
contentHeight(){
let oh = document.documentElement.clientHeight;
return oh-66
},
// 获取抽屉drawer的内容高度
leftContentHeight(){
// let oh = document.documentElement.clientHeight;
// if(oh > 971){oh = 971}
return 510
}
},
mounted(){
if(JSON.parse(sessionStorage.getItem('userInfo'))){
this.userInfo = JSON.parse(sessionStorage.getItem('userInfo'))
// 判断当前登录人角色,如果是普通调解员,则默认展示区域且不可选择
let identifier = this.$store.state.userinfo
console.log(identifier,'identifier')
if(identifier=='mediator'){
this.deptDisabled = true
this.queryParam.deptId = this.$store.state.userinfo.deptId
}else{
this.deptDisabled = false
}
}
this.getCaseapkList()
this.getCaseInfoList()
// this.getstatisticcases()
this.getstatistic_trace()
this.CaseloadrankCharts()
this.CaserefundCharts()
},
methods: {
jumpUrl (url) {
this.$router.push(url);
},
// 待办
handleSearch(){
this.getCaseInfoList();
},
progressChange(){
this.getCaseapkStatistics()
},
// 案件进展情况
getCaseapkStatistics(){
workApi.getmy_case_pkg_statistics({id:this.queryParamJZ.id,allCase:true}).then(res => {
if (!res.code) {
this.caseprogressObj = res;
}
})
},
// 所有案件包数据
getCaseapkList(type =1){
workApi.getmy_case_pkg({size:100,current:1}).then(res => {
if (!res.code) {
this.casePkOptions = res;
if(this.casePkOptions.length > 0 )
{
this.queryParamJZ.id = this.casePkOptions[0].id
this.queryParamCGL.id = this.casePkOptions[0].id
}
}
if(type == 1)
{
this.getCaseapkStatistics()
this.drawCharts()
}
})
},
// 列表数据
getCaseInfoList(val){
console.log(val,'getCaseInfoListgetCaseInfoListgetCaseInfoList')
if(val == 1){
this.getCaseapkList(2)
}
pkapi.getCasePkgQuery({current:1,size:100,pkgName:this.queryParamFP.pkgName}).then(res => {
if (!res.code) {
this.tableData = res.records;
}
})
},
// 待办汇总
getstatisticcases(){
workApi.statistic_cases({current:1,size:100}).then(res => {
if (!res.code) {
this.tableData = res.records;
}
})
},
// 追踪汇总
getstatistic_trace(){
workApi.statistic_trace({current:1,size:100}).then(res => {
if (!res.code) {
this.traceData = res;
}
})
},
// 导入
handleImport(){
this.importCaseDialog={
title:'批量导入案件',
}
},
// 案件分配
handleCaseAllocation(row){
if((row.caseTotal - row.assignTotal) <= 0)
{
this.$message({
showClose: true,
message: '该案件包没有待分配的案件!',
type: 'warning'
});
return false
}
this.caseAllocationDialog={
title:'案件分配',
ObjectInfo:row
}
},
SuccessRateChange(){
this.drawCharts()
},
// 结果统计图
async drawCharts () {
this.mediation_success_rate = await workApi.getmy_case_pkg_statistics({id:this.queryParamCGL.id,allCase:true})
if (this.myEcharts) {
this.myEcharts.clear();
}
this.myEcharts = this.$echarts.init(
document.getElementById("echartsSankey")
);
let _that = this;
var option = {
tooltip: {
trigger: "item",
axisPointer: {
type: "shadow",
},
textStyle: {
fontSize: 22,
},
},
legend: {
top: "5%",
left: "center",
show: false, //取消显示图例
},
series: [
{
type: 'pie',
radius: ['60%', '85%'],
avoidLabelOverlap: false,
label: {
show: false,
position: 'center'
},
emphasis: {
label: {
show: false, //hover圆环中的列子
fontSize: 40,
fontWeight: 'bold'
}
},
labelLine: {
show: false
},
data: [
{ value: this.mediation_success_rate.mediateFail, name: '调解失败',itemStyle:{color:'#a7e054'} },
{ value: this.mediation_success_rate.mediateSuccess, name: '调解成功' ,itemStyle:{color:'#bee18adb'}},
]
}
]
};
_that.myEcharts.setOption(option, true);
},
// 办案量排行榜
async CaseloadrankCharts () {
let operateMethodOptions=[]
await api.getCurrGroupUserList().then(res => {
if (!res.code) {
res.forEach(element => {
operateMethodOptions.push(element.realName)
});
}
})
let case_rank_rate = [0,0,0,0,0,0,0]
if (this.myEchartsCaseRank) {
this.myEchartsCaseRank.clear();
}
this.myEchartsCaseRank = this.$echarts.init(
document.getElementById("echartsCaserank")
);
let _that = this;
var option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
legend: {
show: false, //取消显示图例
},
grid: {
top:'5%',
left: '1%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'value',
boundaryGap: [0, 1]
},
yAxis: {
type: 'category',
data: operateMethodOptions,
},
series: [
{
itemStyle: {
color: '#FBA440'
},
type: 'bar',
data: case_rank_rate
}
]
};
_that.myEchartsCaseRank.setOption(option, true);
},
// 预约回款情况
async CaserefundCharts () {
let case_rank_rate = [0,0,0,0,0,0,0]
if (this.myEchartsCaseRefund) {
this.myEchartsCaseRefund.clear();
}
this.myEchartsCaseRefund = this.$echarts.init(
document.getElementById("echartsCaserefund")
);
let _that = this;
var option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
xAxis: {
type: 'category',
data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']
},
yAxis: {
type: 'value'
},
grid: {
left: '2%',
right: '2%',
bottom: '3%',
containLabel: true
},
legend: {},
series: [
{
data: [120, 200, 150, 80, 70, 110, 130],
type: 'bar',
name:'预约回款金额',
color:'#FBA440'
},
{
data: [120, 200, 150, 80, 70, 110, 130],
type: 'bar',
name:'回款金额',
color:'#4091FB'
}
]
};
_that.myEchartsCaseRefund.setOption(option, true);
},
},
};
</script>
<style scoped lang="scss">
.work-hello{
background:url(../../assets/image/workbench/work-bg.png) no-repeat;
background-size: 100% 100%;
height: 96px;
padding: 25px 0 0 40px;
span{font-size:28px;color: #4E5969;}
}
.work-main{
height: 971px;
background-color: #f6f4f4;
border-radius: 15px;
margin-top: -10px;
}
.casework1{
background:url(../../assets/image/workbench/work-left-bg.png) no-repeat;
background-size: 100% 100%;
// min-height:496px;
width: 412px;
padding: 20px;
.case-title{
height: 50px;
font-size: 18px;
color:#1D2129;
font-weight: 500;
}
.case-progress-cont{
background-color: #fff;
border-radius: 5px;
font-size: 18px;
}
.case-progress{
// background:url(../../assets/image/workbench/icon-bg.png) no-repeat;
background-size: 100% 100%;
height: 460px;
margin: auto;
color: #fff;
span{
padding: 15px 0 0px 15px;
width: 153px;
height: 105px;
display: inline-block;
margin-bottom: 13px;
line-height: 30px;
}
span:nth-child(even){
margin-left: 20px;
}
span p{padding: 0;margin: 0;}
span a{color: #fff;font-size: 22px;padding-left: 20px;}
.case-pro1,.case-pro2,.case-pro3,.case-pro4,.case-pro5,.case-pro6,
.case-pro7,.case-pro8
{
width: 157px;height: 105px;
position: relative;
border-radius: 8px;
img{
width:50px ;
right:10px;
position:absolute;
}
}
.case-pro1
{
background-image: linear-gradient(to right,#0fdfdc,pink)
}
.case-pro2
{
background-image: linear-gradient(to right,pink,#ffd900)
}
.case-pro3
{
background-image: linear-gradient(to right,#ffd900,#ff0000cb)
}
.case-pro4
{
background-image: linear-gradient(to right,#ff0000cb,#59a8ff)
}
.case-pro5
{
background-image: linear-gradient(to right,#59a8ff,#b0d65e)
}
.case-pro6
{
background-image: linear-gradient(to right,#b0d65e,#dbf41e)
}
.case-pro7
{
background-image: linear-gradient(to right,#dbf41e,#df5964a7)
}
.case-pro8
{
background-image: linear-gradient(to right,#df5964a7,#df313fc2)
}
}
}
.casework-1{
background-color: #ec9dd82b;
border-radius: 8px;
margin-top: 15px;
}
.casework2{
width: calc(100% - 850px);
.casework2-1{
background-color: #dbedf7;
height:578px;
margin:4px 0 0 0;
padding: 18px;
color: #4E5969;
.case-pk-title{
span:first-child{
font-size: 18px;
color:#1D2129;
font-weight: 500;
}
.case-pk-btn{
width: 90px;
font-size: 14px;
text-align: center;
line-height: 30px;
display: inline-block;
cursor: pointer;
}
}
.case-pk-cont{
.case-pk-list{
background-color: #fff;
padding: 16px;
border-radius: 8px;
margin-top: 20px;
.case-pk-num{
background-color: #F7F8FA;
height:85px ;
padding-top: 20px;
span{
width: 25%;
text-align: center;
border-right: solid 2px #e5e6e8;
height: 45px;
p{margin: 0;
a{
font-size: 22px;
}
}
}
span:last-child{border-right: 0;}
}
}
}
}
.casework2-2{
background-color: #e2eb5321;
border-radius: 8px;
margin-top: 15px;
}
}
.casework3{
min-height:496px;
width: 400px;
margin:4px 0 0 0;
color: #4E5969;
font-size: 16px;
.pie-chart{
margin-top: 18px;
padding: 18px;
background-color: #ef806d42;
border-radius: 8px;
.case-pk-title{
span:first-child{
font-size: 18px;
color:#1D2129;
font-weight: 500;
}
}
.case-pk-cont{
padding: 10px 0 10px 0;
position: relative;
.resultplan{
font-size: 32px;
position: absolute;
left: 115px;
top: 100px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 165px;
text-align: center;
}
}
}
.item-trace{
padding: 14px 18px;
height:575px ;
background-color: #d1f1dc4f;
border-radius: 8px;
.case-pk-title{
span:first-child{
font-size: 18px;
color:#1D2129;
font-weight: 500;
}
}
.case-pk-cont{
padding: 10px 0 0px 0;
position: relative;
.resultplan{
font-size: 32px;
position: absolute;
left: 115px;
top: 130px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 165px;
text-align: center;
}
div{
margin-top:10px;
margin-bottom:15px;
color: #4E5969;
background-color:#F7F8FA ;
padding: 14px 12px;
border-radius: 2px;
a{
font-weight: 600;
}
a:first-child{
color: #E8535A;
}
span i{color: red;}
}
}
}
}
.casework4{
background: linear-gradient(101.33deg, #0FBEAF 0.46%, #079D87 100%);
box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.12), 0px 4px 4px rgba(0, 0, 0, 0.04);
position: relative;
}
.caseworkicon1{background: linear-gradient(165.96deg, #FFFFFF 0%, rgba(255, 255, 255, 0) 100%);
opacity: 0.1;width: 80px;
}
.casework1 img,.casework2 img,.casework3 img,.casework4 img{position: absolute;right:25px;top:45px}
</style>