@ -17,10 +17,10 @@ export default defineConfig({
|
||||
},
|
||||
proxy: {
|
||||
'/api/': {
|
||||
target: 'http://10.39.13.78:8002/',
|
||||
target: 'http://10.39.13.78:8001/',
|
||||
// target: 'https://gcadmin-test.linyikj.com.cn',
|
||||
// target: 'http://guocaiservice.com',
|
||||
// changeOrigin: true,
|
||||
changeOrigin: true,
|
||||
pathRewrite: { '^': '' },
|
||||
},
|
||||
},
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"url": "http://10.39.13.78:8002/api/docs/openapi",
|
||||
"module": "Admin",
|
||||
"url": "http://10.39.13.78:8001/api/docs/openapi",
|
||||
"module": "Company",
|
||||
"outPath": "./src/gen/",
|
||||
"apis": {
|
||||
"firstLine": "import { MyResponseType } from '@/common';\nimport { request } from '@umijs/max';"
|
||||
|
||||
28
src/common/components/MyModalPagination.tsx
Normal file
@ -0,0 +1,28 @@
|
||||
import { MyPaginationMetaType } from '@/common';
|
||||
import { Pagination } from 'antd';
|
||||
|
||||
export function MyModalPagination({
|
||||
meta,
|
||||
setParams,
|
||||
}: {
|
||||
meta?: MyPaginationMetaType | null;
|
||||
setParams?: ({ page, perPage }: { page: number; perPage: number }) => void;
|
||||
}) {
|
||||
console.log(meta, 'meta2222');
|
||||
if (!meta) return null;
|
||||
return (
|
||||
<div style={{ textAlign: 'right' }}>
|
||||
<Pagination
|
||||
style={{ padding: '10px 0' }}
|
||||
current={meta?.current_page || 1}
|
||||
total={meta?.total || 0}
|
||||
pageSize={meta?.per_page || 20}
|
||||
onChange={(page, perPage) => setParams?.({ page, perPage })}
|
||||
size="small"
|
||||
showTotal={(total) => `总共${total}条`}
|
||||
showSizeChanger
|
||||
showQuickJumper
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -1,25 +1,10 @@
|
||||
import { MyIcons, MyIconsType, PermissionsType, useMyState } from '@/common';
|
||||
import AvatarProps from '@/common/components/layout/AvatarProps';
|
||||
import {
|
||||
BellOutlined,
|
||||
SettingOutlined,
|
||||
TabletOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { SettingOutlined } from '@ant-design/icons';
|
||||
import { Link, RuntimeConfig, history, useNavigate } from '@umijs/max';
|
||||
import {
|
||||
AutoComplete,
|
||||
Button,
|
||||
Image,
|
||||
Input,
|
||||
Menu,
|
||||
MenuProps,
|
||||
Popover,
|
||||
Space,
|
||||
} from 'antd';
|
||||
import { AutoComplete, Button, Input, Menu, MenuProps, Space } from 'antd';
|
||||
import { useState } from 'react';
|
||||
import './allConfig.scss';
|
||||
import ImgCustomerWxApp from './customer_wx_app.jpg';
|
||||
import ImgEmployeeWxApp from './employee_wx_app.jpg';
|
||||
// import Logo from './logo.png';
|
||||
interface LevelKeysProps {
|
||||
key?: string;
|
||||
@ -122,7 +107,7 @@ export const LayoutConfig: RuntimeConfig['layout'] = () => {
|
||||
<div className="headerContentRender">
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 20 }}>
|
||||
<HeaderSearch permissionsList={permissionsList} />
|
||||
<Space size={20} style={{ color: '#666' }}>
|
||||
{/* <Space size={20} style={{ color: '#666' }}>
|
||||
常用功能:
|
||||
{quickLinks.map((q) => (
|
||||
<a
|
||||
@ -133,10 +118,10 @@ export const LayoutConfig: RuntimeConfig['layout'] = () => {
|
||||
{q.label}
|
||||
</a>
|
||||
))}
|
||||
</Space>
|
||||
</Space> */}
|
||||
</div>
|
||||
<Space size={10}>
|
||||
<Popover
|
||||
{/* <Popover
|
||||
placement="bottom"
|
||||
title="小程序二维码"
|
||||
content={
|
||||
@ -155,7 +140,7 @@ export const LayoutConfig: RuntimeConfig['layout'] = () => {
|
||||
>
|
||||
<Button type="default" shape="circle" icon={<TabletOutlined />} />
|
||||
</Popover>
|
||||
<Button type="default" shape="circle" icon={<BellOutlined />} />
|
||||
<Button type="default" shape="circle" icon={<BellOutlined />} /> */}
|
||||
<Button
|
||||
type="default"
|
||||
shape="circle"
|
||||
|
||||
@ -13,7 +13,7 @@ import { theme } from 'antd';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { stateActions } from '..';
|
||||
import gcLogo from './gclogo.png';
|
||||
// import gcLogo from './gclogo.png';
|
||||
import logingBg from './loginBgImg.jpg';
|
||||
|
||||
export function MyLoginPage() {
|
||||
@ -44,7 +44,7 @@ export function MyLoginPage() {
|
||||
<LoginFormPage<ApiTypes.Common.Auth.Login>
|
||||
title={
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
|
||||
<img src={gcLogo} style={{ height: 30, width: 'auto' }} />
|
||||
{/* <img src={gcLogo} style={{ height: 30, width: 'auto' }} /> */}
|
||||
<span style={{ color: '#b1b1b1ff', fontSize: 20 }}>|</span>
|
||||
<span style={{ color: token.colorTextBase, fontSize: 21 }}>
|
||||
智慧物业管理系统
|
||||
@ -71,7 +71,7 @@ export function MyLoginPage() {
|
||||
>
|
||||
<>
|
||||
<ProFormText
|
||||
name="username"
|
||||
name="phone"
|
||||
fieldProps={{
|
||||
size: 'large',
|
||||
prefix: <UserOutlined className={'prefixIcon'} />,
|
||||
|
||||
3750
src/gen/ApiTypes.d.ts
vendored
2501
src/gen/Apis.ts
1653
src/gen/Enums.ts
38
src/pages/bills/summary/components/SearchInfo.tsx
Normal file
@ -0,0 +1,38 @@
|
||||
import { Apis } from '@/gen/Apis';
|
||||
import { ProFormSelect, QueryFilter } from '@ant-design/pro-components';
|
||||
import { Form } from 'antd';
|
||||
type Props = {
|
||||
onChange?: (value: any) => void;
|
||||
};
|
||||
export default function Search(props: Props) {
|
||||
const [form] = Form.useForm();
|
||||
return (
|
||||
<QueryFilter
|
||||
style={{ backgroundColor: '#fff' }}
|
||||
defaultCollapsed
|
||||
split
|
||||
form={form}
|
||||
onFinish={props?.onChange}
|
||||
onReset={() => {
|
||||
props?.onChange?.(form?.getFieldsValue() || {});
|
||||
}}
|
||||
>
|
||||
<ProFormSelect
|
||||
name="asset_houses_id"
|
||||
label="房屋"
|
||||
valueEnum={{
|
||||
open: '未解决',
|
||||
closed: '已解决',
|
||||
}}
|
||||
request={async (params) => {
|
||||
let res = await Apis.Asset.AssetProjects.Select({
|
||||
keywords: params?.keyWords,
|
||||
...params,
|
||||
});
|
||||
return res?.data;
|
||||
}}
|
||||
placeholder="请选择房屋"
|
||||
/>
|
||||
</QueryFilter>
|
||||
);
|
||||
}
|
||||
@ -1,17 +1,52 @@
|
||||
import {
|
||||
MyButtons,
|
||||
MyColumns,
|
||||
MyPageContainer,
|
||||
MyProTableProps,
|
||||
} from '@/common';
|
||||
import { Selects } from '@/components/Select';
|
||||
import { MyPageContainer } from '@/common';
|
||||
import { MyModalPagination } from '@/common/components/MyModalPagination';
|
||||
import { Apis } from '@/gen/Apis';
|
||||
import { ProTable } from '@ant-design/pro-components';
|
||||
import { HomeFilled } from '@ant-design/icons';
|
||||
import { ProCard } from '@ant-design/pro-components';
|
||||
import { useNavigate } from '@umijs/max';
|
||||
import { Space } from 'antd';
|
||||
import { Empty, Space, Tag } from 'antd';
|
||||
import { useEffect, useState } from 'react';
|
||||
import SearchInfo from './components/SearchInfo';
|
||||
|
||||
export default function Index({ title = '房屋账单' }) {
|
||||
const navigate = useNavigate();
|
||||
// const [selectedBuilding, setSelectedBuilding] =
|
||||
// useState<SelectedBuilding | null>(null);
|
||||
const [params, setParams] = useState<any>({ page: 1 });
|
||||
const [getSummaryBillListData, setGetSummaryBillListData] = useState<any>({});
|
||||
|
||||
const getSummaryBillList = (data: any) => {
|
||||
Apis.Bill.HouseBills.SummaryBillList({ ...params, ...data }).then((res) => {
|
||||
setParams({ ...params, ...data });
|
||||
setGetSummaryBillListData(res);
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getSummaryBillList({ page: 1 });
|
||||
}, []);
|
||||
|
||||
// 选择楼栋的回调函数
|
||||
// const handleBuildingSelect = useCallback((building: SelectedBuilding) => {
|
||||
// setSelectedBuilding(building);
|
||||
// // 保存到本地缓存
|
||||
// localStorage.setItem('selectedBuilding', JSON.stringify(building));
|
||||
// }, []);
|
||||
|
||||
// 从本地缓存恢复选中的楼栋信息
|
||||
// useEffect(() => {
|
||||
// const cachedBuilding = localStorage.getItem('selectedBuilding');
|
||||
// if (cachedBuilding) {
|
||||
// try {
|
||||
// const building = JSON.parse(cachedBuilding) as SelectedBuilding;
|
||||
// setSelectedBuilding(building);
|
||||
// // 恢复后重新获取账单列表
|
||||
// getSummaryBillList(building);
|
||||
// } catch (error) {
|
||||
// console.error('Failed to parse cached building:', error);
|
||||
// }
|
||||
// }
|
||||
// }, []);
|
||||
|
||||
return (
|
||||
<MyPageContainer
|
||||
@ -20,94 +55,111 @@ export default function Index({ title = '房屋账单' }) {
|
||||
tabKey="summary"
|
||||
tabLabel={title}
|
||||
>
|
||||
<ProTable
|
||||
{...MyProTableProps.props}
|
||||
headerTitle="房屋账单"
|
||||
request={async (params, sort) =>
|
||||
MyProTableProps.request(
|
||||
params,
|
||||
sort,
|
||||
Apis.Bill.HouseBills.SummaryBillList,
|
||||
)
|
||||
}
|
||||
columns={[
|
||||
{
|
||||
title: '房屋ID',
|
||||
dataIndex: 'asset_houses_id',
|
||||
search: false,
|
||||
},
|
||||
Selects?.AssetProjects({
|
||||
title: '选择项目',
|
||||
key: 'asset_projects_id',
|
||||
hidden: true,
|
||||
}),
|
||||
{
|
||||
title: '关联项目',
|
||||
dataIndex: 'project_name',
|
||||
search: false,
|
||||
// search: {
|
||||
// transform: (value) => {
|
||||
// return { project_name: value };
|
||||
// },
|
||||
// },
|
||||
},
|
||||
{
|
||||
title: '房屋名称',
|
||||
dataIndex: ['asset_house', 'full_name'],
|
||||
search: {
|
||||
transform: (value) => {
|
||||
return { full_name: value };
|
||||
},
|
||||
},
|
||||
},
|
||||
// {
|
||||
// title: '账单金额合计',
|
||||
// dataIndex: 'payable_amount_sum',
|
||||
// search: false,
|
||||
// },
|
||||
// {
|
||||
// title: '滞纳金合计',
|
||||
// dataIndex: 'late_fee_sum',
|
||||
// search: false,
|
||||
// },
|
||||
// {
|
||||
// title: '优惠金额合计',
|
||||
// dataIndex: 'discount_amount_sum',
|
||||
// search: false,
|
||||
// },
|
||||
{
|
||||
title: '应收合计',
|
||||
dataIndex: 'total_payable_sum',
|
||||
search: false,
|
||||
},
|
||||
{
|
||||
title: '已收合计',
|
||||
dataIndex: 'total_paid_sum',
|
||||
search: false,
|
||||
},
|
||||
{
|
||||
title: '未收合计',
|
||||
render: (_, record) => {
|
||||
return (record.total_payable_sum - record.total_paid_sum).toFixed(
|
||||
2,
|
||||
);
|
||||
},
|
||||
search: false,
|
||||
},
|
||||
MyColumns.Option({
|
||||
render: (_, item: any, index) => (
|
||||
<Space key={index}>
|
||||
<MyButtons.View
|
||||
title="查看"
|
||||
onClick={() => {
|
||||
navigate(`/bills/summary/show/${item.asset_houses_id}`);
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'start',
|
||||
justifyContent: 'space-between',
|
||||
gap: 15,
|
||||
}}
|
||||
>
|
||||
<Space direction="vertical" style={{ flex: 1 }}>
|
||||
<SearchInfo
|
||||
onChange={(values) => {
|
||||
setParams({
|
||||
asset_houses_id: values?.asset_houses_id || '',
|
||||
page: 1,
|
||||
});
|
||||
getSummaryBillList({
|
||||
asset_houses_id: values?.asset_houses_id || '',
|
||||
page: 1,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Space>
|
||||
),
|
||||
}),
|
||||
]}
|
||||
<ProCard>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 15 }}>
|
||||
{getSummaryBillListData?.data?.length ? null : (
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
padding: '15px 0',
|
||||
}}
|
||||
>
|
||||
<Empty />
|
||||
</div>
|
||||
)}
|
||||
{getSummaryBillListData?.data?.map((res: any) => {
|
||||
return (
|
||||
<div
|
||||
key={`item_${res?.id}`}
|
||||
style={{
|
||||
width: '240px',
|
||||
height: '120px',
|
||||
backgroundColor: '#f8f8f8',
|
||||
borderRadius: 5,
|
||||
overflow: 'hidden',
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
onClick={() => {
|
||||
navigate(`/bills/summary/show/${res?.asset_houses_id}`);
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
borderBottom: '1px solid #eee',
|
||||
padding: '10px 14px 10px 15px',
|
||||
}}
|
||||
>
|
||||
<HomeFilled />
|
||||
<div>
|
||||
{res.total_payable_sum - res.total_paid_sum > 0 ? (
|
||||
<Tag color="red">欠费</Tag>
|
||||
) : (
|
||||
<Tag color="green">清欠</Tag>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ padding: '0 15px' }}>
|
||||
<div style={{ padding: '10px 0', fontWeight: 'bold' }}>
|
||||
{res?.asset_house?.full_name}
|
||||
</div>
|
||||
{res.total_payable_sum - res.total_paid_sum ? (
|
||||
<div style={{ color: '#f00' }}>
|
||||
欠: ¥
|
||||
{(res.total_payable_sum - res.total_paid_sum).toFixed(
|
||||
2,
|
||||
)}
|
||||
元
|
||||
</div>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
padding: '15px 0 0 0',
|
||||
justifyContent: 'flex-end',
|
||||
}}
|
||||
>
|
||||
<MyModalPagination
|
||||
{...{ setParams: getSummaryBillList }}
|
||||
meta={getSummaryBillListData?.meta}
|
||||
/>
|
||||
</div>
|
||||
</ProCard>
|
||||
</Space>
|
||||
</div>
|
||||
</MyPageContainer>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import {
|
||||
MyButtons,
|
||||
MyColumns,
|
||||
MyImportModal,
|
||||
MyPageContainer,
|
||||
MyProTableProps,
|
||||
renderTextHelper,
|
||||
@ -21,20 +20,7 @@ export default function Index({ title = '员工管理' }) {
|
||||
const getCurrentPermissions = useCurrentPermissions();
|
||||
let toolBarRender = (action: any) => {
|
||||
return getCurrentPermissions({
|
||||
create: (
|
||||
<EmployeeCreate key="Create" reload={action?.reload} title="员工" />
|
||||
),
|
||||
export: (
|
||||
<MyImportModal
|
||||
key="ImportHouse"
|
||||
title="导入外部人员"
|
||||
type="default"
|
||||
size="middle"
|
||||
templateApi={Apis.Company.CompanyEmployees.DownloadTemplate}
|
||||
importApi={Apis.Company.CompanyEmployees.Import}
|
||||
reload={action?.reload}
|
||||
/>
|
||||
),
|
||||
add: <EmployeeCreate key="Create" reload={action?.reload} title="员工" />,
|
||||
});
|
||||
};
|
||||
let tableRender = (item: any, action: any) => {
|
||||
@ -42,14 +28,16 @@ export default function Index({ title = '员工管理' }) {
|
||||
update: (
|
||||
<EmployeeUpdate item={item} reload={action?.reload} title={title} />
|
||||
),
|
||||
change: <Change item={item} reload={action?.reload} title={title} />,
|
||||
CompanyEmployees: (
|
||||
<Change item={item} reload={action?.reload} title={title} />
|
||||
),
|
||||
});
|
||||
let permissionsSpace = getCurrentPermissions({
|
||||
Role: {
|
||||
key: '1',
|
||||
label: <Role item={item} reload={action?.reload} title={title} />,
|
||||
},
|
||||
resetPassword: {
|
||||
ResetPassword: {
|
||||
key: '2',
|
||||
label: (
|
||||
<MyButtons.Default
|
||||
@ -97,7 +85,6 @@ export default function Index({ title = '员工管理' }) {
|
||||
{...MyProTableProps.props}
|
||||
// search={false}
|
||||
headerTitle="员工列表"
|
||||
tooltip="通过企微同步的员工信息的修改,需在企微修改后,同步到系统,才能生效。"
|
||||
request={async (params, sort) =>
|
||||
MyProTableProps.request(
|
||||
params,
|
||||
@ -106,22 +93,6 @@ export default function Index({ title = '员工管理' }) {
|
||||
)
|
||||
}
|
||||
toolBarRender={(action) => [
|
||||
<MyButtons.Default
|
||||
key="sync_wechat_employees"
|
||||
type="primary"
|
||||
size="middle"
|
||||
title="企微同步"
|
||||
isConfirm={true}
|
||||
description="确定要执行企微同步操作吗?"
|
||||
onConfirm={async () => {
|
||||
try {
|
||||
await Apis.Company.CompanyEmployees.SyncWechatEmployees();
|
||||
action?.reload?.();
|
||||
} catch (error) {
|
||||
console.error('同步企微信息失败:', error);
|
||||
}
|
||||
}}
|
||||
/>,
|
||||
<CompletePhone
|
||||
key="CompletePhone"
|
||||
reload={action?.reload}
|
||||
|
||||
@ -7,7 +7,6 @@ import {
|
||||
|
||||
import { Selects } from '@/components/Select';
|
||||
import { Apis } from '@/gen/Apis';
|
||||
import { CompanyEmployeesTypeEnum } from '@/gen/Enums';
|
||||
import { BetaSchemaForm } from '@ant-design/pro-components';
|
||||
import { Form, message } from 'antd';
|
||||
export default function Update(props: MyBetaModalFormProps) {
|
||||
@ -16,15 +15,7 @@ export default function Update(props: MyBetaModalFormProps) {
|
||||
<BetaSchemaForm<ApiTypes.Company.CompanyEmployees.Update>
|
||||
{...MyModalFormProps.props}
|
||||
title={`组织调整`}
|
||||
trigger={
|
||||
<MyButtons.Edit
|
||||
title="组织"
|
||||
disabled={
|
||||
props.item?.type !== CompanyEmployeesTypeEnum.External.value
|
||||
}
|
||||
type="primary"
|
||||
/>
|
||||
}
|
||||
trigger={<MyButtons.Edit title="组织" type="primary" />}
|
||||
wrapperCol={{ span: 24 }}
|
||||
width="500px"
|
||||
key={new Date().getTime()}
|
||||
|
||||
@ -17,14 +17,14 @@ export default function Create(props: MyBetaModalFormProps) {
|
||||
return (
|
||||
<BetaSchemaForm<ApiTypes.Company.CompanyEmployees.Store>
|
||||
{...MyModalFormProps.props}
|
||||
title={`添加外部人员`}
|
||||
title={`添加${props?.title}`}
|
||||
layout="horizontal"
|
||||
labelCol={{ span: 5 }}
|
||||
wrapperCol={{ span: 19 }}
|
||||
labelAlign="left"
|
||||
width="500px"
|
||||
key={new Date().getTime()}
|
||||
trigger={<MyButtons.Create title={`外部人员`} />}
|
||||
trigger={<MyButtons.Create title={props?.title} />}
|
||||
form={form}
|
||||
onOpenChange={(open: any) => {
|
||||
if (open) {
|
||||
|
||||
@ -8,7 +8,7 @@ import {
|
||||
|
||||
import { Selects } from '@/components/Select';
|
||||
import { Apis } from '@/gen/Apis';
|
||||
import { CompanyEmployeesTypeEnum, SexEnum } from '@/gen/Enums';
|
||||
import { SexEnum } from '@/gen/Enums';
|
||||
import { BetaSchemaForm } from '@ant-design/pro-components';
|
||||
import { Form, message } from 'antd';
|
||||
export default function Update(props: MyBetaModalFormProps) {
|
||||
@ -17,17 +17,7 @@ export default function Update(props: MyBetaModalFormProps) {
|
||||
<BetaSchemaForm<ApiTypes.Company.CompanyEmployees.Update>
|
||||
{...MyModalFormProps.props}
|
||||
title={`编辑员工`}
|
||||
trigger={
|
||||
<MyButtons.Default
|
||||
title="编辑"
|
||||
type="primary"
|
||||
// variant="solid"
|
||||
size="small"
|
||||
disabled={
|
||||
props.item?.type !== CompanyEmployeesTypeEnum.External.value
|
||||
}
|
||||
/>
|
||||
}
|
||||
trigger={<MyButtons.Default title="编辑" type="primary" size="small" />}
|
||||
layout="horizontal"
|
||||
labelCol={{ span: 5 }}
|
||||
wrapperCol={{ span: 19 }}
|
||||
|
||||
@ -1,121 +0,0 @@
|
||||
import { Scene } from '@antv/l7';
|
||||
import { L7Layer } from '@antv/l7-leaflet';
|
||||
import { Choropleth } from '@antv/l7plot';
|
||||
import * as L from 'leaflet';
|
||||
import 'leaflet/dist/leaflet.css';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import map_bg_img from './images/map_bg_img.png';
|
||||
|
||||
export default function MapInfo() {
|
||||
const sceneRef = useRef<Scene>();
|
||||
|
||||
useEffect(() => {
|
||||
if (sceneRef.current) return;
|
||||
// 初始化地图场景
|
||||
const map = L.map('map', {
|
||||
center: [29.909571, 119.600006],
|
||||
zoom: 10,
|
||||
minZoom: 9,
|
||||
maxZoom: 10,
|
||||
zoomControl: false,
|
||||
attributionControl: false,
|
||||
}).setView([29.909571, 119.600006], 9);
|
||||
|
||||
const l7layer = new L7Layer({
|
||||
logoVisible: false,
|
||||
}).addTo(map);
|
||||
const scene: any = l7layer.getScene();
|
||||
// const scene = new Scene({
|
||||
// id: 'map', // 传递 DOM 元素
|
||||
// map: new Map({
|
||||
// style: 'blank',
|
||||
// pitch: 0,
|
||||
// rotation: 0,
|
||||
// center: [120.19382669582967, 30.258134],
|
||||
// zoom: 9,
|
||||
// minZoom: 8.5,
|
||||
// maxZoom: 9,
|
||||
// }),
|
||||
// });
|
||||
|
||||
sceneRef.current = scene;
|
||||
|
||||
scene.on('loaded', () => {
|
||||
// const imageLayer = new ImageLayer();
|
||||
// imageLayer.source(localMapImage, {
|
||||
// parser: {
|
||||
// type: 'image',
|
||||
// extent: [110, 27, 130, 45],
|
||||
// },
|
||||
// });
|
||||
// scene.addLayer(imageLayer);
|
||||
|
||||
const choropleth = new Choropleth({
|
||||
chinaBorder: false,
|
||||
source: {
|
||||
data: [],
|
||||
joinBy: {
|
||||
sourceField: 'name',
|
||||
geoField: 'value',
|
||||
},
|
||||
},
|
||||
viewLevel: {
|
||||
level: 'city',
|
||||
adcode: 330100,
|
||||
},
|
||||
autoFit: true,
|
||||
style: {
|
||||
opacity: 1,
|
||||
stroke: '#0083FF',
|
||||
lineWidth: 1,
|
||||
lineOpacity: 1,
|
||||
},
|
||||
label: {
|
||||
field: 'name',
|
||||
style: {
|
||||
fill: '#000',
|
||||
opacity: 1,
|
||||
fontSize: 15,
|
||||
strokeWidth: 1.5,
|
||||
},
|
||||
},
|
||||
state: {
|
||||
active: { stroke: '#0083FF', lineWidth: 1, fill: '#E4F2FF' },
|
||||
},
|
||||
});
|
||||
choropleth.addToScene(scene);
|
||||
});
|
||||
scene.on('resize', () => {
|
||||
console.log('resize');
|
||||
});
|
||||
|
||||
// 组件卸载时清理
|
||||
return () => {
|
||||
if (sceneRef.current) {
|
||||
sceneRef.current.destroy();
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '582px',
|
||||
position: 'relative',
|
||||
zIndex: 1,
|
||||
backgroundColor: '#fff',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
id="map"
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '582px',
|
||||
background: `url(${map_bg_img}) no-repeat bottom`,
|
||||
backgroundSize: '100%',
|
||||
}}
|
||||
></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -1,65 +0,0 @@
|
||||
import { MyBetaModalFormProps } from '@/common';
|
||||
import { Space } from 'antd';
|
||||
import MyOverviewClient from './charts/OverviewClient';
|
||||
import AddressIcon from './images/addressIcon.png';
|
||||
import ImgLeftIcon from './images/LeftIcon.png';
|
||||
import ImgMapTitleBg from './images/map_title_bg_img.svg';
|
||||
import MyMapAntL7 from './MapAntL7';
|
||||
import './styleMap.scss';
|
||||
export default function Map(props: MyBetaModalFormProps) {
|
||||
return (
|
||||
<Space direction="vertical" style={{ width: '100%' }} size="small">
|
||||
<div className="map_card">
|
||||
<MyMapAntL7 />
|
||||
<div className="map_card_contents">
|
||||
<img src={ImgMapTitleBg} className="map_card_title_bg" />
|
||||
<div className="map_data_contents">
|
||||
<div className="map_card_title">项目分布数据</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="map_card_data_contents">
|
||||
<div className="map_card_data">
|
||||
<div>
|
||||
<div className="map_card_data_title">
|
||||
<img src={ImgLeftIcon} />
|
||||
<span>用户总数</span>
|
||||
{/* <img src={ImgRightIcon} /> */}
|
||||
</div>
|
||||
<div className="map_card_data_number">
|
||||
{props?.item?.rankingData?.total_users}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="map_card_data">
|
||||
<div>
|
||||
<div className="map_card_data_title">
|
||||
<img src={ImgLeftIcon} />
|
||||
<span>管理户数</span>
|
||||
{/* <img src={ImgRightIcon} /> */}
|
||||
</div>
|
||||
<div className="map_card_data_number">
|
||||
{props?.item?.rankingData?.total_occupants}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="others_project">
|
||||
<div className="others_project_cell_list">
|
||||
<img src={AddressIcon} alt="" />
|
||||
<div>苏州3个项目</div>
|
||||
</div>
|
||||
<div className="others_project_cell_list">
|
||||
<img src={AddressIcon} alt="" />
|
||||
<div>南京3个项目</div>
|
||||
</div>
|
||||
<div className="others_project_cell_list">
|
||||
<img src={AddressIcon} alt="" />
|
||||
<div>上海8个项目</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<MyOverviewClient item={props?.item?.overviewData} />
|
||||
</Space>
|
||||
);
|
||||
}
|
||||
@ -1,163 +0,0 @@
|
||||
import { useMyState } from '@/common';
|
||||
import { Apis } from '@/gen/Apis';
|
||||
import { DoubleRightOutlined, RightOutlined } from '@ant-design/icons';
|
||||
import { ProCard } from '@ant-design/pro-components';
|
||||
import { useNavigate } from '@umijs/max';
|
||||
import { Progress, Space } from 'antd';
|
||||
import { useEffect, useState } from 'react';
|
||||
import ContractsToTalNumberBg from './images/ContractsToTalNumberBg.jpg';
|
||||
import InfoIcon from './images/info.png';
|
||||
import './styleLeft.scss';
|
||||
export default function OverviewContractData() {
|
||||
const { snap } = useMyState();
|
||||
const navigate = useNavigate();
|
||||
const [pendingCount, setPendingCount] = useState(0);
|
||||
const [contractCount, setContractCount] = useState(0);
|
||||
const [contractCountList, setContractCountList] = useState<any>([]);
|
||||
|
||||
const getPendingCount = async () => {
|
||||
const res = await Apis.Approval.ApprovalInstances.PendingCount();
|
||||
setPendingCount(res?.data?.count || 0);
|
||||
const res2 = await Apis.Statistics.IndexCount.ContractStatistics();
|
||||
setContractCount(res2?.data?.total);
|
||||
setContractCountList([
|
||||
{
|
||||
title: '未审批',
|
||||
number: res2?.data?.pending_approval,
|
||||
path: '/contract/contracts',
|
||||
status: 'TemporaryStorage',
|
||||
color: '#FF2427',
|
||||
},
|
||||
{
|
||||
title: '未用印',
|
||||
number: res2?.data?.pending_seal,
|
||||
path: '/contract/contracts',
|
||||
color: '#F9B01E',
|
||||
},
|
||||
{
|
||||
title: '未归档',
|
||||
number: res2?.data?.pending_archive,
|
||||
path: '/contract/contracts',
|
||||
color: '#FFD789',
|
||||
},
|
||||
{
|
||||
title: '待关闭',
|
||||
number: res2?.data?.pending_close,
|
||||
path: '/contract/contracts',
|
||||
color: '#2A7EFB',
|
||||
},
|
||||
{
|
||||
title: '审批中',
|
||||
number: res2?.data?.under_approval,
|
||||
status: 'UnderApproval',
|
||||
path: '/contract/contracts',
|
||||
color: '#2A7EFB',
|
||||
},
|
||||
{
|
||||
title: '30天内到期',
|
||||
number: res2?.data?.expiring_30_days,
|
||||
path: '/contract/contracts',
|
||||
color: '#2A7EFB',
|
||||
},
|
||||
{
|
||||
title: '60天内到期',
|
||||
number: res2?.data?.expiring_60_days,
|
||||
path: '/contract/contracts',
|
||||
color: '#2A7EFB',
|
||||
},
|
||||
{
|
||||
title: '履约中',
|
||||
number: res2?.data?.in_progress,
|
||||
path: '/contract/contracts',
|
||||
color: '#2A7EFB',
|
||||
},
|
||||
]);
|
||||
console.log(res);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getPendingCount();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Space direction="vertical" style={{ width: '100%' }} size="small">
|
||||
<ProCard className="border_radius_15px overview_contract_info_data_card">
|
||||
<div className="review_information">
|
||||
<div>
|
||||
<div className="info_title">
|
||||
{snap.session.user?.name || ''},欢迎回来!
|
||||
</div>
|
||||
<div
|
||||
className="info_content"
|
||||
onClick={() => {
|
||||
navigate('/approval/pending');
|
||||
}}
|
||||
>
|
||||
{pendingCount ? (
|
||||
<a>
|
||||
你有{pendingCount || 0}条待审核,请及时处理
|
||||
<DoubleRightOutlined />
|
||||
</a>
|
||||
) : (
|
||||
'暂无可审核信息'
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<img src={InfoIcon} alt="" />
|
||||
</div>
|
||||
</div>
|
||||
</ProCard>
|
||||
<ProCard
|
||||
style={{ width: '100%' }}
|
||||
title={<a href="/contract/contracts_bi">合同数据概览</a>}
|
||||
className="border_radius_15px overview_contract_data_card"
|
||||
headerBordered
|
||||
>
|
||||
<Space direction="vertical" style={{ width: '100%' }}>
|
||||
{/* <MyPageTitle title="合同数据概览" /> */}
|
||||
<div className="contracts_total_number">
|
||||
<img src={ContractsToTalNumberBg} alt="" />
|
||||
<div className="contracts_total_number_text">
|
||||
<div className="contracts_total_number_text_title">合同总数</div>
|
||||
<div className="contracts_total_number_text_number">
|
||||
{contractCount || 0}份
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Space direction="vertical" size={10} style={{ width: '100%' }}>
|
||||
{contractCountList?.map((res: any, index: number) => {
|
||||
return (
|
||||
<div key={`items_${index}`}>
|
||||
<a
|
||||
className="progress_title progress_title_first"
|
||||
onClick={() => {
|
||||
navigate(`${res?.path}?status=${res?.status}`);
|
||||
}}
|
||||
>
|
||||
<div className="progress_title_text">
|
||||
{res?.title} <RightOutlined />
|
||||
</div>
|
||||
<div
|
||||
className="progress_title_number"
|
||||
style={{ color: index < 3 ? res?.color : '#666' }}
|
||||
>
|
||||
{res?.number}份
|
||||
</div>
|
||||
</a>
|
||||
<Progress
|
||||
percent={res?.number}
|
||||
status="active"
|
||||
strokeColor={res?.color}
|
||||
size={['100%', 14]}
|
||||
showInfo={false}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</Space>
|
||||
</Space>
|
||||
</ProCard>
|
||||
</Space>
|
||||
);
|
||||
}
|
||||
@ -1,30 +0,0 @@
|
||||
export default function PageTitle(props: {
|
||||
title?: string;
|
||||
subTitle?: string;
|
||||
}) {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
borderLeft: '5px solid #1890FF',
|
||||
margin: '10px 0',
|
||||
fontSize: '15px',
|
||||
height: '23px',
|
||||
lineHeight: '23px',
|
||||
paddingLeft: '10px',
|
||||
display: 'flex',
|
||||
}}
|
||||
>
|
||||
<h2 style={{ display: 'inline-block' }}>{props.title || '标题'}</h2>
|
||||
<div
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
padding: '3px 0 0 5px',
|
||||
color: '#999',
|
||||
fontSize: '15px',
|
||||
}}
|
||||
>
|
||||
{props?.subTitle}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -1,50 +0,0 @@
|
||||
import { MyBetaModalFormProps } from '@/common';
|
||||
import { ProCard } from '@ant-design/pro-components';
|
||||
import { Space } from 'antd';
|
||||
import MyFinanceClient from './charts/FinanceClient';
|
||||
import Ranking1 from './images/Ranking1.png';
|
||||
import Ranking2 from './images/Ranking2.png';
|
||||
import Ranking3 from './images/Ranking3.png';
|
||||
import './styleRight.scss';
|
||||
export default function Ranking(props: MyBetaModalFormProps) {
|
||||
return (
|
||||
<Space direction="vertical" size="small" className="overview_ranking_right">
|
||||
<ProCard
|
||||
style={{ width: '100%', height: '582px' }}
|
||||
title="项目缴费率排名"
|
||||
className="border_radius_15px"
|
||||
headerBordered
|
||||
>
|
||||
<Space direction="vertical" size="large" style={{ width: '100%' }}>
|
||||
<div className="ranking_item_content">
|
||||
{props?.item?.rankingData?.payment_ranking?.map(
|
||||
(item: any, index: number) => {
|
||||
return (
|
||||
<div className="ranking_item" key={index}>
|
||||
{index < 3 ? (
|
||||
<img
|
||||
src={
|
||||
index === 0
|
||||
? Ranking1
|
||||
: index === 1
|
||||
? Ranking2
|
||||
: Ranking3
|
||||
}
|
||||
alt=""
|
||||
/>
|
||||
) : (
|
||||
<div className="ranking_number">{index + 1}</div>
|
||||
)}
|
||||
<div className="name">{item?.project_name}</div>
|
||||
<div className="number">{item?.payment_rate}%</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
)}
|
||||
</div>
|
||||
</Space>
|
||||
</ProCard>
|
||||
<MyFinanceClient item={props?.item?.overviewData} />
|
||||
</Space>
|
||||
);
|
||||
}
|
||||
@ -1,155 +0,0 @@
|
||||
export const workChartsData = [
|
||||
{
|
||||
name: '报修',
|
||||
月份: '1月',
|
||||
数量: 70,
|
||||
},
|
||||
{
|
||||
name: '报事',
|
||||
月份: '1月',
|
||||
数量: 20,
|
||||
},
|
||||
{
|
||||
name: '投诉',
|
||||
月份: '2月',
|
||||
数量: 10,
|
||||
},
|
||||
{
|
||||
name: '报修',
|
||||
月份: '2月',
|
||||
数量: 80,
|
||||
},
|
||||
{
|
||||
name: '报事',
|
||||
月份: '2月',
|
||||
数量: 40,
|
||||
},
|
||||
{
|
||||
name: '投诉',
|
||||
月份: '2月',
|
||||
数量: 6,
|
||||
},
|
||||
{
|
||||
name: '报修',
|
||||
月份: '3月',
|
||||
数量: 67,
|
||||
},
|
||||
{
|
||||
name: '报事',
|
||||
月份: '3月',
|
||||
数量: 27,
|
||||
},
|
||||
{
|
||||
name: '投诉',
|
||||
月份: '3月',
|
||||
数量: 7,
|
||||
},
|
||||
{
|
||||
name: '报修',
|
||||
月份: '4月',
|
||||
数量: 55,
|
||||
},
|
||||
{
|
||||
name: '报事',
|
||||
月份: '4月',
|
||||
数量: 17,
|
||||
},
|
||||
{
|
||||
name: '投诉',
|
||||
月份: '4月',
|
||||
数量: 9,
|
||||
},
|
||||
{
|
||||
name: '报修',
|
||||
月份: '5月',
|
||||
数量: 32,
|
||||
},
|
||||
{
|
||||
name: '报事',
|
||||
月份: '5月',
|
||||
数量: 27,
|
||||
},
|
||||
{
|
||||
name: '投诉',
|
||||
月份: '5月',
|
||||
数量: 11,
|
||||
},
|
||||
{
|
||||
name: '报修',
|
||||
月份: '6月',
|
||||
数量: 42,
|
||||
},
|
||||
{
|
||||
name: '报事',
|
||||
月份: '6月',
|
||||
数量: 7,
|
||||
},
|
||||
{
|
||||
name: '投诉',
|
||||
月份: '6月',
|
||||
数量: 21,
|
||||
},
|
||||
];
|
||||
|
||||
export const FinanceClientData = [
|
||||
{
|
||||
name: '应收',
|
||||
月份: '1月',
|
||||
数量: 200,
|
||||
},
|
||||
{
|
||||
name: '实收',
|
||||
月份: '1月',
|
||||
数量: 210,
|
||||
},
|
||||
{
|
||||
name: '应收',
|
||||
月份: '2月',
|
||||
数量: 170,
|
||||
},
|
||||
{
|
||||
name: '实收',
|
||||
月份: '2月',
|
||||
数量: 200,
|
||||
},
|
||||
{
|
||||
name: '应收',
|
||||
月份: '3月',
|
||||
数量: 270,
|
||||
},
|
||||
{
|
||||
name: '实收',
|
||||
月份: '3月',
|
||||
数量: 310,
|
||||
},
|
||||
{
|
||||
name: '应收',
|
||||
月份: '4月',
|
||||
数量: 230,
|
||||
},
|
||||
{
|
||||
name: '实收',
|
||||
月份: '4月',
|
||||
数量: 190,
|
||||
},
|
||||
{
|
||||
name: '应收',
|
||||
月份: '5月',
|
||||
数量: 170,
|
||||
},
|
||||
{
|
||||
name: '实收',
|
||||
月份: '5月',
|
||||
数量: 160,
|
||||
},
|
||||
{
|
||||
name: '应收',
|
||||
月份: '6月',
|
||||
数量: 250,
|
||||
},
|
||||
{
|
||||
name: '实收',
|
||||
月份: '6月',
|
||||
数量: 280,
|
||||
},
|
||||
];
|
||||
@ -1,39 +0,0 @@
|
||||
import { MyBetaModalFormProps } from '@/common';
|
||||
import { Column } from '@ant-design/plots';
|
||||
import { ProCard } from '@ant-design/pro-components';
|
||||
import { useEffect, useState } from 'react';
|
||||
export default function FinanceClient(props: MyBetaModalFormProps) {
|
||||
const [configData, setConfigData] = useState({});
|
||||
const config = {
|
||||
data: [],
|
||||
xField: '月份',
|
||||
yField: '数量',
|
||||
colorField: 'name',
|
||||
group: true,
|
||||
style: {
|
||||
// 矩形四个方向的内边距
|
||||
inset: 3,
|
||||
// 矩形单个方向的内边距
|
||||
// insetLeft:5,
|
||||
// insetRight:20,
|
||||
// insetBottom:10
|
||||
// insetTop:10
|
||||
},
|
||||
};
|
||||
useEffect(() => {
|
||||
console.log(props?.item?.financial, 'financial');
|
||||
setConfigData({ ...config, data: props?.item?.financial || [] });
|
||||
}, [props?.item?.financial]);
|
||||
return (
|
||||
<ProCard
|
||||
title={<a href="/work_order/work_bi">财务数据概览</a>}
|
||||
//跳转链接src/pages/work_order/work_bill/index.tsx
|
||||
|
||||
headerBordered
|
||||
className="border_radius_15px"
|
||||
style={{ height: 468, width: '100%', overflow: 'hidden' }}
|
||||
>
|
||||
<Column {...configData} />
|
||||
</ProCard>
|
||||
);
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
import { MyBetaModalFormProps } from '@/common';
|
||||
import { Column } from '@ant-design/plots';
|
||||
import { ProCard } from '@ant-design/pro-components';
|
||||
import { useEffect, useState } from 'react';
|
||||
export default function OverviewClient(props: MyBetaModalFormProps) {
|
||||
const [configData, setConfigData] = useState({});
|
||||
const config = {
|
||||
data: [],
|
||||
xField: '月份',
|
||||
yField: '数量',
|
||||
colorField: 'name',
|
||||
group: true,
|
||||
style: {
|
||||
// 矩形四个方向的内边距
|
||||
inset: 5,
|
||||
// 矩形单个方向的内边距
|
||||
// insetLeft:5,
|
||||
// insetRight:20,
|
||||
// insetBottom:10
|
||||
// insetTop:10
|
||||
},
|
||||
};
|
||||
useEffect(() => {
|
||||
console.log(props?.item?.work_order, 'financial');
|
||||
setConfigData({ ...config, data: props?.item?.work_order || [] });
|
||||
}, [props?.item?.work_order]);
|
||||
return (
|
||||
<ProCard
|
||||
title={<a href="/charge/charge_bi">工单数据概览</a>}
|
||||
headerBordered
|
||||
className="border_radius_15px"
|
||||
style={{ height: 468, width: '100%', overflow: 'hidden' }}
|
||||
>
|
||||
<Column {...configData} />
|
||||
</ProCard>
|
||||
);
|
||||
}
|
||||
|
Before Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 532 B |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 562 B |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 759 B |
|
Before Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 105 KiB |
|
Before Width: | Height: | Size: 1.0 KiB |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="714" height="47" viewBox="0 0 714 47"><g><g><g><path d="M212,17L231.661898,39.996876C235.461674,44.441154,241.016041,47,246.863251,47L467.13675,47C472.98395,47,478.53833,44.441154,482.3381,39.996877999999995L502,17L212,17Z" fill="#2A7EFB" fill-opacity="1"/></g><g><path d="M0,17L714,17L714,12.000001C714,6.4771528,709.52283,2,704,2L10.000001,2C4.4771528,2,0,6.4771528,0,12.000001L0,17Z" fill="#2A7EFB" fill-opacity="1"/></g></g><g><g><path d="M212,15L231.661898,37.996876C235.461674,42.441154,241.016041,45,246.863251,45L467.13675,45C472.98395,45,478.53833,42.441154,482.3381,37.996877999999995L502,15L212,15Z" fill="#E2F1FF" fill-opacity="1"/></g><g><path d="M0,15L714,15L714,10.000001C714,4.4771528,709.52283,0,704,0L10.000001,0C4.4771528,0,0,4.4771528,0,10.000001L0,15Z" fill="#E2F1FF" fill-opacity="1"/></g></g></g></svg>
|
||||
|
Before Width: | Height: | Size: 941 B |
@ -1,123 +0,0 @@
|
||||
.progress_title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 10px 0 8px 0;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #3d3d3d;
|
||||
&_number {
|
||||
color: #666;
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.review_information {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
img {
|
||||
width: 62px;
|
||||
height: 62px;
|
||||
}
|
||||
.info_title {
|
||||
color: #333;
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
}
|
||||
.info_content {
|
||||
color: #2a7efb;
|
||||
font-size: 14px;
|
||||
padding-top: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.overview_contract_info_data_card {
|
||||
height: 100px;
|
||||
}
|
||||
.overview_contract_data_card {
|
||||
height: 950px;
|
||||
}
|
||||
|
||||
/* 平板端 */
|
||||
@media (min-width: 768px) and (max-width: 1024px) {
|
||||
.contracts_total_number {
|
||||
.contracts_total_number_text {
|
||||
&_title {
|
||||
font-size: 15px;
|
||||
padding-top: 8px;
|
||||
}
|
||||
&_number {
|
||||
font-size: 28px;
|
||||
line-height: 35px;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 笔记本端 */
|
||||
@media (min-width: 1025px) and (max-width: 2000px) {
|
||||
.contracts_total_number {
|
||||
position: relative;
|
||||
padding: 15px 0 20px 0;
|
||||
width: 100%;
|
||||
img {
|
||||
width: 100%;
|
||||
border-radius: 15px;
|
||||
font-size: 0;
|
||||
}
|
||||
.contracts_total_number_text {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
padding: 15px;
|
||||
&_title {
|
||||
font-size: 15px;
|
||||
padding-top: 8px;
|
||||
}
|
||||
&_number {
|
||||
font-size: 28px;
|
||||
line-height: 35px;
|
||||
font-weight: 500;
|
||||
color: #2a7efb;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 台式机大屏幕 */
|
||||
@media (min-width: 2001px) {
|
||||
.contracts_total_number {
|
||||
position: relative;
|
||||
padding: 10px 0;
|
||||
width: 100%;
|
||||
img {
|
||||
width: 100%;
|
||||
border-radius: 15px;
|
||||
font-size: 0;
|
||||
}
|
||||
.contracts_total_number_text {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
padding: 15px;
|
||||
&_title {
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
padding-top: 16px;
|
||||
}
|
||||
&_number {
|
||||
font-size: 36px;
|
||||
line-height: 50px;
|
||||
font-weight: 500;
|
||||
color: #2a7efb;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,99 +0,0 @@
|
||||
.map_card {
|
||||
width: 100%;
|
||||
border-radius: 15px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.map_card_contents {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 4;
|
||||
.map_card_title_bg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
height: 70px;
|
||||
z-index: 1;
|
||||
}
|
||||
.map_data_contents {
|
||||
position: relative;
|
||||
z-index: 100;
|
||||
padding-top: 18px;
|
||||
}
|
||||
.map_card_title {
|
||||
color: #2a7efb;
|
||||
font-size: 1.8rem;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
.map_card_data_contents {
|
||||
position: absolute;
|
||||
top: 70px;
|
||||
left: 30px;
|
||||
z-index: 100;
|
||||
.map_card_data {
|
||||
// display: inline-block;
|
||||
// 换为 2 行
|
||||
// justify-content: center;
|
||||
// flex-wrap: wrap;
|
||||
// justify-content: space-between;
|
||||
// align-items: center;
|
||||
// display: inline-flex;
|
||||
// text-align: center;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
.map_card_data_title {
|
||||
color: #3d3d3d;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #0083ff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
// justify-content: space-between;
|
||||
span {
|
||||
padding: 0 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.map_card_data_number {
|
||||
padding: 10px 0 0 25px;
|
||||
color: #0083ff;
|
||||
font-size: 28px;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.others_project {
|
||||
position: absolute;
|
||||
right: 1px;
|
||||
bottom: 10px;
|
||||
z-index: 100;
|
||||
.others_project_cell_list {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
background: linear-gradient(
|
||||
270deg,
|
||||
rgba(124, 191, 255, 0) 0%,
|
||||
rgba(217, 236, 255, 0.67) 95%
|
||||
);
|
||||
padding: 0 10px 0 0;
|
||||
border-left: 5px solid #0083ff;
|
||||
margin-bottom: 20px;
|
||||
width: 200px;
|
||||
color: #0083ff;
|
||||
img {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin: 0 3px;
|
||||
}
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,112 +0,0 @@
|
||||
.ranking_item_content {
|
||||
width: 100%;
|
||||
padding: 0 0 32px 0;
|
||||
}
|
||||
.overview_ranking_right {
|
||||
width: 100%;
|
||||
}
|
||||
.ranking_item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: #f3f8fb;
|
||||
border-left: 5px solid #2a7efb;
|
||||
padding: 0 15px;
|
||||
margin-top: 24px;
|
||||
height: 73px;
|
||||
width: 100%;
|
||||
img {
|
||||
width: 33px;
|
||||
height: 40px;
|
||||
}
|
||||
.name {
|
||||
flex: 1;
|
||||
padding: 0 15px;
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
color: #3d3d3d;
|
||||
}
|
||||
.number {
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
padding-right: 5px;
|
||||
}
|
||||
.ranking_number {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 5px;
|
||||
font-size: 20px;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #fff;
|
||||
}
|
||||
&:first-child {
|
||||
background-color: #fff8eb;
|
||||
margin-top: 10px;
|
||||
border-left: 5px solid #faad14;
|
||||
.number {
|
||||
color: #faad14;
|
||||
}
|
||||
}
|
||||
&:nth-child(2) {
|
||||
background-color: #f3f8fb;
|
||||
border-left: 5px solid #b7c7d6;
|
||||
.number {
|
||||
color: #5f8db8;
|
||||
}
|
||||
}
|
||||
&:nth-child(3) {
|
||||
background-color: #fff9f4;
|
||||
border-left: 5px solid #dcb08e;
|
||||
.number {
|
||||
color: #d08143;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 平板端 */
|
||||
@media (min-width: 768px) and (max-width: 1024px) {
|
||||
}
|
||||
|
||||
/* 笔记本端 */
|
||||
@media (min-width: 1025px) and (max-width: 2000px) {
|
||||
.ranking_item {
|
||||
padding: 15px;
|
||||
.name {
|
||||
font-size: 16px;
|
||||
}
|
||||
.number {
|
||||
font-size: 16px;
|
||||
}
|
||||
.ranking_number {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 台式机大屏幕 */
|
||||
@media (min-width: 2001px) {
|
||||
}
|
||||
|
||||
// @media (min-width: 1400px) and (max-width: 2000px) {
|
||||
// .overview_ranking {
|
||||
// width: 100%;
|
||||
// }
|
||||
// .overview_ranking_right {
|
||||
// display: flex;
|
||||
// width: 100%;
|
||||
// align-items: self-start;
|
||||
// justify-content: space-between;
|
||||
// }
|
||||
// }
|
||||
|
||||
// @media (max-width: 1400px) {
|
||||
// .overview_ranking {
|
||||
// width: 100%;
|
||||
// }
|
||||
// }
|
||||
@ -1,45 +0,0 @@
|
||||
// import MyModalsMapLeaflet from '@/components/ModalsMapLeaflet';
|
||||
import { Apis } from '@/gen/Apis';
|
||||
import { useEffect, useState } from 'react';
|
||||
import MyMap from './components/MapContents';
|
||||
import MyOverviewContractData from './components/OverviewContractData';
|
||||
import MyRanking from './components/Ranking';
|
||||
import './style.scss';
|
||||
export default function Index() {
|
||||
const [overviewData, setOverviewData] = useState<any>({});
|
||||
const [rankingData, setRankingData] = useState<any>({});
|
||||
const getFinancialWorkOverview = async () => {
|
||||
const res =
|
||||
await Apis.Statistics.IndexCount.FinancialAndWorkOrderOverview();
|
||||
setOverviewData(res?.data);
|
||||
const res_s =
|
||||
await Apis.Statistics.IndexCount.ProjectDistributionAndPaymentRanking();
|
||||
setRankingData(res_s?.data);
|
||||
console.log(res, 'res');
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getFinancialWorkOverview();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="overview_content">
|
||||
<div className="overview_contract_data">
|
||||
{/* <MyModalsMapLeaflet /> */}
|
||||
<MyOverviewContractData />
|
||||
</div>
|
||||
<div className="overview_map">
|
||||
<div className="overview_map_content">
|
||||
<MyMap
|
||||
item={{ overviewData: overviewData, rankingData: rankingData }}
|
||||
/>
|
||||
</div>
|
||||
<div className="overview_ranking">
|
||||
<MyRanking
|
||||
item={{ overviewData: overviewData, rankingData: rankingData }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -1,70 +0,0 @@
|
||||
.overview_content {
|
||||
margin: -20px !important;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.overview_map {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
align-items: flex-start;
|
||||
}
|
||||
.overview_contract_data {
|
||||
margin-right: 10px;
|
||||
min-width: 280px;
|
||||
}
|
||||
.overview_map_content {
|
||||
flex: 1;
|
||||
}
|
||||
.overview_ranking {
|
||||
margin-left: 10px;
|
||||
min-width: 280px;
|
||||
}
|
||||
|
||||
.border_radius_15px {
|
||||
border-radius: 15px;
|
||||
}
|
||||
|
||||
/* 平板端 */
|
||||
@media (min-width: 768px) and (max-width: 1024px) {
|
||||
}
|
||||
/* 笔记本端 */
|
||||
@media (min-width: 1025px) and (max-width: 2000px) {
|
||||
.overview_contract_data {
|
||||
width: 28%;
|
||||
}
|
||||
.overview_ranking {
|
||||
width: 32%;
|
||||
}
|
||||
}
|
||||
|
||||
/* 台式机大屏幕 */
|
||||
@media (min-width: 2001px) {
|
||||
.overview_contract_data {
|
||||
width: 380px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
.overview_ranking {
|
||||
width: 430px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
// @media (min-width: 1400px) and (max-width: 2000px) {
|
||||
// .overview_content {
|
||||
// width: 100%;
|
||||
// margin: 0 auto;
|
||||
// flex-wrap: wrap;
|
||||
// }
|
||||
// }
|
||||
|
||||
// @media (max-width: 1400px) {
|
||||
// .overview_content {
|
||||
// flex-wrap: wrap;
|
||||
// width: 100%;
|
||||
// margin: 0 auto;
|
||||
// }
|
||||
// }
|
||||
@ -1,24 +0,0 @@
|
||||
import { MyBetaModalFormProps } from '@/common';
|
||||
import { Column } from '@ant-design/plots';
|
||||
import { useEffect, useState } from 'react';
|
||||
export default function AnalysisClient(props: MyBetaModalFormProps) {
|
||||
const [configData, setConfigData] = useState({});
|
||||
const config = {
|
||||
data: [],
|
||||
xField: '月份',
|
||||
yField: '数量',
|
||||
group: true,
|
||||
style: {
|
||||
// 矩形四个方向的内边距
|
||||
inset: 3,
|
||||
},
|
||||
};
|
||||
useEffect(() => {
|
||||
setConfigData({ ...config, data: props?.item?.chart || [] });
|
||||
}, [props?.item?.chart]);
|
||||
return (
|
||||
<div style={{ height: 303 }}>
|
||||
<Column {...configData} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -1,155 +0,0 @@
|
||||
export const workChartsData = [
|
||||
{
|
||||
name: '物业费',
|
||||
月份: '1月',
|
||||
数量: 70,
|
||||
},
|
||||
{
|
||||
name: '工单',
|
||||
月份: '1月',
|
||||
数量: 20,
|
||||
},
|
||||
{
|
||||
name: '停车费',
|
||||
月份: '2月',
|
||||
数量: 10,
|
||||
},
|
||||
{
|
||||
name: '物业费',
|
||||
月份: '2月',
|
||||
数量: 80,
|
||||
},
|
||||
{
|
||||
name: '工单',
|
||||
月份: '2月',
|
||||
数量: 40,
|
||||
},
|
||||
{
|
||||
name: '停车费',
|
||||
月份: '2月',
|
||||
数量: 6,
|
||||
},
|
||||
{
|
||||
name: '物业费',
|
||||
月份: '3月',
|
||||
数量: 67,
|
||||
},
|
||||
{
|
||||
name: '工单',
|
||||
月份: '3月',
|
||||
数量: 27,
|
||||
},
|
||||
{
|
||||
name: '停车费',
|
||||
月份: '3月',
|
||||
数量: 7,
|
||||
},
|
||||
{
|
||||
name: '物业费',
|
||||
月份: '4月',
|
||||
数量: 55,
|
||||
},
|
||||
{
|
||||
name: '工单',
|
||||
月份: '4月',
|
||||
数量: 17,
|
||||
},
|
||||
{
|
||||
name: '停车费',
|
||||
月份: '4月',
|
||||
数量: 9,
|
||||
},
|
||||
{
|
||||
name: '物业费',
|
||||
月份: '5月',
|
||||
数量: 32,
|
||||
},
|
||||
{
|
||||
name: '工单',
|
||||
月份: '5月',
|
||||
数量: 27,
|
||||
},
|
||||
{
|
||||
name: '停车费',
|
||||
月份: '5月',
|
||||
数量: 11,
|
||||
},
|
||||
{
|
||||
name: '物业费',
|
||||
月份: '6月',
|
||||
数量: 42,
|
||||
},
|
||||
{
|
||||
name: '工单',
|
||||
月份: '6月',
|
||||
数量: 7,
|
||||
},
|
||||
{
|
||||
name: '停车费',
|
||||
月份: '6月',
|
||||
数量: 21,
|
||||
},
|
||||
];
|
||||
|
||||
export const FinanceClientData = [
|
||||
{
|
||||
name: '应收',
|
||||
月份: '1月',
|
||||
数量: 200,
|
||||
},
|
||||
{
|
||||
name: '实收',
|
||||
月份: '1月',
|
||||
数量: 210,
|
||||
},
|
||||
{
|
||||
name: '应收',
|
||||
月份: '2月',
|
||||
数量: 170,
|
||||
},
|
||||
{
|
||||
name: '实收',
|
||||
月份: '2月',
|
||||
数量: 200,
|
||||
},
|
||||
{
|
||||
name: '应收',
|
||||
月份: '3月',
|
||||
数量: 270,
|
||||
},
|
||||
{
|
||||
name: '实收',
|
||||
月份: '3月',
|
||||
数量: 310,
|
||||
},
|
||||
{
|
||||
name: '应收',
|
||||
月份: '4月',
|
||||
数量: 230,
|
||||
},
|
||||
{
|
||||
name: '实收',
|
||||
月份: '4月',
|
||||
数量: 190,
|
||||
},
|
||||
{
|
||||
name: '应收',
|
||||
月份: '5月',
|
||||
数量: 170,
|
||||
},
|
||||
{
|
||||
name: '实收',
|
||||
月份: '5月',
|
||||
数量: 160,
|
||||
},
|
||||
{
|
||||
name: '应收',
|
||||
月份: '6月',
|
||||
数量: 250,
|
||||
},
|
||||
{
|
||||
name: '实收',
|
||||
月份: '6月',
|
||||
数量: 280,
|
||||
},
|
||||
];
|
||||
@ -1,91 +0,0 @@
|
||||
import { Apis } from '@/gen/Apis';
|
||||
import { Pie } from '@ant-design/plots';
|
||||
import { Space } from 'antd';
|
||||
import { useEffect, useState } from 'react';
|
||||
export default function FinancialAnalysisLine() {
|
||||
const [getPieCount, setPieCount] = useState<any>({});
|
||||
const config = {
|
||||
data: [],
|
||||
angleField: '数量',
|
||||
colorField: 'name',
|
||||
innerRadius: 0.8,
|
||||
radius: 0.5,
|
||||
style: {
|
||||
width: '60px',
|
||||
},
|
||||
label: {
|
||||
text: '数量',
|
||||
style: {
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const getPieData = async () => {
|
||||
const res = await Apis.Statistics.IndexCount.ContractStatistics();
|
||||
setPieCount({
|
||||
...config,
|
||||
data: res?.data?.items,
|
||||
legend: {
|
||||
color: {
|
||||
render: (legendItem: any, item: any) => {
|
||||
console.log(legendItem, item, 'legendItem');
|
||||
// 这里可以返回 React 节点或 HTML 字符串
|
||||
return (
|
||||
<Space size="small">
|
||||
{legendItem?.map((row: any, index: number) => {
|
||||
return (
|
||||
<Space key={`item_${index}`}>
|
||||
<div
|
||||
style={{
|
||||
width: 8,
|
||||
height: 8,
|
||||
backgroundColor: row?.color,
|
||||
borderRadius: 100,
|
||||
fontSize: 12,
|
||||
}}
|
||||
/>
|
||||
{row?.label}
|
||||
{
|
||||
res?.data?.items?.find(
|
||||
(i: any) => i.name === row?.label,
|
||||
)?.数量
|
||||
}
|
||||
</Space>
|
||||
);
|
||||
})}
|
||||
</Space>
|
||||
);
|
||||
},
|
||||
title: false,
|
||||
position: 'top',
|
||||
rowPadding: 5,
|
||||
},
|
||||
},
|
||||
annotations: [
|
||||
{
|
||||
type: 'text',
|
||||
style: {
|
||||
text: `${res?.data?.total}\n合同总数`,
|
||||
x: '50%',
|
||||
y: '50%',
|
||||
textAlign: 'center',
|
||||
fontSize: 20,
|
||||
fontStyle: 'bold',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
console.log(res, 'res');
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getPieData();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div style={{ height: 430 }}>
|
||||
<Pie {...getPieCount} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -1,50 +0,0 @@
|
||||
import { MyBetaModalFormProps } from '@/common';
|
||||
import { Line } from '@ant-design/plots';
|
||||
import { useEffect, useState } from 'react';
|
||||
export default function FinancialAnalysisLine(props: MyBetaModalFormProps) {
|
||||
const [houseBillsCount, setHouseBillsCount] = useState<any>({});
|
||||
const config = {
|
||||
data: [],
|
||||
xField: '月份',
|
||||
yField: '金额',
|
||||
colorField: 'name',
|
||||
point: {
|
||||
size: 7,
|
||||
},
|
||||
legend: {
|
||||
position: 'top',
|
||||
},
|
||||
tooltip: {},
|
||||
style: {
|
||||
// 矩形四个方向的内边距
|
||||
inset: 5,
|
||||
},
|
||||
|
||||
// 使用双Y轴,因为两个指标数值范围差异大
|
||||
yAxis: [
|
||||
{
|
||||
title: {
|
||||
text: '月收款(万元)',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: {
|
||||
text: '收缴率(%)',
|
||||
},
|
||||
grid: null,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (props?.item?.chart?.length) {
|
||||
setHouseBillsCount({ ...config, data: props?.item?.chart || [] });
|
||||
}
|
||||
}, [props?.item?.chart]);
|
||||
|
||||
return (
|
||||
<div style={{ height: 290 }}>
|
||||
<Line {...houseBillsCount} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -1,93 +0,0 @@
|
||||
import { MyBetaModalFormProps } from '@/common';
|
||||
import { Pie } from '@ant-design/plots';
|
||||
import { Space } from 'antd';
|
||||
import { useEffect, useState } from 'react';
|
||||
export default function WorkOrderPie(props: MyBetaModalFormProps) {
|
||||
const [getPieCount, setPieCount] = useState<any>({});
|
||||
const config = {
|
||||
data: [],
|
||||
angleField: '数量',
|
||||
colorField: 'name',
|
||||
innerRadius: 0.8,
|
||||
radius: 0.5,
|
||||
style: {
|
||||
width: '60px',
|
||||
},
|
||||
label: {
|
||||
text: '数量',
|
||||
style: {
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setPieCount({
|
||||
...config,
|
||||
data: props?.item?.statistics?.items,
|
||||
legend: {
|
||||
color: {
|
||||
render: (legendItem: any, item: any) => {
|
||||
console.log(legendItem, item, 'legendItem');
|
||||
// 这里可以返回 React 节点或 HTML 字符串
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
fontSize: 12,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
flexWrap: 'wrap',
|
||||
gap: '10px',
|
||||
}}
|
||||
>
|
||||
{legendItem?.map((row: any, index: number) => {
|
||||
return (
|
||||
<Space key={`item_${index}`}>
|
||||
<div
|
||||
style={{
|
||||
width: 8,
|
||||
height: 8,
|
||||
backgroundColor: row?.color,
|
||||
borderRadius: 100,
|
||||
fontSize: 12,
|
||||
}}
|
||||
/>
|
||||
{row?.label}
|
||||
{
|
||||
props?.item?.statistics?.items?.find(
|
||||
(i: any) => i.name === row?.label,
|
||||
)?.数量
|
||||
}
|
||||
</Space>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
title: false,
|
||||
position: 'top',
|
||||
rowPadding: 5,
|
||||
},
|
||||
},
|
||||
annotations: [
|
||||
{
|
||||
type: 'text',
|
||||
style: {
|
||||
text: `${props?.item?.statistics?.total}\n工单总数`,
|
||||
x: '50%',
|
||||
y: '50%',
|
||||
textAlign: 'center',
|
||||
fontSize: 20,
|
||||
fontStyle: 'bold',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}, [props?.item?.statistics?.items]);
|
||||
|
||||
return (
|
||||
<div style={{ height: 430 }}>
|
||||
<Pie {...getPieCount} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -1,132 +0,0 @@
|
||||
[
|
||||
{
|
||||
"name": "上城区",
|
||||
"level": "district",
|
||||
"adcode": 330102,
|
||||
"lng": 120.19732,
|
||||
"lat": 30.226543,
|
||||
"childrenNum": 0,
|
||||
"parent": 330100,
|
||||
"value": 41.040194955144216
|
||||
},
|
||||
{
|
||||
"name": "拱墅区",
|
||||
"level": "district",
|
||||
"adcode": 330105,
|
||||
"lng": 120.141503,
|
||||
"lat": 30.319126,
|
||||
"childrenNum": 0,
|
||||
"parent": 330100,
|
||||
"value": 741.6573303294999
|
||||
},
|
||||
{
|
||||
"name": "西湖区",
|
||||
"level": "district",
|
||||
"adcode": 330106,
|
||||
"lng": 120.130396,
|
||||
"lat": 30.259242,
|
||||
"childrenNum": 0,
|
||||
"parent": 330100,
|
||||
"value": 2948.4079430920074
|
||||
},
|
||||
{
|
||||
"name": "滨江区",
|
||||
"level": "district",
|
||||
"adcode": 330108,
|
||||
"lng": 120.211981,
|
||||
"lat": 30.208332,
|
||||
"childrenNum": 0,
|
||||
"parent": 330100,
|
||||
"value": 49.89546143372991
|
||||
},
|
||||
{
|
||||
"name": "萧山区",
|
||||
"level": "district",
|
||||
"adcode": 330109,
|
||||
"lng": 120.264263,
|
||||
"lat": 30.184119,
|
||||
"childrenNum": 0,
|
||||
"parent": 330100,
|
||||
"value": 2384.034354262634
|
||||
},
|
||||
{
|
||||
"name": "余杭区",
|
||||
"level": "district",
|
||||
"adcode": 330110,
|
||||
"lng": 119.978742,
|
||||
"lat": 30.273705,
|
||||
"childrenNum": 0,
|
||||
"parent": 330100,
|
||||
"value": 1882.4494466789638
|
||||
},
|
||||
{
|
||||
"name": "富阳区",
|
||||
"level": "district",
|
||||
"adcode": 330111,
|
||||
"lng": 119.96022,
|
||||
"lat": 30.048803,
|
||||
"childrenNum": 0,
|
||||
"parent": 330100,
|
||||
"value": 560.1787727190821
|
||||
},
|
||||
{
|
||||
"name": "临安区",
|
||||
"level": "district",
|
||||
"adcode": 330112,
|
||||
"lng": 119.724457,
|
||||
"lat": 30.234375,
|
||||
"childrenNum": 0,
|
||||
"parent": 330100,
|
||||
"value": 4051.1361966943305
|
||||
},
|
||||
{
|
||||
"name": "临平区",
|
||||
"level": "district",
|
||||
"adcode": 330113,
|
||||
"lng": 120.299222,
|
||||
"lat": 30.419154,
|
||||
"childrenNum": 0,
|
||||
"parent": 330100,
|
||||
"value": 4071.9384042194924
|
||||
},
|
||||
{
|
||||
"name": "钱塘区",
|
||||
"level": "district",
|
||||
"adcode": 330114,
|
||||
"lng": 120.493941,
|
||||
"lat": 30.32304,
|
||||
"childrenNum": 0,
|
||||
"parent": 330100,
|
||||
"value": 1813.6359839537997
|
||||
},
|
||||
{
|
||||
"name": "桐庐县",
|
||||
"level": "district",
|
||||
"adcode": 330122,
|
||||
"lng": 119.691755,
|
||||
"lat": 29.79418,
|
||||
"childrenNum": 0,
|
||||
"parent": 330100,
|
||||
"value": 2089.953961851202
|
||||
},
|
||||
{
|
||||
"name": "淳安县",
|
||||
"level": "district",
|
||||
"adcode": 330127,
|
||||
"lng": 119.042015,
|
||||
"lat": 29.609678,
|
||||
"childrenNum": 0,
|
||||
"parent": 330100,
|
||||
"value": 978.0639544756548
|
||||
},
|
||||
{
|
||||
"name": "建德市",
|
||||
"level": "district",
|
||||
"adcode": 330182,
|
||||
"lng": 119.281195,
|
||||
"lat": 29.474964,
|
||||
"childrenNum": 0,
|
||||
"parent": 330100,
|
||||
"value": 4427.419741967931
|
||||
}
|
||||
]
|
||||
@ -1,60 +0,0 @@
|
||||
import { Apis } from '@/gen/Apis';
|
||||
import { RightOutlined } from '@ant-design/icons';
|
||||
import { useNavigate } from '@umijs/max';
|
||||
import { Space } from 'antd';
|
||||
import { useEffect, useState } from 'react';
|
||||
import AnalysisClient from '../charts/AnalysisClient';
|
||||
|
||||
export default function AssetManagementAnalysis() {
|
||||
const navigate = useNavigate();
|
||||
const [getAssetAnalysis, setAssetAnalysis] = useState<any>({});
|
||||
const getAssetAnalysisApi = async () => {
|
||||
const res = await Apis.Statistics.IndexCount.AssetAnalysis();
|
||||
setAssetAnalysis(res?.data);
|
||||
console.log(res, 'res');
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getAssetAnalysisApi();
|
||||
}, []);
|
||||
return (
|
||||
<Space direction="vertical" size="middle" style={{ width: '100%' }}>
|
||||
<div className="asset_management_analysis_data">
|
||||
<div
|
||||
style={{ cursor: 'pointer' }}
|
||||
onClick={() => {
|
||||
navigate('/asset/asset_items');
|
||||
}}
|
||||
>
|
||||
<div className="label">
|
||||
资产仓库 <RightOutlined />
|
||||
</div>
|
||||
<div className="value">{getAssetAnalysis?.total || 0}</div>
|
||||
</div>
|
||||
<div
|
||||
style={{ cursor: 'pointer' }}
|
||||
onClick={() => {
|
||||
navigate('/asset/asset_items');
|
||||
}}
|
||||
>
|
||||
<div className="label">
|
||||
资产总数 <RightOutlined />
|
||||
</div>
|
||||
<div className="value">{getAssetAnalysis?.total_price || 0}</div>
|
||||
</div>
|
||||
<div
|
||||
style={{ cursor: 'pointer' }}
|
||||
onClick={() => {
|
||||
navigate('/asset/asset_items');
|
||||
}}
|
||||
>
|
||||
<div className="label">
|
||||
闲置资产 <RightOutlined />
|
||||
</div>
|
||||
<div className="value">{getAssetAnalysis?.idle_count || 0}</div>
|
||||
</div>
|
||||
</div>
|
||||
<AnalysisClient item={getAssetAnalysis} />
|
||||
</Space>
|
||||
);
|
||||
}
|
||||
@ -1,82 +0,0 @@
|
||||
import { Apis } from '@/gen/Apis';
|
||||
import { ProCard } from '@ant-design/pro-components';
|
||||
import { Space } from 'antd';
|
||||
import { useEffect, useState } from 'react';
|
||||
import AssetManagementAnalysis from './AssetManagementAnalysis';
|
||||
import ImgLeftIcon from './images/LeftIcon.png';
|
||||
import ImgMapTitleBg from './images/map_title_bg_img.svg';
|
||||
import MapAntL7 from './MapAntL7';
|
||||
import './styleCenter.scss';
|
||||
import './styleMap.scss';
|
||||
|
||||
export default function CardCenter() {
|
||||
const [loginStatus, setLoginStatus] = useState<boolean>(false);
|
||||
const [dataInfo, setDataInfo] = useState<any>({});
|
||||
const getProjectDistributionAndPaymentRanking = async () => {
|
||||
const res =
|
||||
await Apis.Statistics.IndexCount.ProjectDistributionAndPaymentRanking();
|
||||
setLoginStatus(true);
|
||||
setDataInfo(res?.data);
|
||||
};
|
||||
useEffect(() => {
|
||||
getProjectDistributionAndPaymentRanking();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Space direction="vertical" size="middle" style={{ width: '100%' }}>
|
||||
<div className="map_card">
|
||||
{loginStatus ? <MapAntL7 item={dataInfo} /> : ''}
|
||||
<div className="map_card_contents">
|
||||
<img src={ImgMapTitleBg} className="map_card_title_bg" />
|
||||
<div className="map_data_contents">
|
||||
<div className="map_card_title">项目分布数据</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="map_card_data_contents">
|
||||
<div className="map_card_data">
|
||||
<div>
|
||||
<div className="map_card_data_title">
|
||||
<img src={ImgLeftIcon} />
|
||||
<span>管理户数</span>
|
||||
{/* <img src={ImgRightIcon} /> */}
|
||||
</div>
|
||||
<div className="map_card_data_number">
|
||||
{dataInfo?.total_users || 0}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="map_card_data">
|
||||
<div>
|
||||
<div className="map_card_data_title">
|
||||
<img src={ImgLeftIcon} />
|
||||
<span>员工总数</span>
|
||||
{/* <img src={ImgRightIcon} /> */}
|
||||
</div>
|
||||
<div className="map_card_data_number">
|
||||
{dataInfo?.total_occupants || 0}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* <div className="others_project">
|
||||
<div className="others_project_cell_list">
|
||||
<img src={AddressIcon} alt="" />
|
||||
<div>苏州3个项目</div>
|
||||
</div>
|
||||
<div className="others_project_cell_list">
|
||||
<img src={AddressIcon} alt="" />
|
||||
<div>南京3个项目</div>
|
||||
</div>
|
||||
<div className="others_project_cell_list">
|
||||
<img src={AddressIcon} alt="" />
|
||||
<div>上海8个项目</div>
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
<ProCard title="资产管理分析" style={{ borderRadius: '10px' }}>
|
||||
<AssetManagementAnalysis />
|
||||
</ProCard>
|
||||
</Space>
|
||||
);
|
||||
}
|
||||
@ -1,34 +0,0 @@
|
||||
import { Apis } from '@/gen/Apis';
|
||||
import { ProCard } from '@ant-design/pro-components';
|
||||
import { Space } from 'antd';
|
||||
import { useEffect, useState } from 'react';
|
||||
import ContractStatisticalAnalysis from '../charts/ContractStatisticalAnalysis';
|
||||
import FinancialAnalysisLine from '../charts/FinancialAnalysisLine';
|
||||
import FinancialAnalysis from './FinancialAnalysis';
|
||||
import './styleLeft.scss';
|
||||
export default function CardLeft() {
|
||||
const [getFinancialAnalysis, setFinancialAnalysis] = useState<any>({});
|
||||
const getFinancialWorkOverview = async () => {
|
||||
const res = await Apis.Statistics.IndexCount.FinancialAnalysis();
|
||||
setFinancialAnalysis(res?.data);
|
||||
|
||||
console.log(res, 'res');
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getFinancialWorkOverview();
|
||||
}, []);
|
||||
return (
|
||||
<Space direction="vertical" size="middle" style={{ width: '100%' }}>
|
||||
<ProCard title="财务分析">
|
||||
<Space direction="vertical" size="middle" style={{ width: '100%' }}>
|
||||
<FinancialAnalysis item={getFinancialAnalysis} />
|
||||
<FinancialAnalysisLine item={getFinancialAnalysis} />
|
||||
</Space>
|
||||
</ProCard>
|
||||
<ProCard title="合同统计分析">
|
||||
<ContractStatisticalAnalysis />
|
||||
</ProCard>
|
||||
</Space>
|
||||
);
|
||||
}
|
||||
@ -1,77 +0,0 @@
|
||||
import { Apis } from '@/gen/Apis';
|
||||
import { ProCard } from '@ant-design/pro-components';
|
||||
import { Progress, Space } from 'antd';
|
||||
import { useEffect, useState } from 'react';
|
||||
import WorkOrderPie from '../charts/WorkOrderPie';
|
||||
import PendingApplicationForm from './PendingApplicationForm';
|
||||
import './styleRight.scss';
|
||||
export default function CardRight() {
|
||||
const [getAssetAnalysis, setAssetAnalysis] = useState<any>({});
|
||||
const getAssetAnalysisApi = async () => {
|
||||
const res = await Apis.Statistics.IndexCount.WorkOrderAnalysis();
|
||||
setAssetAnalysis(res);
|
||||
console.log(res, 'res');
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getAssetAnalysisApi();
|
||||
}, []);
|
||||
return (
|
||||
<div className="card_right">
|
||||
<Space direction="vertical" size="middle" style={{ width: '100%' }}>
|
||||
<ProCard title="工单分析">
|
||||
<PendingApplicationForm item={getAssetAnalysis?.data} />
|
||||
</ProCard>
|
||||
<ProCard title="工单统计">
|
||||
<WorkOrderPie item={getAssetAnalysis} />
|
||||
</ProCard>
|
||||
<ProCard title="工单数据">
|
||||
<div className="work_order_data">
|
||||
<div className="work_order_data_item">
|
||||
<Progress
|
||||
type="dashboard"
|
||||
size={[160, 30]}
|
||||
percent={getAssetAnalysis?.data?.metrics?.completion_rate || 0}
|
||||
format={(percent) => {
|
||||
return (
|
||||
<div className="dashboard_progress">
|
||||
<div className="dashboard_value">{`${percent}%`}</div>
|
||||
<div className="dashboard_label">完成率</div>
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<div className="work_order_data_cell">
|
||||
已完成:{getAssetAnalysis?.data?.metrics?.completed_count || 0}
|
||||
</div>
|
||||
<div className="work_order_data_cell">
|
||||
已关闭:{getAssetAnalysis?.data?.metrics?.closed_count || 0}
|
||||
</div>
|
||||
</div>
|
||||
<div className="work_order_data_item">
|
||||
<Progress
|
||||
type="dashboard"
|
||||
size={[160, 30]}
|
||||
percent={getAssetAnalysis?.data?.metrics?.approval_rate || 0}
|
||||
format={(percent) => {
|
||||
return (
|
||||
<div className="dashboard_progress">
|
||||
<div className="dashboard_value">{`${percent}%`}</div>
|
||||
<div className="dashboard_label">好评率</div>
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<div className="work_order_data_cell">
|
||||
已评价:{getAssetAnalysis?.data?.metrics?.evaluated_count || 0}
|
||||
</div>
|
||||
<div className="work_order_data_cell">
|
||||
已好评:{getAssetAnalysis?.data?.metrics?.positive_count || 0}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ProCard>
|
||||
</Space>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -1,36 +0,0 @@
|
||||
import { MyBetaModalFormProps } from '@/common';
|
||||
|
||||
export default function FinancialAnalysis(props: MyBetaModalFormProps) {
|
||||
return (
|
||||
<div className="financial_analysis">
|
||||
<div className="financial_analysis_item">
|
||||
<div className="value">
|
||||
{props?.item?.month_received || '0'}
|
||||
<span>元</span>
|
||||
</div>
|
||||
<div className="title">本月收款</div>
|
||||
</div>
|
||||
<div className="financial_analysis_item">
|
||||
<div className="value">
|
||||
{props?.item?.year_received || '0'}
|
||||
<span>元</span>
|
||||
</div>
|
||||
<div className="title">年度收款</div>
|
||||
</div>
|
||||
<div className="financial_analysis_item">
|
||||
<div className="value">
|
||||
{props?.item?.month_rate || '0'}
|
||||
<span>%</span>
|
||||
</div>
|
||||
<div className="title">月度收缴率</div>
|
||||
</div>
|
||||
<div className="financial_analysis_item">
|
||||
<div className="value">
|
||||
{props?.item?.year_rate || '0'}
|
||||
<span>%</span>
|
||||
</div>
|
||||
<div className="title">年度收缴率</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -1,129 +0,0 @@
|
||||
import { MyBetaModalFormProps } from '@/common';
|
||||
import { Scene } from '@antv/l7';
|
||||
import { L7Layer } from '@antv/l7-leaflet';
|
||||
import { Choropleth } from '@antv/l7plot';
|
||||
import * as L from 'leaflet';
|
||||
import 'leaflet/dist/leaflet.css';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import ListArea from './AreaInfoList.json';
|
||||
import map_bg_img from './images/map_bg_img.png';
|
||||
|
||||
export default function MapInfo(props: MyBetaModalFormProps) {
|
||||
const sceneRef = useRef<Scene>();
|
||||
|
||||
const getProjectDistributionAndPaymentRanking = async () => {
|
||||
let dataJson: any = [];
|
||||
console.log(props?.item?.area_stats, 'props?.item?.area_stats');
|
||||
props?.item?.area_stats?.map((item: any) => {
|
||||
ListArea?.map((i: any) => {
|
||||
if (i?.name === item?.name) {
|
||||
dataJson?.push({
|
||||
...i,
|
||||
name: `${i?.name}(${item?.value}个)`,
|
||||
数量: `${item?.value}个项目`,
|
||||
区: i?.name,
|
||||
});
|
||||
console.log(i, 'i');
|
||||
}
|
||||
});
|
||||
});
|
||||
console.log(dataJson, 'skkskck');
|
||||
return dataJson;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (sceneRef.current) {
|
||||
return;
|
||||
}
|
||||
// 初始化地图场景
|
||||
const map = L.map('map', {
|
||||
center: [29.909571, 119.600006],
|
||||
zoom: 10,
|
||||
minZoom: 9,
|
||||
maxZoom: 10,
|
||||
zoomControl: false,
|
||||
attributionControl: false,
|
||||
}).setView([29.909571, 119.600006], 9);
|
||||
|
||||
const l7layer = new L7Layer({
|
||||
logoVisible: false,
|
||||
}).addTo(map);
|
||||
|
||||
const scene: any = l7layer.getScene();
|
||||
sceneRef.current = scene;
|
||||
|
||||
scene.on('loaded', async () => {
|
||||
let dataAreaJson = await getProjectDistributionAndPaymentRanking();
|
||||
console.log(dataAreaJson, 'dataAreaJson');
|
||||
const choropleth = new Choropleth({
|
||||
chinaBorder: false,
|
||||
source: {
|
||||
data: dataAreaJson || [],
|
||||
joinBy: {
|
||||
sourceField: 'adcode',
|
||||
geoField: 'adcode',
|
||||
},
|
||||
},
|
||||
viewLevel: {
|
||||
level: 'city',
|
||||
adcode: 330100,
|
||||
},
|
||||
autoFit: true,
|
||||
style: {
|
||||
opacity: 1,
|
||||
stroke: '#0083FF',
|
||||
lineWidth: 1,
|
||||
lineOpacity: 1,
|
||||
},
|
||||
label: {
|
||||
field: 'name',
|
||||
style: {
|
||||
fill: '#000',
|
||||
opacity: 1,
|
||||
fontSize: 15,
|
||||
strokeWidth: 1.5,
|
||||
},
|
||||
},
|
||||
tooltip: {
|
||||
items: ['区', '数量'],
|
||||
},
|
||||
state: {
|
||||
active: { stroke: '#0083FF', lineWidth: 1, fill: '#E4F2FF' },
|
||||
},
|
||||
});
|
||||
choropleth.addToScene(scene);
|
||||
});
|
||||
scene.on('resize', () => {
|
||||
console.log('resize');
|
||||
});
|
||||
|
||||
// 组件卸载时清理
|
||||
return () => {
|
||||
if (sceneRef.current) {
|
||||
sceneRef.current.destroy();
|
||||
}
|
||||
};
|
||||
}, [props?.item]);
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '594px',
|
||||
position: 'relative',
|
||||
zIndex: 1,
|
||||
backgroundColor: '#fff',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
id="map"
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '594px',
|
||||
background: `url(${map_bg_img}) no-repeat bottom`,
|
||||
backgroundSize: '100%',
|
||||
}}
|
||||
></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -1,86 +0,0 @@
|
||||
import { MyBetaModalFormProps } from '@/common';
|
||||
import { RightOutlined } from '@ant-design/icons';
|
||||
import { useNavigate } from '@umijs/max';
|
||||
|
||||
export default function PendingApplicationForm(props: MyBetaModalFormProps) {
|
||||
const navigate = useNavigate();
|
||||
return (
|
||||
<div className="pending_application_form">
|
||||
<div className="pending_application_form_title">待处理工单</div>
|
||||
<div className="pending_application_form_container">
|
||||
<div className="pending_application_form_item">
|
||||
<div
|
||||
className="label"
|
||||
onClick={() => {
|
||||
navigate('/emergency');
|
||||
}}
|
||||
>
|
||||
突发事件
|
||||
<RightOutlined />
|
||||
</div>
|
||||
<div className="value">{props?.item?.pending?.emergency || 0}</div>
|
||||
</div>
|
||||
<div className="pending_application_form_item">
|
||||
<div
|
||||
className="label"
|
||||
onClick={() => {
|
||||
navigate('/work_order/list');
|
||||
}}
|
||||
>
|
||||
报修工单
|
||||
<RightOutlined />
|
||||
</div>
|
||||
<div className="value">{props?.item?.pending?.repair || 0}</div>
|
||||
</div>
|
||||
<div className="pending_application_form_item">
|
||||
<div
|
||||
className="label"
|
||||
onClick={() => {
|
||||
navigate('/work_order/list');
|
||||
}}
|
||||
>
|
||||
报事工单
|
||||
<RightOutlined />
|
||||
</div>
|
||||
<div className="value">{props?.item?.pending?.incident || 0}</div>
|
||||
</div>
|
||||
<div className="pending_application_form_item">
|
||||
<div
|
||||
className="label"
|
||||
onClick={() => {
|
||||
navigate('/work_order/list');
|
||||
}}
|
||||
>
|
||||
投诉工单
|
||||
<RightOutlined />
|
||||
</div>
|
||||
<div className="value">{props?.item?.pending?.complaint || 0}</div>
|
||||
</div>
|
||||
<div className="pending_application_form_item">
|
||||
<div
|
||||
className="label"
|
||||
onClick={() => {
|
||||
navigate('/attendance/attendance_schedules');
|
||||
}}
|
||||
>
|
||||
巡检工单
|
||||
<RightOutlined />
|
||||
</div>
|
||||
<div className="value">{props?.item?.pending?.inspection || 0}</div>
|
||||
</div>
|
||||
<div className="pending_application_form_item">
|
||||
<div
|
||||
className="label"
|
||||
onClick={() => {
|
||||
navigate('/asset/asset_items_maintenances');
|
||||
}}
|
||||
>
|
||||
维保工单
|
||||
<RightOutlined />
|
||||
</div>
|
||||
<div className="value">{props?.item?.pending?.maintenance || 0}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
Before Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 532 B |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 562 B |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 759 B |
|
Before Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 105 KiB |
|
Before Width: | Height: | Size: 1.0 KiB |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="714" height="47" viewBox="0 0 714 47"><g><g><g><path d="M212,17L231.661898,39.996876C235.461674,44.441154,241.016041,47,246.863251,47L467.13675,47C472.98395,47,478.53833,44.441154,482.3381,39.996877999999995L502,17L212,17Z" fill="#2A7EFB" fill-opacity="1"/></g><g><path d="M0,17L714,17L714,12.000001C714,6.4771528,709.52283,2,704,2L10.000001,2C4.4771528,2,0,6.4771528,0,12.000001L0,17Z" fill="#2A7EFB" fill-opacity="1"/></g></g><g><g><path d="M212,15L231.661898,37.996876C235.461674,42.441154,241.016041,45,246.863251,45L467.13675,45C472.98395,45,478.53833,42.441154,482.3381,37.996877999999995L502,15L212,15Z" fill="#E2F1FF" fill-opacity="1"/></g><g><path d="M0,15L714,15L714,10.000001C714,4.4771528,709.52283,0,704,0L10.000001,0C4.4771528,0,0,4.4771528,0,10.000001L0,15Z" fill="#E2F1FF" fill-opacity="1"/></g></g></g></svg>
|
||||
|
Before Width: | Height: | Size: 941 B |
@ -1,19 +0,0 @@
|
||||
.asset_management_analysis_data {
|
||||
background-color: #f3f8fb;
|
||||
border-radius: 10px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 20px 15px;
|
||||
.label {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #666666;
|
||||
}
|
||||
.value {
|
||||
color: #333333;
|
||||
font-size: 30px;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
.financial_analysis {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 15px;
|
||||
&_item {
|
||||
color: #fff;
|
||||
background: linear-gradient(134deg, #6499ff 34%, #95b8ff 100%);
|
||||
border-radius: 10px;
|
||||
text-align: center;
|
||||
width: 48%;
|
||||
height: 100px;
|
||||
.value {
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
padding-top: 17px;
|
||||
span {
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
.title {
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,102 +0,0 @@
|
||||
.map_card {
|
||||
width: 100%;
|
||||
border-radius: 15px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.map_card_contents {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 4;
|
||||
.map_card_title_bg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
height: 70px;
|
||||
z-index: 1;
|
||||
}
|
||||
.map_data_contents {
|
||||
position: relative;
|
||||
z-index: 100;
|
||||
padding-top: 18px;
|
||||
}
|
||||
.map_card_title {
|
||||
color: #2a7efb;
|
||||
font-size: 1.8rem;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
.map_card_data_contents {
|
||||
position: absolute;
|
||||
top: 70px;
|
||||
left: 30px;
|
||||
z-index: 100;
|
||||
display: flex;
|
||||
right: 30px;
|
||||
justify-content: space-between;
|
||||
.map_card_data {
|
||||
// display: inline-block;
|
||||
// 换为 2 行
|
||||
// justify-content: center;
|
||||
// flex-wrap: wrap;
|
||||
// justify-content: space-between;
|
||||
// align-items: center;
|
||||
// display: inline-flex;
|
||||
// text-align: center;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
.map_card_data_title {
|
||||
color: #3d3d3d;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #0083ff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
// justify-content: space-between;
|
||||
span {
|
||||
padding: 0 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.map_card_data_number {
|
||||
padding: 10px 0 0 25px;
|
||||
color: #0083ff;
|
||||
font-size: 28px;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.others_project {
|
||||
position: absolute;
|
||||
right: 1px;
|
||||
bottom: 10px;
|
||||
z-index: 100;
|
||||
.others_project_cell_list {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
background: linear-gradient(
|
||||
270deg,
|
||||
rgba(124, 191, 255, 0) 0%,
|
||||
rgba(217, 236, 255, 0.67) 95%
|
||||
);
|
||||
padding: 0 10px 0 0;
|
||||
border-left: 5px solid #0083ff;
|
||||
margin-bottom: 20px;
|
||||
width: 200px;
|
||||
color: #0083ff;
|
||||
img {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin: 0 3px;
|
||||
}
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,67 +0,0 @@
|
||||
.card_right {
|
||||
background-color: #fff;
|
||||
}
|
||||
.pending_application_form {
|
||||
background-color: #f3faff;
|
||||
border-radius: 10px;
|
||||
&_title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
padding: 15px 20px;
|
||||
}
|
||||
&_container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
padding: 0 30px;
|
||||
}
|
||||
&_item {
|
||||
width: 33.333%;
|
||||
padding-bottom: 10px;
|
||||
.label {
|
||||
color: #666666;
|
||||
font-size: 14px;
|
||||
line-height: 12px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.value {
|
||||
color: #333333;
|
||||
font-size: 27px;
|
||||
font-weight: 550;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.work_order_data {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding-top: 10px;
|
||||
&_item {
|
||||
width: 50%;
|
||||
text-align: center;
|
||||
color: #3d3d3d;
|
||||
font-size: 16rpx;
|
||||
}
|
||||
&_cell {
|
||||
padding-top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.dashboard_progress {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
// padding-top: 100px;
|
||||
.dashboard_label {
|
||||
font-size: 16px;
|
||||
color: #3d3d3d;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
top: 50px;
|
||||
}
|
||||
.dashboard_value {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
@ -1,20 +1,5 @@
|
||||
// import MyModalsMapLeaflet from '@/components/ModalsMapLeaflet';
|
||||
import CardCenter from './components/CardCenter';
|
||||
import CardLeft from './components/CardLeft';
|
||||
import CardRight from './components/CardRight';
|
||||
import './style.scss';
|
||||
export default function Index() {
|
||||
return (
|
||||
<div className="overview_content">
|
||||
<div className="overview_left">
|
||||
<CardLeft />
|
||||
</div>
|
||||
<div className="overview_center">
|
||||
<CardCenter />
|
||||
</div>
|
||||
<div className="overview_right">
|
||||
<CardRight />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
return <div className="overview_content">2</div>;
|
||||
}
|
||||
|
||||
@ -5,14 +5,14 @@ export default function Login() {
|
||||
<div>
|
||||
<MyLoginPage />
|
||||
<div className="filing_info">
|
||||
浙江国彩城市服务有限公司 |{' '}
|
||||
XXXX有限公司 |
|
||||
<a
|
||||
href="https://beian.miit.gov.cn/#/Integrated/index"
|
||||
target="_blank"
|
||||
key="icp"
|
||||
rel="noreferrer"
|
||||
>
|
||||
浙ICP备2025210789号-3
|
||||
粤ICP备2025210号-3
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,27 +1,17 @@
|
||||
import {
|
||||
MyButtons,
|
||||
MyColumns,
|
||||
MyPageContainer,
|
||||
MyProTableProps,
|
||||
} from '@/common';
|
||||
import { MyPageContainer, MyProTableProps } from '@/common';
|
||||
import { Apis } from '@/gen/Apis';
|
||||
import { SysPermissionsTypeEnum } from '@/gen/Enums';
|
||||
import { DownOutlined, UpOutlined } from '@ant-design/icons';
|
||||
import { ActionType, ProTable } from '@ant-design/pro-components';
|
||||
import { Button, Space, Tag } from 'antd';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import Create from './modals/Create';
|
||||
import Update from './modals/Update';
|
||||
|
||||
export default function Index({ title = '功能' }) {
|
||||
const [data, setData] = useState<any>([]);
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const actionRef = useRef<ActionType>();
|
||||
const [guardName] = useState<string>('Admin');
|
||||
|
||||
const getData = async () => {
|
||||
let data = await Apis.Permission.SysPermissions.List({
|
||||
guard_name: guardName,
|
||||
});
|
||||
let data = await Apis.Permission.Roles.PermissionTree();
|
||||
setLoading(true);
|
||||
setData(data.data);
|
||||
};
|
||||
|
||||
@ -38,19 +28,11 @@ export default function Index({ title = '功能' }) {
|
||||
actionRef={actionRef}
|
||||
headerTitle="功能管理"
|
||||
expandable={{
|
||||
// defaultExpandAllRows: true,
|
||||
defaultExpandedRowKeys: [1],
|
||||
defaultExpandAllRows: true,
|
||||
// defaultExpandedRowKeys: [1],
|
||||
}}
|
||||
options={false}
|
||||
dataSource={data}
|
||||
toolBarRender={() => [
|
||||
<Create
|
||||
key="Create"
|
||||
reload={getData}
|
||||
title={title}
|
||||
guardName={guardName}
|
||||
/>,
|
||||
]}
|
||||
columns={[
|
||||
{
|
||||
title: '名称',
|
||||
@ -58,88 +40,7 @@ export default function Index({ title = '功能' }) {
|
||||
return `${record.id}_${record?.name}`;
|
||||
},
|
||||
},
|
||||
{ title: 'icon', dataIndex: 'icon' },
|
||||
MyColumns.EnumTag({
|
||||
title: '类型',
|
||||
dataIndex: 'type',
|
||||
valueEnum: SysPermissionsTypeEnum,
|
||||
}),
|
||||
{ title: '链接', dataIndex: 'path' },
|
||||
// { title: '前端表示', dataIndex: 'key' },
|
||||
{
|
||||
title: '后端API',
|
||||
dataIndex: 'backend_apis',
|
||||
render: (_, item) => {
|
||||
return (
|
||||
<Space direction="vertical">
|
||||
{item.backend_apis?.map((item: string) => (
|
||||
<Tag key={item}>{item}</Tag>
|
||||
))}
|
||||
</Space>
|
||||
);
|
||||
},
|
||||
},
|
||||
MyColumns.Option({
|
||||
render: (_, item: any, index) => (
|
||||
<Space key={index}>
|
||||
<Button
|
||||
size="small"
|
||||
key={`up_${item.id}`}
|
||||
icon={<UpOutlined />}
|
||||
disabled={!item.parent_id}
|
||||
onClick={() => {
|
||||
Apis.Permission.SysPermissions.Move({
|
||||
id: item.id,
|
||||
type: 'up',
|
||||
}).then(() => {
|
||||
getData();
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
size="small"
|
||||
icon={<DownOutlined />}
|
||||
key={`down_${item.id}`}
|
||||
disabled={!item.parent_id}
|
||||
onClick={() => {
|
||||
Apis.Permission.SysPermissions.Move({
|
||||
id: item.id,
|
||||
type: 'down',
|
||||
}).then(() => {
|
||||
getData();
|
||||
});
|
||||
}}
|
||||
></Button>
|
||||
<Create
|
||||
reload={getData}
|
||||
title={title}
|
||||
item={item}
|
||||
key={`create_sub_${item.id}`}
|
||||
guardName={guardName}
|
||||
buttonProps={{
|
||||
size: 'small',
|
||||
title: '添加下级功能',
|
||||
type: 'link',
|
||||
}}
|
||||
/>
|
||||
<Update
|
||||
item={item}
|
||||
reload={getData}
|
||||
title={title}
|
||||
key={`update_${item.id}`}
|
||||
guardName={guardName}
|
||||
/>
|
||||
<MyButtons.Delete
|
||||
key={`delete_${item.id}`}
|
||||
onConfirm={() =>
|
||||
Apis.Permission.SysPermissions.Delete({ id: item.id }).then(
|
||||
() => getData(),
|
||||
)
|
||||
}
|
||||
/>
|
||||
</Space>
|
||||
),
|
||||
}),
|
||||
]}
|
||||
/>
|
||||
);
|
||||
@ -152,7 +53,7 @@ export default function Index({ title = '功能' }) {
|
||||
tabKey="system-permissions"
|
||||
tabLabel={title}
|
||||
>
|
||||
<ShowTable />
|
||||
{loading ? <ShowTable /> : null}
|
||||
</MyPageContainer>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,4 +1,9 @@
|
||||
import { MyButtons, MyPageContainer, MyProTableProps } from '@/common';
|
||||
import {
|
||||
MyButtons,
|
||||
MyPageContainer,
|
||||
MyProTableProps,
|
||||
useCurrentPermissions,
|
||||
} from '@/common';
|
||||
import { flattenToMultiLevelFormatWithRowSpanAdvancedNew } from '@/common/utils/flattenIterative';
|
||||
import { Apis } from '@/gen/Apis';
|
||||
import { ProCard, ProTable } from '@ant-design/pro-components';
|
||||
@ -10,6 +15,7 @@ interface SelectedBuilding {
|
||||
name: string;
|
||||
}
|
||||
export default function Index({ title = '角色' }) {
|
||||
const getCurrentPermissions = useCurrentPermissions();
|
||||
const [selectedBuilding, setSelectedBuilding] =
|
||||
useState<SelectedBuilding | null>(null);
|
||||
const [selectedPermissionsIds, setSelectedPermissionsIds] = useState<any[]>(
|
||||
@ -19,7 +25,7 @@ export default function Index({ title = '角色' }) {
|
||||
const [dataTabsSource, setDataTabsSource] = useState<any>([]);
|
||||
const [tabsKey, setTabsKey] = useState<any>('');
|
||||
const getSysPermissions = () => {
|
||||
Apis.Permission.SysPermissions.List({ guard_name: 'Admin' }).then((res) => {
|
||||
Apis.Permission.Roles.PermissionTree().then((res) => {
|
||||
setDataSource(
|
||||
flattenToMultiLevelFormatWithRowSpanAdvancedNew(
|
||||
res?.data[0]?.children || [],
|
||||
@ -31,7 +37,7 @@ export default function Index({ title = '角色' }) {
|
||||
|
||||
const onSave = () => {
|
||||
if (selectedPermissionsIds?.length && selectedBuilding?.id) {
|
||||
Apis.Permission.SysRoles.SetPermissions({
|
||||
Apis.Permission.Roles.SetPermissions({
|
||||
permissions_ids: selectedPermissionsIds,
|
||||
id: selectedBuilding?.id || 0,
|
||||
}).then(() => {
|
||||
@ -52,7 +58,7 @@ export default function Index({ title = '角色' }) {
|
||||
name: selectedRole.name,
|
||||
});
|
||||
}
|
||||
Apis.Permission.SysRoles.GetPermissions({
|
||||
Apis.Permission.Roles.GetPermissions({
|
||||
id: id ?? 0,
|
||||
}).then((res) => {
|
||||
setSelectedPermissionsIds(res?.data?.permissions_ids || []);
|
||||
@ -60,15 +66,15 @@ export default function Index({ title = '角色' }) {
|
||||
};
|
||||
|
||||
const getSysRoles = () => {
|
||||
Apis.Permission.SysRoles.List().then((res) => {
|
||||
Apis.Permission.Roles.List().then((res) => {
|
||||
setDataTabsSource(res?.data || []);
|
||||
if (res?.data?.length) {
|
||||
const firstRole = res.data[0];
|
||||
const firstRole = res?.data[0];
|
||||
getPermissions(firstRole?.id || 0);
|
||||
// 初始化选中第一个角色
|
||||
setSelectedBuilding({
|
||||
id: firstRole.id,
|
||||
name: firstRole.name,
|
||||
id: firstRole?.id,
|
||||
name: firstRole?.name,
|
||||
});
|
||||
}
|
||||
console.log(res, 'res');
|
||||
@ -77,7 +83,7 @@ export default function Index({ title = '角色' }) {
|
||||
|
||||
const onSelect = () => {
|
||||
//删除角色
|
||||
Apis.Permission.SysRoles.Delete({
|
||||
Apis.Permission.Roles.Delete({
|
||||
id: tabsKey,
|
||||
}).then(() => {
|
||||
getSysRoles();
|
||||
@ -88,21 +94,11 @@ export default function Index({ title = '角色' }) {
|
||||
getSysRoles();
|
||||
getSysPermissions();
|
||||
}, []);
|
||||
return (
|
||||
<MyPageContainer
|
||||
title={title}
|
||||
enableTabs={true}
|
||||
tabKey="system-roles"
|
||||
tabLabel={title}
|
||||
>
|
||||
<ProCard
|
||||
title="权限配置"
|
||||
style={{ width: '100%' }}
|
||||
headerBordered
|
||||
extra={
|
||||
<Space size="large">
|
||||
<Space size="small">
|
||||
<Create key="Create" reload={() => getSysRoles()} title={title} />
|
||||
|
||||
let toolBarRender = () => {
|
||||
return getCurrentPermissions({
|
||||
add: <Create key="Create" reload={() => getSysRoles()} title={title} />,
|
||||
delete: (
|
||||
<MyButtons.Default
|
||||
key="delete"
|
||||
size="middle"
|
||||
@ -115,7 +111,8 @@ export default function Index({ title = '角色' }) {
|
||||
// 如果当前选中角色是管理员,则禁用删除按钮
|
||||
disabled={selectedBuilding?.name === '管理员'}
|
||||
/>
|
||||
</Space>
|
||||
),
|
||||
save: (
|
||||
<MyButtons.Default
|
||||
key="save"
|
||||
type="primary"
|
||||
@ -123,8 +120,22 @@ export default function Index({ title = '角色' }) {
|
||||
title="保存权限"
|
||||
onClick={() => onSave()}
|
||||
/>
|
||||
</Space>
|
||||
}
|
||||
),
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<MyPageContainer
|
||||
title={title}
|
||||
enableTabs={true}
|
||||
tabKey="system-roles"
|
||||
tabLabel={title}
|
||||
>
|
||||
<ProCard
|
||||
title="权限配置"
|
||||
style={{ width: '100%' }}
|
||||
headerBordered
|
||||
extra={<Space size="small">{toolBarRender()}</Space>}
|
||||
>
|
||||
<div style={{ display: 'flex' }}>
|
||||
<div style={{ width: '130px' }}>
|
||||
|
||||
@ -26,7 +26,7 @@ export default function Create(props: MyBetaModalFormProps) {
|
||||
}
|
||||
}}
|
||||
onFinish={async (values) =>
|
||||
Apis.Permission.SysRoles.Store(values)
|
||||
Apis.Permission.Roles.Store(values)
|
||||
.then(() => {
|
||||
props.reload?.();
|
||||
message.success(props.title + '成功');
|
||||
|
||||