Commit 39a4ab8a authored by 左玲玲's avatar 左玲玲 😬

1723

parent cf32b0ef
......@@ -337,6 +337,12 @@ export default [
icon: '',
component: './lease/contract',
},
{
name: '费用分析',
path: '/lease/costanalysis',
icon: '',
component: './lease/costanalysis',
},
{
name: '租赁设备',
path: '/lease/leasedevice',
......
......@@ -13,7 +13,7 @@ export default {
dev: {
[defaultSetting.proxypath]: {
// 要代理的地址
target: 'http://192.168.40.111:8000', //jf哥
target: 'http://192.168.40.110:8000', //jf哥
// target: 'http://192.168.40.248:8080', //jf哥
// target: 'http://192.168.40.64:28000', //gc哥
// target: 'http://192.168.40.203:8000', //dj哥
......@@ -22,7 +22,7 @@ export default {
},
'/token': {
// 要代理的地址
target: 'http://192.168.40.111:8000',
target: 'http://192.168.40.110:8000',
changeOrigin: true,
},
'/staticfile/': {
......
......@@ -73,6 +73,7 @@
"react-dom": "^17.0.0",
"react-helmet-async": "^1.2.0",
"react-resizable": "^3.0.4",
"socket.io-client": "2.2.0",
"umi-request": "^1.4.0"
},
"devDependencies": {
......
......@@ -120,7 +120,7 @@ export default (props) => {
{props.childposition == 'bottom' && props.children}
</Card>
) : (
<div className="tabsTable">
<div className="tabstable">
<div style={{ display: 'flex', justifyContent: 'space-between', padding: '16px 20px 0' }}>
<div style={{ fontSize: 16, fontWeight: 500 }}>{props.pagetitle}</div>
<div className="center">{renderextra()}</div>
......
......@@ -36,7 +36,11 @@ function DrawerPro(props) {
{props?.children}
</div>
) : (
<InitForm {...newProps} />
<>
{props.childrenposition == 'top' && props.children}
<InitForm {...newProps} />
{props.childrenposition == 'bottom' && props.children}
</>
)}
{pushSettingFlag ? (
......
......@@ -138,11 +138,11 @@ let FormRender = memo(({ fields = [], name, curindex, formRef, action }) => {
<Col {...item.colProps} key={index}>
{curindex == 0 ? (
<div>
<label htmlFor="">{item.title}</label>
<label htmlFor="" style={{ marginBottom: 10, display: 'inline-block' }} >{item.title}</label>
{
hideInFormShowKey ? <div style={{ padding: "6px 0 0 0", margin: 0 }}>{value[hideInFormShowKey]}</div>
hideInFormShowKey ? <div style={{ margin: 0 }}>{value[hideInFormShowKey]}</div>
:
<div style={{ padding: "6px 0 0 0", margin: 0 }}>
<div style={{ margin: 0 }}>
<b style={{ color: "red" }}>!</b>{" "}
需满足条件才可以填写{item.title}
</div>
......@@ -154,7 +154,7 @@ let FormRender = memo(({ fields = [], name, curindex, formRef, action }) => {
{
hideInFormShowKey ? <>{value[hideInFormShowKey]}</>
:
<div style={{ padding: "6px 0 0 0", margin: 0 }}>
<div style={{ margin: 0 }}>
<b style={{ color: "red" }}>!</b>{" "}
需满足条件才可以填写{item.title}
</div>
......@@ -180,8 +180,8 @@ let FormRender = memo(({ fields = [], name, curindex, formRef, action }) => {
return curindex === 0 ? (
<Col {...item.colProps} style={{ height: 68 }} key={index}>
<div>
<label htmlFor="">{item.title}</label>
<div style={{ padding: "6px 0 0 0", margin: 0 }}>
<label htmlFor="" style={{ marginBottom: 10, display: 'inline-block' }} >{item.title}</label>
<div style={{ margin: 0 }}>
{value[item?.key ?? item?.dataIndex] ?? "-"}
</div>
</div>
......@@ -189,7 +189,7 @@ let FormRender = memo(({ fields = [], name, curindex, formRef, action }) => {
) : (
<Col {...item.colProps} style={{ height: 68 }} key={index}>
<div>
<div style={{ padding: "6px 0 0 0", margin: 0 }}>
<div style={{ margin: 0 }}>
{value[item?.key ?? item?.dataIndex] ?? "-"}
</div>
</div>
......@@ -383,7 +383,7 @@ function DigitRange({ item, colProps }) {
}
//Date
function Date({ item, colProps }) {
function Date({ item, colProps, curindex = 0 }) {
return (
<>
<ProFormDatePicker
......@@ -391,7 +391,7 @@ function Date({ item, colProps }) {
formItemProps={item.formItemProps}
name={item?.key ?? item?.dataIndex}
colProps={item.colProps ?? colProps}
label={item.title}
label={curindex == 0 ? item.title : ""}
placeholder={`请选择${item.title}`}
width="100%"
/>
......@@ -1452,36 +1452,62 @@ function Expandable({ item, colProps }) {
}
function FormList(props) {
const [isEmpty, cie] = useState(false);
let { item, colProps, formRef } = props;
let col = item.colProps ?? colProps;
let fields = item.columns?.filter(it => !it.hideInTable) ?? [];
useEffect(() => {
let value = props.formRef.current.getFieldValue(
item?.key ?? item?.dataIndex
);
if (value?.length == 0) {
cie(true);
}
}, [props]);
return (
<Col {...col}>
<ProFormList
name={item.key ?? item.dataIndex}
label={item.title}
min={item.min ?? 0}
max={item.max ?? 100}
itemContainerRender={(doms) => {
return <ProForm.Group>{doms}</ProForm.Group>;
}}
alwaysShowItemLabel={false}
copyIconProps={item?.copyIconProps ?? false}
deleteIconProps={item?.deleteIconProps ?? true}
creatorButtonProps={item?.creatorButtonProps ?? true}
>
{(f, index, action) => {
return (
<FormRender
fields={fields}
action={action}
curindex={index}
formRef={formRef}
<div className="formlist">
{
!isEmpty ?
<ProFormList
name={item.key ?? item.dataIndex}
/>
);
}}
</ProFormList>
label={item.title}
min={item.min ?? 0}
max={item.max ?? 100}
itemContainerRender={(doms) => {
return <ProForm.Group>{doms}</ProForm.Group>;
}}
alwaysShowItemLabel={false}
copyIconProps={item?.copyIconProps ?? false}
deleteIconProps={item?.deleteIconProps ?? true}
creatorButtonProps={item?.creatorButtonProps ?? true}
>
{(f, index, action) => {
return (
<FormRender
fields={fields}
action={action}
curindex={index}
formRef={formRef}
name={item.key ?? item.dataIndex}
/>
);
}}
</ProFormList>
:
<div>
<div>{item.title}</div>
<Empty
image={"./empty.svg"}
imageStyle={{
height: 60,
}}
/>
</div>
}
</div>
</Col>
);
}
......
import React, { useCallback, useState, useMemo } from 'react';
import React, { useCallback, useState, useMemo, useEffect } from 'react';
import { LogoutOutlined, LockOutlined } from '@ant-design/icons';
import { Menu, Spin, Button, Form, Modal, message, Avatar, Select } from 'antd';
import { history, useModel } from '@umijs/max';
......@@ -14,6 +14,14 @@ import ECB from 'crypto-js/mode-ecb';
import Pkcs7 from 'crypto-js/pad-pkcs7';
import Utf8 from 'crypto-js/enc-utf8';
import moment from 'moment';
import io from 'socket.io-client';
const { NODE_ENV } = process.env;
const websocketUrl = NODE_ENV == "development" ? "ws://192.168.40.110:9933" : `${window.location.protocol == "http:" ? "ws" : "wss"}://${window.location.host}`;
const socket = io(websocketUrl, {
reconnectionDelay: 4000,
transports: ['websocket'],
autoConnect: true,
});
/**
* 退出登录,并且将当前的 url 保存
*/
......@@ -31,6 +39,7 @@ const AvatarDropdown = ({ menu }) => {
return res?.data || {};
});
const { initialState, setInitialState } = useModel('@@initialState');
const { allWebsocket, changeWebsocket } = useModel('useGlobal');
const [visible, cv] = useState(false),
[formRef] = Form.useForm(),
{ run, loading } = useRequest(doFetch, {
......@@ -50,6 +59,14 @@ const AvatarDropdown = ({ menu }) => {
}
},
});
useEffect(() => {
changeWebsocket((s) => ({ ...s, commonWebsocket: socket }));
socket.on('iotData', (data) => {
changeWebsocket((s) => ({ ...s, commonWebmsg: data }));
});
}, []);
const fields = useMemo(() => {
return {
password: {
......@@ -133,9 +150,9 @@ const AvatarDropdown = ({ menu }) => {
padding: Pkcs7,
}).toString();
let newPassword = AES.encrypt(values.newPassword, Utf8.parse(timestamp), {
mode: ECB,
padding: Pkcs7,
}).toString(),
mode: ECB,
padding: Pkcs7,
}).toString(),
password = AES.encrypt(values.password, Utf8.parse(timestamp), {
mode: ECB,
padding: Pkcs7,
......@@ -184,7 +201,7 @@ const AvatarDropdown = ({ menu }) => {
formRef={formRef}
fields={fields}
col={{ span: 24 }}
onChange={(changedValues, allValues) => {}}
onChange={(changedValues, allValues) => { }}
submitData={(values, fn) => {
saveData(values, fn);
}}
......
......@@ -368,7 +368,7 @@ ol {
}
}
.tabsTable {
.tabstable {
background: #fff;
.ant-tabs-nav {
......@@ -561,26 +561,28 @@ ol {
}
}
.formList {
.ledgerf {
.ant-card-head {
display: none !important;
}
.ant-card-body {
padding: 0 !important;
}
}
.formlist {
>div {
>div {
>div {
>div {
>div:last-child {
border: 1px solid #dbdbdb;
padding: 12px;
}
}
}
}
}
}
.ledgerf {
.ant-card-head {
display: none !important;
}
.ant-card-body {
padding: 0 !important;
}
}
\ No newline at end of file
import { useState, useCallback } from 'react';
export default function useGlobal() {
const [alive, setAlive] = useState(false),
[newMenus, setMenu] = useState({});
[newMenus, setMenu] = useState({}),
[allWebsocket, setAllWebsocket] = useState({});
const changealive = useCallback((parser) => {
setAlive(parser);
......@@ -10,11 +11,16 @@ export default function useGlobal() {
const setMenuFn = useCallback((val) => {
setMenu(val);
}, []);
const changeWebsocket = useCallback((parser) => {
setAllWebsocket(parser)
}, []);
return {
alive,
changealive,
newMenus,
setMenuFn,
allWebsocket,
changeWebsocket
};
}
......@@ -3,6 +3,7 @@ import { Tooltip, Tabs } from 'antd';
import Filedetail from "@/components/Filedetail";
import DetailPro from '@/components/DetailPro';
import AutoTable from '@/components/AutoTable/mtable';
import { history } from '@umijs/max';
const fields = [
{
title: '合同单号',
......@@ -188,14 +189,31 @@ const fields = [
render: (_, row) => {
return (
<Tooltip title={row.equipmentNo}>
<a
className="table-cell"
onClick={() => {
{
row.pageStatus == 0 ?
<span className="table-cell">
{row.equipmentNo}
</span>
:
<a
className="table-cell"
onClick={() => {
history.push({
path: '/lease/costanalysis',
query: {
pageStatus: row.pageStatus,
extraparams: {
contractId: row.contractId,
equipmentId: row.id
}
}
})
}}
>
{row.equipmentNo}
</a>
}
}}
>
{row.equipmentNo}
</a>
</Tooltip>
);
}
......
import React, { useMemo } from 'react';
import { Tooltip, Tabs } from 'antd';
import Filedetail from "@/components/Filedetail";
import DetailPro from '@/components/DetailPro';
import AutoTable from '@/components/AutoTable/mtable';
import { history } from '@umijs/max';
const columns = [
{
title: '设备编号',
dataIndex: 'equipmentNo',
key: 'equipmentNo'
},
{
title: '设备名称',
dataIndex: 'equipmentName',
key: 'equipmentName',
},
{
title: '设备类型',
dataIndex: 'equipmentTypeName',
key: 'equipmentType',
hideInSearch: true,
// valueType: 'select',
// options: [
// { label: '设备', value: 1 },
// { label: '智能单元', value: 2 },
// ]
},
{
title: '设备型号',
dataIndex: 'equipmentModelName',
key: 'equipmentModelName',
},
{
title: '开始租赁时间',
dataIndex: 'startLeaseDate',
key: 'startLeaseDateList',
valueType: 'dateRange'
},
{
title: '结束租赁时间',
dataIndex: 'endLeaseDate',
key: 'endLeaseDateList',
valueType: 'dateRange'
},
{
title: '实际结束时间',
dataIndex: 'realEndDate',
key: 'realEndDateList',
valueType: 'dateRange'
},
{
title: '采集状态',
dataIndex: 'collectStatusName',
key: 'collectStatusName',
hideInSearch: true
},
];
const Devices = ({ drawer }) => {
return <div>
<AutoTable
columns={columns}
path={'/lease/umContractEquipment/queryByContractId'}
resizeable={false}
pageextra="none"
bordered={false}
extraparams={{ contractId: drawer?.item?.id }}
pagination={'false'}
/>
</div>
}
export default Devices;
\ No newline at end of file
......@@ -18,7 +18,8 @@ function getcolumns(setdrawer, drawer) {
open: true,
item: row,
val: 'only',
title: '合同详情'
title: '合同详情',
type: 'detail'
}));
}}
>
......@@ -71,13 +72,14 @@ function getcolumns(setdrawer, drawer) {
<a
className="table-cell"
onClick={() => {
// setdrawer && setdrawer((s) => ({
// ...s,
// open: true,
// item: row,
// val: 'only',
// title: '租赁设备'
// }));
setdrawer && setdrawer((s) => ({
...s,
open: true,
item: row,
val: 'only',
title: '租赁设备',
type: 'device'
}));
}}
>
{row.equipmentNum}
......
This diff is collapsed.
import React, { useMemo, useState } from 'react';
import DrawerPro from '@/components/DrawerPro';
import AutoTable from '@/components/AutoTable/mtable';
import PremButton from '@/components/PremButton';
import { Tooltip } from "antd";
import Filedetail from "@/components/Filedetail";
import { doFetch, exportFetch } from '@/utils/doFetch';
import { message } from "antd";
const commona = [
{
title: '当期金额',
dataIndex: 'thisPrice',
key: 'thisPrice',
search: false
},
{
title: '回款日期',
dataIndex: 'collectionDate',
key: 'collectionDate',
search: false
},
{
title: '预警日期',
dataIndex: 'warnDate',
key: 'warnDate',
search: false
},
{
title: '状态',
dataIndex: 'statusName',
key: 'statusName',
search: false
}
],
commonb = [
{
title: '是否回款',
dataIndex: 'isCollectionName',
key: 'isCollectionName',
search: false
},
{
title: '回款时间',
dataIndex: 'collectionTime',
key: 'collectionTime',
search: false
},
{
title: '回款形式',
dataIndex: 'collectionTypeName',
key: 'collectionTypeName',
search: false
}
],
columnsc = [
{
title: '基本信息',
valueType: 'split'
},
{
title: '期数',
dataIndex: 'thisTenancy',
key: 'thisTenancy'
},
{
title: '当期开始时间',
dataIndex: 'tenancyStartDate',
key: 'tenancyStartDate'
},
{
title: '当期结束时间',
dataIndex: 'tenancyEndDate',
key: 'tenancyEndDate'
},
...commona,
{
title: '回款信息',
valueType: 'split'
},
...commonb,
{
title: '回款确认人',
dataIndex: 'collectionUserName',
key: 'collectionUserName'
},
{
title: '是否逾期',
dataIndex: 'isOverdueName',
key: 'isOverdueName'
},
{
title: '减免租金信息',
valueType: 'split'
},
{
title: '当期租金减免金额',
dataIndex: 'reducePrice',
key: 'reducePrice'
},
{
title: '最近租金减免时间',
dataIndex: 'reduceTime',
key: 'reduceTime'
},
{
title: '最近租金减免人',
dataIndex: 'reduceUserName',
key: 'reduceUserName'
},
{
title: '减免情况说明',
dataIndex: 'reduceRemark',
key: 'reduceRemark'
},
{
title: '相关文件',
dataIndex: 'reduceFileFileList',
key: 'reduceFileFileList',
render: (_, row) => {
return <Filedetail files={row?.['reduceFileFileList']} />
}
},
{
title: '开票信息',
valueType: 'split'
},
{
title: '是否开票',
dataIndex: 'isOpenName',
key: 'isOpenName'
},
{
title: '开票时间',
dataIndex: 'openTime',
key: 'openTime'
},
{
title: '开票记录人',
dataIndex: 'openUserName',
key: 'openUserName'
},
];
const Leaseterminformation = ({ drawer, boxRef }) => {
const [detail, cd] = useState({
open: false,
});
const columns = [
{
title: '期数',
dataIndex: 'thisTenancy',
key: 'thisTenancy',
search: false
},
...commona,
...commonb,
{
title: '是否逾期',
dataIndex: 'isOverdueName',
key: 'isOverdueName',
search: false
},
{
title: '租金减免金额',
dataIndex: 'reducePrice',
key: 'reducePrice',
search: false
},
{
title: '租金情况说明',
dataIndex: 'reduceRemark',
key: 'reduceRemark',
search: false
},
{
title: '是否开票',
dataIndex: 'isOpenName',
key: 'isOpenName',
search: false
},
{
title: '操作',
valueType: 'option',
width: 80,
render: (text, row, _, action) => rightExtra(text, row, _, action),
}
];
const rightExtra = (text, row, _, action) => {
return [
<PremButton
key='confirm'
btn={{
size: 'small',
onClick: () => {
cd((s) => ({
...s,
open: true,
item: row,
title: '租期详情',
val: 'detail'
}));
},
}}
>
详情
</PremButton>
]
}
return <div style={{ position: "relative" }}>
<div style={{ display: 'flex', justifyContent: 'flex-end' }}>
<PremButton
key='export'
btn={{
type: 'primary',
onClick: async () => {
message.warning('导出中,请稍后');
await exportFetch({ url: '/lease/umContractEquipmentTenancy/exportExcelTenancy', params: { id: drawer?.item?.id } });
}
}}
>
导出
</PremButton>
</div>
<AutoTable
columns={columns}
path={'/lease/umContractEquipmentTenancy/queryByContractEquipmentId'}
resizeable={false}
bordered={false}
extraparams={{ id: drawer?.item?.id }}
options={false}
pagination='false'
/>
<DrawerPro
{...detail}
fields={columnsc}
params={{ id: detail?.item?.id }}
detailpath='/lease/umContractEquipmentTenancy/queryDetail'
placement="right"
onClose={() => {
cd((s) => ({
...s,
open: false,
}));
}}
getContainer={() => boxRef.current}
>
</DrawerPro>
</div>
}
export default Leaseterminformation;
\ No newline at end of file
import { Tooltip, Image, Tag } from 'antd';
import { doFetch } from '@/utils/doFetch';
const statusColors = {
1: '#7ac143',
2: 'orange',
3: '#fa4659'
};
function getcolumns(setdrawer, activeKey) {
const commona = [
{
title: '客户',
dataIndex: 'customerName',
key: 'customerId',
valueType: 'select',
options: { path: '/lease/umLeaseCustomer/getSelection', params: {} },
fieldProps: {
showSearch: true
},
fixed: 'left'
},
{
title: '合同单号',
dataIndex: 'contractNo',
key: 'contractNo',
fixed: 'left'
},
{
title: '设备编号',
dataIndex: 'equipmentNo',
key: 'equipmentNo'
},
{
title: '设备名称',
dataIndex: 'equipmentName',
key: 'equipmentName',
},
{
title: '智能单元莫格云眼编号',
dataIndex: 'intelligentUnitNo',
key: 'intelligentUnitNo',
width: 170
},
{
title: '每期单价(元)',
dataIndex: 'unitPrice',
key: 'unitPrice',
hideInSearch: true
},
{
title: '智享价(元)',
dataIndex: 'zxPrice',
key: 'zxPrice',
hideInSearch: true
},
{
title: '返利金额(元)',
dataIndex: 'rebatePrice',
key: 'rebatePrice',
hideInSearch: true
},
{
title: '押金(元)',
dataIndex: 'deposit',
key: 'deposit',
hideInSearch: true
}
],
commonb = [
{
title: '开票期数',
dataIndex: 'openNum',
key: 'openNum',
hideInSearch: true
},
{
title: '已发生租金',
dataIndex: 'occurredPrice',
key: 'occurredPrice',
hideInSearch: true
},
{
title: '累计逾期欠费',
dataIndex: 'overduePrice',
key: 'overduePrice',
hideInSearch: true
},
{
title: '累计回款金额',
dataIndex: 'collectionPrice',
key: 'collectionPrice',
hideInSearch: true
},
{
title: '逾期次数',
dataIndex: 'overdueNum',
key: 'overdueNum',
hideInSearch: true
},
{
title: '开始租赁时间',
dataIndex: 'startLeaseDate',
key: 'startLeaseDateList',
valueType: 'dateRange'
},
{
title: '结束租赁时间',
dataIndex: 'endLeaseDate',
key: 'endLeaseDateList',
valueType: 'dateRange'
},
{
title: '实际结束时间',
dataIndex: 'realEndDate',
key: 'realEndDateList',
valueType: 'dateRange'
}
];
return [
{
tab: '未完成',
key: 'item-1',
columns: [
...commona,
{
title: '当前租期/租期',
dataIndex: 'thisTenancy',
key: 'thisTenancy',
render: (_, row) => {
return (
<a
className="table-cell"
onClick={() => {
setdrawer && setdrawer((s) => ({
...s,
open: true,
item: row,
val: 'only',
title: '租期信息',
type: 'detail'
}));
}}
>
{row.thisTenancy + '/' + row.tenancyTotal}
</a>
);
},
hideInSearch: true
},
...commonb,
{
title: '回款状态',
dataIndex: 'collectionStatusName',
key: 'collectionStatus',
hideInForm: true,
valueType: 'select',
options: [
{ label: '正常', value: 1 },
{ label: '预警', value: 2 },
{ label: '报警', value: 3 }
],
fixed: 'right',
render: (_, row) => {
return <span style={{ color: statusColors[row.collectionStatus] }}>{row.collectionStatusName}</span>
},
width: 100
},
]
},
{
tab: '已完成',
key: 'item-2',
columns: [
...commona,
{
title: '租期',
dataIndex: 'tenancyTotal',
key: 'tenancyTotal',
render: (_, row) => {
return (
<a
className="table-cell"
onClick={() => {
setdrawer && setdrawer((s) => ({
...s,
open: true,
item: row,
val: 'only',
title: '租期信息',
type: 'detail'
}));
}}
>
{row.tenancyTotal}
</a>
);
},
hideInSearch: true
},
...commonb,]
}
]
}
export default getcolumns;
\ No newline at end of file
import React, { useState, useMemo, useRef, useEffect } from 'react';
import DrawerPro from '@/components/DrawerPro';
import AutoTable from '@/components/AutoTable';
import PremButton from '@/components/PremButton';
import getcolumns from './columns';
import { doFetch } from '@/utils/doFetch';
import { useRequest } from "ahooks";
import { Divider, Tabs, ProDescriptions, message } from "antd";
import dayjs from 'dayjs';
import Leaseterminformation from "./Leaseterminformation";
const Costanalysis = () => {
let actionRef = useRef(), formRef = useRef(), boxRef = useRef();
const [drawer, setdrawer] = useState({
open: false,
}),
[extraparams, setextraparams] = useState({}),
[activeKey, catk] = useState('item-1');
const { run, loading, runAsync } = useRequest(doFetch, {
manual: true,
onSuccess: (res, params) => {
if (res?.code == "0000") {
actionRef?.current?.reload();
setdrawer((s) => ({
...s,
open: false,
}));
}
},
});
const columns = useMemo(() => {
let defcolumn = getcolumns(setdrawer, activeKey)?.filter(it => it.key == activeKey)?.[0]?.columns ?? [];
return defcolumn.concat({
title: '操作',
valueType: 'option',
width: activeKey == 'item-1' ? 260 : 100,
render: (text, row, _, action) => rightExtra(text, row, _, action),
});
}, [activeKey]);
const rightExtra = (text, row, _, action) => {
return [
activeKey == 'item-1' && <PremButton
key='confirm'
btn={{
size: 'small',
onClick: async () => {
let res = await doFetch({ url: '/lease/umContractEquipment/queryBeforeCollection', params: { id: row.id } });
if (res?.data?.data?.waitNum == 0) {
message.warning('该设备需回款的租期已全部回款,无需再次回款!')
} else {
setdrawer((s) => ({
...s,
open: true,
item: { ...row, waitNum: res?.data?.data?.waitNum, isColl: res?.data?.data?.isColl },
val: 'confirm',
title: '回款确认',
fields: [
{
title: '本期是否回款',
dataIndex: 'isColl',
key: 'isColl',
fieldProps: {
disabled: true
},
colProps: { span: 8 },
},
{
title: '剩余回款期数',
dataIndex: 'waitNum',
key: 'waitNum',
fieldProps: {
disabled: true
},
colProps: { span: 8 },
},
{
title: '本次回款期数',
dataIndex: 'collNum',
key: 'collNum',
valueType: 'digit',
colProps: { span: 8 },
precision: 0,
formItemProps: { rules: [{ required: true, message: '此项为必填项' }] }
},
{
title: '回款形式',
dataIndex: 'collType',
key: 'collType',
valueType: 'select',
options: [
{ label: '现金', value: 1 },
{ label: '银行承兑', value: 2 },
],
colProps: { span: 8 },
formItemProps: { rules: [{ required: true, message: '此项为必填项' }] },
},
]
}));
}
},
}}
>
回款确认
</PremButton>,
activeKey == 'item-1' && <PremButton
key='reduction'
btn={{
size: 'small',
onClick: async () => {
},
}}
>
租金减免
</PremButton>,
<PremButton
key='invoicing'
btn={{
size: 'small',
onClick: async () => {
},
}}
>
开票记录
</PremButton>
]
};
return <div ref={boxRef}>
<AutoTable
pagetitle={<h3 className="page-title">费用分析</h3>}
columns={columns}
path={activeKey == 'item-1' ? '/lease/umContractEquipment/queryNoAnalysis' : '/lease/umContractEquipment/queryYesAnalysis'}
actionRef={actionRef}
resizeable={false}
bordered={false}
x={2500}
extraparams={extraparams}
onTabChange={(key) => {
catk(key);
}}
activeTabKey={activeKey}
tabList={getcolumns()}
/>
<DrawerPro
{...drawer}
fields={drawer.fields}
params={{ id: drawer?.item?.id }}
defaultFormValue={drawer?.item ?? {}}
placement="right"
onClose={() => {
setdrawer((s) => ({
...s,
open: false,
}));
}}
>
<Leaseterminformation drawer={drawer} boxRef={boxRef} />
</DrawerPro>
</div>
}
export default Costanalysis;
\ No newline at end of file
import { Tooltip, Image, Tag } from 'antd';
import { doFetch } from '@/utils/doFetch';
const statusColors = {
1: '#7ac143',
2: '#00bce4',
3: '#6a737b',
4: '#fa4659'
};
function getcolumns(setdrawer, activeKey) {
return activeKey == 'item-1' ? {
columns: [
......@@ -130,12 +136,15 @@ function getcolumns(setdrawer, activeKey) {
hideInForm: true,
valueType: 'select',
options: [
{ label: '工作', value: '1' },
{ label: '待机', value: '2' },
{ label: '关机', value: '3' },
{ label: '报警', value: '4' }
{ label: '工作', value: 1 },
{ label: '待机', value: 2 },
{ label: '关机', value: 3 },
{ label: '报警', value: 4 }
],
fixed: 'right'
fixed: 'right',
render: (_, row) => {
return <span style={{ color: statusColors[row.collectStatus] }}>{row.collectStatusName}</span>
}
},
{
title: '所属信息',
......
......@@ -10,6 +10,8 @@ import TreeRender from '@/components/TreeRender';
import { Divider, Tabs, ProDescriptions } from "antd";
import Account from "./Account";
import Basemsg from "./Basemsg";
import { useModel } from "@umijs/max";
import dayjs from 'dayjs';
const Devicedata = () => {
let actionRef = useRef(), formRef = useRef(), boxRef = useRef();
const [drawer, setdrawer] = useState({
......@@ -18,7 +20,9 @@ const Devicedata = () => {
[extraparams, setextraparams] = useState({}),
[activeKey, catk] = useState('item-1'),
[item2extraparams, citp] = useState({}),
[searchParams, csp] = useState({});
[searchParams, csp] = useState({}),
[leaseList, clea] = useState([]);
const { allWebsocket: { commonWebsocket, commonWebmsg } } = useModel('useGlobal');
const { run, loading, runAsync } = useRequest(doFetch, {
manual: true,
onSuccess: (res, params) => {
......@@ -31,12 +35,42 @@ const Devicedata = () => {
}
},
}),
tableData = useRequest(async () => {
let res = await doFetch({ url: '/lease/umLeaseLedger/queryLeaseList', params: { ...searchParams, ...extraparams } });
return res?.data?.dataList ?? [];
}, {
refreshDeps: [extraparams, searchParams]
})
tableData = useRequest(() => doFetch({ url: '/lease/umLeaseLedger/queryLeaseList', params: { ...searchParams, ...extraparams } }), {
refreshDeps: [extraparams, searchParams],
onSuccess: (res, params) => {
if (res.code == '0000') {
clea(res?.data?.dataList ?? [])
}
}
});
useEffect(() => {
const msg = commonWebmsg?.msg;
if (commonWebmsg?.wsMsgModel == 'LEASE') {
let newList = JSON.parse(JSON.stringify(leaseList));
newList = newList?.map(it => {
if (it.id == msg.id) {
it.collectStatusName = msg.collectStatusName;
it.collectStatus = msg.collectStatus;
}
return it
});
clea(newList);
}
}, [commonWebmsg]);
useEffect(() => {
try {
commonWebsocket && commonWebsocket.emit("sendMessage", {
"wsMsgModel": "LEASE",
"subId": dayjs().valueOf(),
param: '',
unsubscribe: false,
});
} catch (error) {
}
}, []);
const columns = useMemo(() => {
let defcolumn = getcolumns(setdrawer, activeKey)?.columns ?? [];
return defcolumn;
......@@ -49,7 +83,7 @@ const Devicedata = () => {
key: 'item-1',
children: <AutoTable
columns={columns}
dataSource={tableData?.data ?? []}
dataSource={leaseList}
actionRef={actionRef}
resizeable={false}
bordered={false}
......@@ -70,7 +104,7 @@ const Devicedata = () => {
children: <Account boxRef={boxRef} extraparams={item2extraparams} />
}
]
}, [extraparams, tableData?.data]);
}, [extraparams, leaseList]);
const items = useMemo(() => {
if (drawer.val == 'only') {
if (activeKey == 'item-1') {
......
......@@ -2,6 +2,7 @@ import React, { useState, useRef } from 'react';
import AutoTable from '@/components/AutoTable/mtable';
import { useRequest } from 'ahooks';
import { doFetch } from '@/utils/doFetch';
import styles from "./index.less";
const columnsa = [
{
title: '客户名称',
......@@ -42,7 +43,10 @@ const columnsa = [
dataIndex: 'equipmentModelName',
key: 'equipmentModelId',
valueType: 'select',
options: { path: '/asset/equipmentModel/query/selection', params: {} }
options: { path: '/asset/equipmentModel/query/selection', params: {} },
fieldProps: {
showSearch: true
}
},
{
title: '设备品牌',
......@@ -77,25 +81,37 @@ const columnsa = [
title: '工作',
dataIndex: 'runRate',
key: 'runRate',
search: false
search: false,
render: (_, row) => {
return <span style={{ color: "#7ac143" }}>{row.runRate}%</span>
}
},
{
title: '待机',
dataIndex: 'standbyRate',
key: 'standbyRate',
search: false
search: false,
render: (_, row) => {
return <span style={{ color: "#00bce4" }}>{row.runRate}%</span>
}
},
{
title: '报警',
dataIndex: 'alarmRate',
key: 'alarmRate',
search: false
search: false,
render: (_, row) => {
return <span style={{ color: "#fa4659" }}>{row.runRate}%</span>
}
},
{
title: '关机',
dataIndex: 'offRate',
key: 'offRate',
search: false
search: false,
render: (_, row) => {
return <span style={{ color: "#6a737b" }}>{row.runRate}%</span>
}
},
];
......@@ -109,7 +125,7 @@ const Leasedevice = () => {
return res?.data?.dataList ?? [];
}, {
refreshDeps: [searchParams]
})
});
return <div style={{ background: '#fff' }}>
<div className="ant-card-head" style={{ backgroundColor: 'white' }}>
<div className="ant-card-head-wrapper">
......@@ -128,7 +144,7 @@ const Leasedevice = () => {
onRow={(record) => {
return {
onClick: (event) => {
console.log(event, record);
cr(record);
}
};
}}
......@@ -139,14 +155,19 @@ const Leasedevice = () => {
}}
toolBarRender={true}
options={false}
rowKey='ledgerCustomerId'
rowClassName={(record, index) => {
return record.ledgerCustomerId == clickrow?.ledgerCustomerId ? styles.rowClass : ''
}}
/>
</div>
<div style={{ flex: 2 }}>
<AutoTable
columns={columnsb}
path='/lease/umLeaseLedger/ledgerCustomerEquipmentUseDetail'
path={clickrow?.ledgerCustomerId ? '/lease/umLeaseLedger/ledgerCustomerEquipmentUseDetail' : ''}
resizeable={false}
pageextra="none"
extraparams={{ ledgerCustomerId: clickrow?.ledgerCustomerId }}
/>
</div>
</div>
......
.rowClass {
background-color: #e6f4ff;
}
\ No newline at end of file
......@@ -10,9 +10,9 @@ import TreeRender from '@/components/TreeRender';
const { RangePicker } = DatePicker;
const statusColors = {
报警: '#fa4659',
工作: '#00fff5',
待机: '#80d6ff',
关机: '#194769'
工作: '#7ac143',
待机: '#00bce4',
关机: '#6a737b'
},
format = 'YYYY-MM-DD HH:mm:ss';
const Devicestatus = ({ drawer }) => {
......@@ -151,14 +151,14 @@ const Devicestatus = ({ drawer }) => {
<div style={{ display: "flex", flexWrap: "wrap", gap: 15 }}>
{
Object?.keys(statusColors)?.map(it => {
return <div key={it} style={{ width: '30%', display: 'flex', gap: 16, justifyContent: 'center' }} >
return <div key={it} style={{ width: '31%', display: 'flex', gap: 16, justifyContent: 'center' }} >
<div style={{ color: statusColors[it] }}>{it}时长</div>
<div>{chartdata?.data?.data?.rateList?.filter(item => item.name == it)?.[0]?.time ?? 0}小时</div>
<div>{chartdata?.data?.data?.rateList?.filter(item => item.name == it)?.[0]?.rate ?? 0}%</div>
</div>
})
}
<div style={{ width: '30%', display: 'flex', gap: 16, justifyContent: 'center' }} >
<div style={{ width: '31%', display: 'flex', gap: 16, justifyContent: 'center' }} >
<div>总时长</div>
<div>{chartdata?.data?.data?.timeRange}小时</div>
</div>
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment