/*
|
* @Company: hugeInfo
|
* @Author: ldh
|
* @Date: 2022-03-18 14:36:38
|
* @LastEditTime: 2024-01-23 16:01:41
|
* @LastEditors: lwh
|
* @Version: 1.0.0
|
* @Description: 调解视窗
|
*/
|
import React, { useState, useEffect } from 'react';
|
import { useSearchParams, useNavigate } from 'react-router-dom';
|
import { Tooltip, Popconfirm, Space, Popover, Descriptions, Typography, Button } from 'antd';
|
import { LeftOutlined, QrcodeOutlined, CloseCircleOutlined, ProfileOutlined, CheckCircleFilled } from '@ant-design/icons';
|
import * as $$ from '../../utils/utility';
|
import timer from '../../utils/timer';
|
import { ConcludeContent, MediateDynamic, MediationNav1, MediationNav, ActionModal } from './component';
|
import Page from '../../components/Page';
|
import NameCard from '../../components/NameCard';
|
import FilesDrawer from '../../components/FilesDrawer';
|
import {
|
documentMaking,
|
documentMaking_active,
|
supplementaryMaterials,
|
supplementaryMaterials_active,
|
mediationSetting,
|
mediationSetting_active,
|
mediationMsg,
|
mediationMsg_active,
|
startMediation,
|
funnel,
|
clock,
|
clock_active,
|
camera,
|
End,
|
promptArrow,
|
} from '../../assets/images/icon';
|
import MyModal from '../../components/MyModal';
|
|
const { Text } = Typography;
|
// hh的兼容性修改0419
|
//推荐接口
|
// function getDataApi(submitData) {
|
// return $$.ax.request({ url: `guide/windowCaseGuideByDb`, type: 'get', data: submitData, service: 'mediate' });
|
// }
|
function getDataApi(submitData) {
|
return $$.ax.request({ url: `guide/windowCaseGuideByMilvus`, type: 'get', data: submitData, service: 'mediate' });
|
}
|
|
function cacheOpenAiCaseGuideListApi(submitData) {
|
return $$.ax.request({ url: `guide/cacheOpenAiCaseGuideList`, type: 'get', data: submitData, service: 'mediate' });
|
}
|
|
// 类案推荐缓存接口
|
function cacheLatjCaseGuideApi(submitData) {
|
return $$.ax.request({ url: `guide/cacheLatjCaseGuide`, type: 'get', data: submitData, service: 'mediate' });
|
}
|
|
// 案件特征缓存接口
|
function cacheCaseFeatureApi(submitData) {
|
return $$.ax.request({ url: `guide/cacheCaseFeature`, type: 'get', data: submitData, service: 'mediate' });
|
}
|
|
// 获取纠纷信息 和 已达成内容
|
function getDisputeDataApi(submitData) {
|
return $$.ax.request({ url: `caseInfo/pcWindowCaseInfo?id=${submitData}`, type: 'get', service: 'mediate' });
|
}
|
|
// 获取任务信息
|
function getTaskInfoApi(taskId) {
|
return $$.ax.request({ url: 'caseTask/getTaskInfo?taskId=' + taskId, type: 'get', service: 'mediate' });
|
}
|
|
// 计划内开始时间与结束时间之内则立即开始调解
|
function startMediationApi(submitData) {
|
return $$.ax.request({ url: `caseInfo/pcWindowStartMediate`, type: 'post', service: 'mediate', data: submitData });
|
}
|
|
const MediationWindow = () => {
|
const [searchParams] = useSearchParams();
|
|
const navigate = useNavigate();
|
|
const back = searchParams.get('back');
|
|
const caseId = searchParams.get('caseId');
|
|
const taskId = searchParams.get('taskId');
|
|
// 当有值时=='2',则判断为退回案件,则打开任务信息modal
|
const taskType = searchParams.get('taskType');
|
|
// 类案推荐数据
|
const [data, setData] = useState([])
|
|
// 纠纷案件数据
|
const [disputeData, setDisputeData] = useState({});
|
|
// 调解开始时间
|
const [mediateStartTime, setMediateStartTime] = useState();
|
|
// 预约时间提醒
|
const [orderVisible, setOrderVisible] = useState(false);
|
|
// 语音转文字是否开启
|
const [voiceVisible, setVoiceVisible] = useState(false);
|
|
// 任务信息是否查看
|
const [task, setTask] = useState({ visible: false });
|
|
// 操作modal
|
const [modal, setModal] = useState({ visible: null });
|
|
// 调解开始提示显示
|
const [successVisible, setSuccessVisible] = useState(false);
|
|
// 底部操作数据
|
const operation = [
|
{ icon: documentMaking, iconActive: documentMaking_active, title: '文书制作', actionType: 'documentMaking' },
|
{ icon: mediationMsg, iconActive: mediationMsg_active, title: '案件信息', actionType: 'caseCheck' },
|
{ icon: startMediation, iconActive: funnel, title: '开始调解', actionType: 'mediationStart' },
|
{ icon: supplementaryMaterials, iconActive: supplementaryMaterials_active, title: '补充材料', actionType: 'caseChange' },
|
{ icon: mediationSetting, iconActive: mediationSetting_active, title: '其他功能', actionType: 'setting' },
|
];
|
|
// 底部操作区和左侧card点击
|
function handleClickBottomAction(type) {
|
let visible = modal.actionType === type ? !modal.visible : true;
|
setModal({ visible, actionType: visible ? type : '' });
|
}
|
|
// 左侧底部操作区点击
|
function handleClickLeftAction(type) {
|
if (type === '1') {
|
// 预约调解
|
let visible = modal.actionType === type ? !modal.visible : true;
|
setModal({ visible, actionType: visible ? 'orderMediation' : '' });
|
}
|
if (type === '3') {
|
// 开启视频会议
|
window.open(disputeData.meetCloud.pcJoinUrl);
|
}
|
}
|
|
// 调解开始后回调
|
function onStartMediation() {
|
setSuccessVisible(true);
|
setMediateStartTime(new Date());
|
}
|
|
// 开始调解
|
async function handleStartMediate(type) {
|
let meetInfo = disputeData.meetInfo;
|
if (
|
meetInfo &&
|
$$.timeFormat(meetInfo.orderStartTime) <= $$.timeFormat(new Date()) &&
|
$$.timeFormat(meetInfo.orderEndTime) >= $$.timeFormat(new Date())
|
) {
|
// 在预约时间内立即开始
|
global.setSpinning(true);
|
const res = await startMediationApi({ caseId, startType: '1' });
|
global.setSpinning(false);
|
if (res.type) {
|
onStartMediation();
|
}
|
return;
|
}
|
// 预约时间外则打开modal
|
handleClickBottomAction(type);
|
}
|
|
// 获取纠纷信息
|
async function getDisputeData(isNoLoading) {
|
if (!isNoLoading) global.setSpinning(true);
|
const res = await getDisputeDataApi(caseId);
|
global.setSpinning(false, 'only');
|
if (res.type) {
|
getData();
|
setDisputeData(res.data || {});
|
if (res.data?.mediStartTime) {
|
setMediateStartTime($$.timeFormat(res.data?.mediStartTime, 'isValue'));
|
}
|
}
|
}
|
|
// 获取任务信息
|
async function getTaskInfo() {
|
if (task.visible) {
|
setTask({ visible: false });
|
return;
|
}
|
global.setSpinning(true);
|
const res = await getTaskInfoApi(taskId);
|
global.setSpinning(false);
|
if (res.type) {
|
setTask({ visible: true, contentData: res.data || {} });
|
}
|
}
|
|
// ai获取相关推荐接口
|
async function cacheOpenAiCaseGuideList(params) {
|
global.setSpinning(true);
|
const res = await cacheOpenAiCaseGuideListApi({ caseId, guideTypes: '5,6,7' });
|
global.setSpinning(false);
|
if (res.type) {
|
cacheLatjCaseGuide()
|
cacheCaseFeature()
|
}
|
}
|
|
// 类案推荐接口
|
async function cacheLatjCaseGuide() {
|
global.setSpinning(true);
|
const res = await cacheLatjCaseGuideApi({ caseId, start_page_num: 0, end_page_num: 1000 });
|
global.setSpinning(false);
|
if (res.type) {
|
getData();
|
}
|
}
|
|
// 案件特征缓存
|
async function cacheCaseFeature() {
|
global.setSpinning(true);
|
const res = await cacheCaseFeatureApi({ caseId });
|
global.setSpinning(false);
|
if (res.type) {
|
}
|
}
|
|
// 获取数据
|
async function getData() {
|
// global.setSpinning(true);
|
// const res = await getDataApi({ caseId });
|
// global.setSpinning(false);
|
// console.log(res);
|
// if (res.type) {
|
// let newData = res.data;
|
// setData(newData);
|
// // if (!newData?.find(i => i.guideName === '类案推荐')?.guideInfoList) {
|
// // cacheOpenAiCaseGuideList();
|
// // }
|
// }
|
}
|
|
// 初始化
|
useEffect(() => {
|
|
getDisputeData();
|
// 退回案件时打开任务信息
|
if (taskType === '2') {
|
getTaskInfo();
|
}
|
}, [caseId]);
|
|
// 定时器触发预约时间提醒
|
let orderStartTime = disputeData?.meetInfo?.orderStartTime || '';
|
|
|
useEffect(() => {
|
if (orderStartTime) {
|
let startTime = new Date(orderStartTime).getTime() - 15 * 60 * 1000;
|
let nowTime = new Date().getTime();
|
if (startTime > nowTime) {
|
let second = parseInt(startTime - nowTime);
|
timer.setTimeout(
|
'orderVisible',
|
() => {
|
if (window.location.hash.indexOf('mediationWindow') !== -1) setOrderVisible(true);
|
},
|
second
|
);
|
}
|
}
|
return () => {
|
timer.clearTimeOut('orderVisible');
|
};
|
}, [orderStartTime]);
|
|
// 暂停,结束调解dom
|
const stopMediate = (
|
<Space size={32}>
|
<div className="mediationWindow-stopMediate" onClick={() => handleClickBottomAction('mediationOver')}>
|
<End />
|
<span>结束调解</span>
|
</div>
|
</Space>
|
);
|
|
return (
|
<Page>
|
<div className="mediationWindow">
|
<div className="mediationWindow-header">
|
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
|
<Tooltip title="返回">
|
<div onClick={() => navigate(`${back}?isBack=true`)} className="mediationWindow-header-returnIcon">
|
<LeftOutlined />
|
</div>
|
</Tooltip>
|
<h5 className="mediationWindow-noMargin">
|
{disputeData.caseTitle}
|
{disputeData.caseNo}
|
</h5>
|
<Button onClick={getTaskInfo} className="public-mainBtn" size="small">
|
任务信息
|
</Button>
|
</div>
|
<Tooltip title="调解邀请码" placement="topLeft">
|
<QrcodeOutlined onClick={() => setModal({ visible: true, actionType: 'qrCode' })} style={{ fontSize: '34px', cursor: 'pointer' }} />
|
</Tooltip>
|
</div>
|
{/* center */}
|
<div className="mediationWindow-main">
|
<div className="mediationWindow-main-left">
|
{voiceVisible ? (
|
<MediateDynamic />
|
) : (
|
<Space direction="vertical" className="animated faster flipInY">
|
<div
|
onClick={() => handleClickBottomAction('caseChange')}
|
className="mediationWindow-card mediationWindow-cursor"
|
style={{ paddingRight: '8px' }}
|
>
|
<h5>调解请求</h5>
|
<pre className="mediationWindow-top-pre">{disputeData.caseClaim}</pre>
|
</div>
|
<div
|
onClick={() => handleClickBottomAction('caseChange')}
|
className="mediationWindow-card mediationWindow-cursor"
|
style={{ paddingRight: '8px' }}
|
>
|
<h5>纠纷描述</h5>
|
<pre style={{ height: '218px' }} className="mediationWindow-top-pre">{disputeData.caseDes}</pre>
|
</div>
|
<div onClick={() => handleClickBottomAction('caseChange')} className="mediationWindow-card mediationWindow-cursor">
|
<Space size={4}>
|
<h5 className="mediationWindow-noMargin">申请人-</h5>
|
<div>
|
{(disputeData.plaintiffList || [])[0]?.trueName || '-'}
|
{`( 共${disputeData.plaintiffList?.length || 0}方 )`}
|
</div>
|
</Space>
|
</div>
|
<div onClick={() => handleClickBottomAction('caseChange')} className="mediationWindow-card mediationWindow-cursor">
|
<Space size={4}>
|
<h5 className="mediationWindow-noMargin">被申请人-</h5>
|
<div>
|
{(disputeData.defendantList || [])[0]?.trueName || '-'}
|
{`( 共${disputeData.defendantList?.length || 0}方 )`}
|
</div>
|
</Space>
|
</div>
|
<div className="mediationWindow-card mediationWindow-material" onClick={() => handleClickBottomAction('materialCheck')}>
|
<div className="mediationWindow-material-item">
|
<h5 className="mediationWindow-noMargin">申请人材料</h5>
|
<div>{disputeData.plaintiffFileNum || 0}</div>
|
</div>
|
<div className="mediationWindow-material-item">
|
<h5 className="mediationWindow-noMargin">被申请人材料</h5>
|
<div>{disputeData.defendantFileNum || 0}</div>
|
</div>
|
</div>
|
</Space>
|
)}
|
<div className="mediationWindow-main-left-action" style={!voiceVisible ? { flex: 1 } : {}}>
|
<Space size={66}>
|
<Tooltip
|
title={
|
orderVisible ? (
|
<Space>
|
<span>15分钟后开始调解</span>
|
<CloseCircleOutlined onClick={() => setOrderVisible(false)} style={{ fontSize: 20 }} />
|
</Space>
|
) : (
|
'预约设置'
|
)
|
}
|
visible={orderVisible || undefined}
|
>
|
<img onClick={() => handleClickLeftAction('1')} src={modal.actionType === 'orderMediation' ? clock_active : clock} alt="" />
|
</Tooltip>
|
{/* TODO:暂无此功能开放 */}
|
{/* <Popconfirm
|
title={voiceVisible ? '是否关闭语音转文字功能?' : '是否开启语音转文字功能?'}
|
onConfirm={() => setVoiceVisible(!voiceVisible)}
|
okText={voiceVisible ? '关闭转写' : '开启转写'}
|
cancelText={voiceVisible ? '保持开启' : '稍后再说'}
|
>
|
<Tooltip title="语音转文字">
|
<img src={voiceVisible ? microphone_active : microphone} alt="" />
|
</Tooltip>
|
</Popconfirm> */}
|
<Popconfirm
|
title="是否跳转到视频会议房间?"
|
onConfirm={() => {
|
if (!disputeData.meetCloud?.pcJoinUrl) {
|
$$.info({ type: 'warning', content: '抱歉!视频会议房间暂未创建,请先开始调解' });
|
return;
|
}
|
handleClickLeftAction('3');
|
}}
|
>
|
<Tooltip title="视频会议">
|
<img src={camera} alt="" />
|
</Tooltip>
|
</Popconfirm>
|
</Space>
|
</div>
|
</div>
|
{/* TODO:接口未提供是否购买调解导航判断字段 */}
|
{/* <div className="mediationWindow-card" style={{ height: 'calc(100% - 16px)' }}>
|
<h5>调解导航</h5>
|
<div className="mediationWindow-nav-empty">
|
{$$.MyEmpty({
|
description: (
|
<>
|
<div>您尚未购买调解导航增强服务</div>
|
<div>如需体验请联系平台管理员</div>
|
</>
|
),
|
})}
|
</div>
|
</div> */}
|
<MediationNav1
|
newData={data || []}
|
onClickRatio={(guideInfoId, id) => {
|
setModal({ visible: true, actionType: 'ratio', guideInfoId, guideId: id })
|
}}
|
createAgreement={(id) => {
|
setModal({ visible: true, actionType: 'ratio', guideInfoId: id })
|
}}
|
/>
|
|
{/* <MediationNav /> */}
|
</div>
|
{/* bottom */}
|
<div className="mediationWindow-bottom">
|
{operation.map((x, t) => {
|
if (x.actionType === 'mediationStart') {
|
return (
|
<div className="mediationWindow-bottom-item" key={x.actionType}>
|
{!mediateStartTime ? (
|
<Popconfirm title="确定开始调解吗?" onConfirm={() => handleStartMediate(x.actionType)} okText="开始调解" cancelText="稍后再说">
|
<div className="mediationWindow-bottom-mediate">
|
<Space direction="vertical" size={2}>
|
<img className="mediationWindow-bottom-icon" src={x.icon} alt="" />
|
<div>{x.title}</div>
|
</Space>
|
</div>
|
</Popconfirm>
|
) : (
|
<Popover content={stopMediate}>
|
<div className="mediationWindow-bottom-mediate">
|
<Space direction="vertical" size={2}>
|
<img className="mediationWindow-bottom-icon" src={x.iconActive} alt="" />
|
<Timer mediateStartTime={mediateStartTime} />
|
</Space>
|
</div>
|
</Popover>
|
)}
|
</div>
|
);
|
}
|
return (
|
<div
|
className={`mediationWindow-bottom-item ${modal.actionType === x.actionType ? 'mediationWindow-bottom-item-active' : ''}`}
|
key={x.actionType}
|
>
|
<Space direction="vertical" size={4} onClick={() => handleClickBottomAction(x.actionType)}>
|
<img className="mediationWindow-bottom-icon" src={modal.actionType === x.actionType ? x.iconActive : x.icon} alt="" />
|
<div>{x.title}</div>
|
</Space>
|
</div>
|
);
|
})}
|
</div>
|
{modal.visible !== null && (
|
<ActionModal
|
caseId={caseId}
|
taskId={taskId}
|
guideInfoId={modal.guideInfoId || ''}
|
guideId={modal.guideId || ''}
|
disputeData={disputeData}
|
visible={modal.visible}
|
actionType={modal.actionType}
|
getDisputeData={getDisputeData}
|
onClose={() => setModal({ visible: false })}
|
onStartMediation={onStartMediation} // 开始调解回调
|
/>
|
)}
|
{/* 任务信息 */}
|
<MediationTask visible={task.visible} onClose={() => setTask({ visible: false })} contentData={task.contentData || {}} />
|
{/* 调解开始后的一个浮窗显示 */}
|
<MyModal visible={successVisible} footer={false} width={374} centered onCancel={() => setSuccessVisible(false)}>
|
<div style={{ padding: '12px 16px 16px' }}>
|
<Space direction="vertical" align="center" size="large">
|
<Space>
|
<CheckCircleFilled style={{ color: '#52c41a' }} />
|
<h4 style={{ margin: 0 }}>调解开始提示</h4>
|
</Space>
|
<div>调解已经开始!线上调解时,可点击工作台右上方二维码查看或复制「在线视频调解房间号」</div>
|
<Button type="primary" onClick={() => setSuccessVisible(false)}>
|
我知道了
|
</Button>
|
</Space>
|
</div>
|
<div className="mediationWindow-start-tips">
|
<QrcodeOutlined style={{ fontSize: '34px' }} />
|
<div className="mediationWindow-start-arrow">
|
<img src={promptArrow} alt="" />
|
</div>
|
</div>
|
</MyModal>
|
</div>
|
</Page>
|
);
|
};
|
|
// 任务信息
|
const MediationTask = ({ visible, onClose, contentData }) => {
|
// 处理时限,暂时取消,后续可根据需求改动
|
// const expireHours = $$.getHours(contentData.expireTime);
|
|
return (
|
<>
|
{visible && <div onClick={onClose} className="mediationWindow-task-box" />}
|
<div className="mediationWindow-task caseDetail-headerCard" style={{ top: visible ? undefined : '-200px' }}>
|
<div className="caseDetail-cardTitle">
|
<Space size="small">
|
<div className="caseDetail-cardTitle-icon caseDetail-cardTitle-iconGreen">
|
<ProfileOutlined />
|
</div>
|
<h5>任务信息</h5>
|
</Space>
|
</div>
|
<div className="caseDetail-descriptions">
|
<Descriptions size="small">
|
<Descriptions.Item label="任务名称">{contentData.taskNodeName || '-'}</Descriptions.Item>
|
<Descriptions.Item label="任务下达时间">{$$.timeFormat(contentData.createTime)}</Descriptions.Item>
|
{/* TODO:暂时取消,后续可根据需求改动 <Descriptions.Item label="处理时限">
|
<span className={expireHours.isNegativeNum ? 'public-danger' : ''}>{expireHours.hours}小时</span>
|
</Descriptions.Item> */}
|
<Descriptions.Item label="上一级处理人">
|
{contentData.lastUserName ? <NameCard name={contentData.lastUserName} userId={contentData.lastUserId} /> : <div>-</div>}
|
</Descriptions.Item>
|
<Descriptions.Item label="上一级处理说明">
|
<Text className="public-fontBg" ellipsis={{ tooltip: contentData.lastContent || '-' }}>
|
{contentData.lastContent || '-'}
|
</Text>
|
</Descriptions.Item>
|
<Descriptions.Item label="上一级处理附件">
|
<FilesDrawer filesData={contentData.lastFileInfoList} />
|
</Descriptions.Item>
|
</Descriptions>
|
</div>
|
</div>
|
</>
|
);
|
};
|
|
// 计时器
|
const Timer = ({ mediateStartTime }) => {
|
const [time, setTime] = useState('00:00:00');
|
|
function uninstall() {
|
timer.clearInterval('mediationWindowTimer');
|
}
|
|
useEffect(() => {
|
let seconds = 0;
|
if (mediateStartTime) {
|
seconds = $$.getFunnel(mediateStartTime);
|
if (seconds > 345600) {
|
// 大于4天时显示
|
setTime('99:99:99:99');
|
} else {
|
let duration = $$.getDuration(seconds);
|
setTime(duration);
|
}
|
} else {
|
setTime('00:00:00');
|
}
|
timer.setInterval(
|
'mediationWindowTimer',
|
() => {
|
if (seconds > 345600) {
|
setTime('99:99:99:99');
|
uninstall();
|
return;
|
}
|
seconds = seconds + 1;
|
setTime($$.getDuration(seconds));
|
},
|
1000
|
);
|
return uninstall;
|
}, [mediateStartTime]);
|
|
return <div>{time}</div>;
|
};
|
|
export default MediationWindow;
|