组织架构图改造

feature/v3
Chengliang 2 years ago
parent 337a2101cd
commit dc2e54528a

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

@ -2,7 +2,7 @@
* @Author: Chengliang 1546584672@qq.com * @Author: Chengliang 1546584672@qq.com
* @Date: 2023-06-25 16:33:21 * @Date: 2023-06-25 16:33:21
* @LastEditors: Chengliang 1546584672@qq.com * @LastEditors: Chengliang 1546584672@qq.com
* @LastEditTime: 2023-06-27 10:51:02 * @LastEditTime: 2023-06-28 16:02:39
* @FilePath: /org-chart-frant/src/components/timeline/index.jsx * @FilePath: /org-chart-frant/src/components/timeline/index.jsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
@ -41,17 +41,17 @@ export default class TimeLine extends React.Component {
// }); // });
// }); // });
const datas = [ const datas = [
{ key: 0, title: '当前版本', color: 'blue', time: '2022-01-09' }, { key: 0, id: 0, title: '当前版本', color: 'blue', time: '' },
{ key: 1, title: '测试', color: 'grey', time: '2022-01-09' }, { key: 1, id: 1, title: '测试', color: 'grey', time: '2022-01-09' },
{ key: 2, title: '测试', color: 'grey', time: '2022-01-09' }, { key: 2, id: 2, title: '测试', color: 'grey', time: '2022-01-09' },
{ key: 3, title: '测试', color: 'grey', time: '2022-01-09' }, { key: 3, id: 3, title: '测试', color: 'grey', time: '2022-01-09' },
{ key: 4, title: '测试', color: 'grey', time: '2022-01-09' }, { key: 4, id: 4, title: '测试', color: 'grey', time: '2022-01-09' },
{ key: 5, title: '测试', color: 'grey', time: '2022-01-09' }, { key: 5, id: 5, title: '测试', color: 'grey', time: '2022-01-09' },
{ key: 6, title: '测试', color: 'grey', time: '2022-01-09' }, { key: 6, id: 6, title: '测试', color: 'grey', time: '2022-01-09' },
{ key: 7, title: '测试', color: 'grey', time: '2022-01-09' }, { key: 7, id: 7, title: '测试', color: 'grey', time: '2022-01-09' },
{ key: 8, title: '测试', color: 'grey', time: '2022-01-09' }, { key: 8, id: 8, title: '测试', color: 'grey', time: '2022-01-09' },
{ key: 9, title: '测试', color: 'grey', time: '2022-01-09' }, { key: 9, id: 9, title: '测试', color: 'grey', time: '2022-01-09' },
{ key: 10, title: '测试', color: 'grey', time: '2022-01-09' }, { key: 10, id: 10, title: '测试', color: 'grey', time: '2022-01-09' },
]; ];
this.setState({ this.setState({
timelineList: datas, timelineList: datas,

@ -1,4 +1,5 @@
import React from 'react'; import React from 'react';
import { QuestionCircleOutlined } from '@ant-design/icons';
import style from './index.less'; import style from './index.less';
import { import {
DatePicker, DatePicker,
@ -10,8 +11,13 @@ import {
Dropdown, Dropdown,
Menu, Menu,
TreeSelect, TreeSelect,
Tooltip,
Modal,
Input,
message,
} from 'antd'; } from 'antd';
const { Option } = Select; const { Option } = Select;
const { TextArea } = Input;
import moment from 'moment'; import moment from 'moment';
import 'moment/locale/zh-cn'; import 'moment/locale/zh-cn';
import locale from 'antd/lib/date-picker/locale/zh_CN'; import locale from 'antd/lib/date-picker/locale/zh_CN';
@ -30,6 +36,9 @@ export class TopBar extends React.Component {
level: '3', level: '3',
fisvitual: '0', fisvitual: '0',
}, },
open: false,
confirmLoading: false,
description: '',
}; };
} }
@ -42,13 +51,35 @@ export class TopBar extends React.Component {
this.setState({ requestData }); this.setState({ requestData });
} }
onChange = (e) => {
this.setState({ description: e.target.value });
};
/** /**
* 组织维度改变 * 弹窗确认
*/ */
changeFclass() { handleOk = () => {
debugger; const { description, requestData } = this.state;
this.getSeatchCondition(this.props.url); if (description.length == 0) {
} return message.error('请填写描述信息');
}
this.setState({ confirmLoading: true });
setTimeout(() => {
this.setState({ open: false, confirmLoading: false, description: '' });
message.success('版本记录成功,请重新刷新页面');
}, 2000);
// let api = '/api/bs/hrmorganization/orgchart/synchronousData?flcass='+requestData.fclass+ '&description=' +description;
// fetch(api)
// .then((res) => res.json())
// .then((data) => {
// if (data.code == 200) {
// this.setState({ open: false, confirmLoading: false,description:'' });
// message.success(',');
// } else {
// message.error(',');
// }
// });
};
handleExportMenuClick(e) { handleExportMenuClick(e) {
this.props.onExport(e.key == '1' ? 'png' : 'pdf'); this.props.onExport(e.key == '1' ? 'png' : 'pdf');
@ -93,11 +124,10 @@ export class TopBar extends React.Component {
setTimeout(() => { setTimeout(() => {
this.getNodeTreeNode(id); this.getNodeTreeNode(id);
resolve(undefined); resolve(undefined);
}, 1000); }, 500);
}); });
onRootChange = (value) => { onRootChange = (value) => {
debugger;
let requestData = { ...this.state.requestData, root: value }; let requestData = { ...this.state.requestData, root: value };
this.setState({ requestData }); this.setState({ requestData });
}; };
@ -140,9 +170,8 @@ export class TopBar extends React.Component {
); );
render() { render() {
const { disabled } = this.props; const { disabled, type } = this.props;
debugger; const { rootTreeData, open, confirmLoading } = this.state;
const { rootTreeData } = this.state;
return ( return (
<div className={style.topbarWrapper}> <div className={style.topbarWrapper}>
@ -154,8 +183,17 @@ export class TopBar extends React.Component {
style={{ width: 140 }} style={{ width: 140 }}
value={this.state.requestData.fclass} value={this.state.requestData.fclass}
onChange={(value) => { onChange={(value) => {
this.handleFormChange({ fclass: value }); const requestData = {
this.props.onSearch(this.state.requestData); fclass: value,
root: undefined,
level: '3',
fisvitual: '0',
};
this.handleFormChange(requestData);
this.getSeatchCondition(
`/api/bs/hrmorganization/orgchart/getCondition?fclass=${value}&type=${this.props.type}`,
);
this.props.onSearch(requestData);
}} }}
> >
{this.state.fclasslist.map((item) => ( {this.state.fclasslist.map((item) => (
@ -182,6 +220,7 @@ export class TopBar extends React.Component {
<Col span={6}> <Col span={6}>
<Checkbox <Checkbox
style={{ marginTop: '5px', marginLeft: 100 }} style={{ marginTop: '5px', marginLeft: 100 }}
checked={this.state.requestData.fisvitual == '1'}
onChange={(e) => onChange={(e) =>
this.handleFormChange({ this.handleFormChange({
fisvitual: e.target.checked ? '1' : '0', fisvitual: e.target.checked ? '1' : '0',
@ -190,6 +229,15 @@ export class TopBar extends React.Component {
> >
显示虚拟组织 显示虚拟组织
</Checkbox> </Checkbox>
<Tooltip
title="提示:若启用虚拟组织,需要在分部自定义表增加字段(名称 fblx) 字段类型 下拉框(0实体 1虚拟) 部门自定义表同上(字段名称 bmlx)。"
color="#FF7F00"
placement="rightTop"
>
<QuestionCircleOutlined
style={{ color: '#FF7F00', cursor: 'pointer', fontSize: 16 }}
/>
</Tooltip>
</Col> </Col>
<Col span={6}> <Col span={6}>
显示层级 显示层级
@ -207,16 +255,18 @@ export class TopBar extends React.Component {
</Row> </Row>
<Row style={{ marginTop: '15px' }}> <Row style={{ marginTop: '15px' }}>
<Col span={8}> <Col span={8}>
<Button {type == 'user' && (
type="primary" <Button
style={{ marginRight: '10px' }} type="primary"
disabled={disabled} style={{ marginRight: '10px' }}
onClick={() => { disabled={disabled}
this.props.onSynchronous(this.state.requestData); onClick={() => {
}} this.setState({ open: true });
> }}
版本记录 >
</Button> 版本记录
</Button>
)}
<Button <Button
type="primary" type="primary"
style={{ marginRight: '10px' }} style={{ marginRight: '10px' }}
@ -227,10 +277,31 @@ export class TopBar extends React.Component {
查询 查询
</Button> </Button>
<Dropdown overlay={this.menu}> <Dropdown overlay={this.menu}>
<Button>导出</Button> <Button type="primary">导出</Button>
</Dropdown> </Dropdown>
</Col> </Col>
</Row> </Row>
<Modal
title="版本记录"
cancelText="取消"
okText="确定"
open={open}
onOk={this.handleOk}
confirmLoading={confirmLoading}
onCancel={() => this.setState({ open: false })}
>
<p style={{ color: 'red' }}>
提示:版本操作耗时较长请谨慎操作版本仅记录当前维度的数据
</p>
<p>描述:</p>
<TextArea
showCount
maxLength={10}
style={{ height: 120, resize: 'none' }}
onChange={this.onChange}
placeholder="please enter"
/>
</Modal>
</div> </div>
); );
} }

@ -12,6 +12,7 @@ import { message } from 'antd';
let active = 'top'; let active = 'top';
export default function companyPage() { export default function companyPage() {
let topbar = null;
const [data, setData] = useState(null); const [data, setData] = useState(null);
const [sliderProgress, setSliderProgress] = useState(50); const [sliderProgress, setSliderProgress] = useState(50);
let addNodeChildFunc = null; let addNodeChildFunc = null;
@ -19,7 +20,7 @@ export default function companyPage() {
let topBarSearchRequest = null; let topBarSearchRequest = null;
const [hasRight, setHasRight] = useState(''); const [hasRight, setHasRight] = useState('');
const [disabled, setDisabled] = useState(false); const [id, setId] = useState(0);
// //
function onNodeClick(nodeId) { function onNodeClick(nodeId) {
@ -49,9 +50,7 @@ export default function companyPage() {
qs.stringify(request, { addQueryPrefix: true }); qs.stringify(request, { addQueryPrefix: true });
} else { } else {
api = api =
'/api/bs/hrmorganization/orgchart/asyncCompanyData?fclass=0&root=0&date=' + '/api/bs/hrmorganization/orgchart/asyncCompanyData?fclass=0&fisvitual=0&id=0&root=0&ids=' +
moment(new Date()).format('YYYY-MM-DD') +
'&ids=' +
idsStr; idsStr;
} }
@ -82,9 +81,7 @@ export default function companyPage() {
// //
useEffect(() => { useEffect(() => {
d3.json( d3.json(
// "/company/data" '/api/bs/hrmorganization/orgchart/companyData?fclass=0&fisvitual=0&root=0&level=3&id=0',
'/api/bs/hrmorganization/orgchart/companyData?fclass=0&isvitual=0&root=0&date=' +
moment(new Date()).format('YYYY-MM-DD'),
).then((data) => { ).then((data) => {
setData(data.data); setData(data.data);
setHasRight(data?.hasRight); setHasRight(data?.hasRight);
@ -183,7 +180,6 @@ export default function companyPage() {
return `<div>${d.data.fname}</div>`; return `<div>${d.data.fname}</div>`;
}; };
// tool bar start
const handleTopLayoutClick = (progressBtn) => { const handleTopLayoutClick = (progressBtn) => {
progressBtn.current.style.top = 50 + 'px'; progressBtn.current.style.top = 50 + 'px';
orgChart && orgChart &&
@ -232,10 +228,6 @@ export default function companyPage() {
orgChart && orgChart.zoomBehavior(value - 50); orgChart && orgChart.zoomBehavior(value - 50);
}; };
// tool bar end
// top bar start
function downloadPdf(chart) { function downloadPdf(chart) {
chart.exportImg({ chart.exportImg({
save: false, save: false,
@ -275,13 +267,20 @@ export default function companyPage() {
* 时间轴点击 * 时间轴点击
* @param {*} timeline * @param {*} timeline
*/ */
const timeLineSearch = (timeline) => {}; const timeLineSearch = (timeline) => {
setId(timeline.id);
let requestData = { ...topbar.state.requestData, id: timeline.id };
handleSearch(requestData, false);
};
/** /**
* 查询 * 查询
* @param {*} requestData * @param {*} requestData
*/ */
const handleSearch = (requestData) => { const handleSearch = (requestData, cache = true) => {
if (cache) {
requestData = { ...requestData, id: id };
}
topBarSearchRequest = requestData; topBarSearchRequest = requestData;
let api = let api =
'/api/bs/hrmorganization/orgchart/companyData' + '/api/bs/hrmorganization/orgchart/companyData' +
@ -300,26 +299,6 @@ export default function companyPage() {
}); });
}; };
/**
* 同步数据
* @param {*} requestData
*/
const handleSynchronous = (requestData) => {
setDisabled(true);
let api = '/api/bs/hrmorganization/orgchart/synchronousData';
fetch(api)
.then((res) => res.json())
.then((data) => {
if (data.code == 200) {
message.success('同步成功,请重新查询');
} else {
message.error('数据同步失败');
}
setDisabled(false);
//this.handleSearch(requestData);
});
};
useEffect(() => { useEffect(() => {
if (active == 'left') { if (active == 'left') {
orgChart && orgChart &&
@ -352,18 +331,15 @@ export default function companyPage() {
hasRight && ( hasRight && (
<div className={styles.contentWrapper}> <div className={styles.contentWrapper}>
<TopBar <TopBar
ref={(r) => (topbar = r)}
onExport={(type) => { onExport={(type) => {
handleExport(type); handleExport(type);
}} }}
onSearch={(requestData) => { onSearch={(requestData) => {
handleSearch(requestData); handleSearch(requestData);
}} }}
onSynchronous={(requestData) => {
handleSynchronous(requestData);
}}
disabled={disabled}
type="company" type="company"
url="/api/bs/hrmorganization/orgchart/getCondition?type=company" url="/api/bs/hrmorganization/orgchart/getCondition?fclass=0&type=company"
/> />
<ToolBar <ToolBar
onTopLayoutClick={(progressBtn) => handleTopLayoutClick(progressBtn)} onTopLayoutClick={(progressBtn) => handleTopLayoutClick(progressBtn)}
@ -378,7 +354,7 @@ export default function companyPage() {
onClick={(timeline) => { onClick={(timeline) => {
timeLineSearch(timeline); timeLineSearch(timeline);
}} }}
url="/api/bs/hrmorganization/orgchart/timelines?type=company" url={'/api/bs/hrmorganization/orgchart/timelines?id=' + id}
/> />
<OrgChartComponent <OrgChartComponent
setChart={(chart) => (orgChart = chart)} setChart={(chart) => (orgChart = chart)}

@ -4,6 +4,8 @@ import { OrgChartComponent } from '@/components/orgChart';
import * as d3 from 'd3'; import * as d3 from 'd3';
import { TopBar } from '../components/topBar'; import { TopBar } from '../components/topBar';
import ToolBar from '../components/toolBar'; import ToolBar from '../components/toolBar';
import TimeLine from '../components/timeline';
import moment from 'moment'; import moment from 'moment';
import qs from 'qs'; import qs from 'qs';
import { message } from 'antd'; import { message } from 'antd';
@ -11,6 +13,7 @@ import jsPDF from 'jspdf';
let active = 'top'; let active = 'top';
export default function userPage() { export default function userPage() {
const [data, setData] = useState(null); const [data, setData] = useState(null);
let topbar = null;
const [topBarSearchRequest, setTpBarSearchRequest] = useState(null); const [topBarSearchRequest, setTpBarSearchRequest] = useState(null);
const [requestRes, setRequestRes] = useState({ const [requestRes, setRequestRes] = useState({
date: moment(new Date()).format('YYYY-MM-DD'), date: moment(new Date()).format('YYYY-MM-DD'),
@ -25,7 +28,7 @@ export default function userPage() {
let progressBtnRef = null; let progressBtnRef = null;
const [hasRight, setHasRight] = useState(''); const [hasRight, setHasRight] = useState('');
const [disabled, setDisabled] = useState(false); const [id, setId] = useState(0);
// //
function onNodeClick(nodeId) { function onNodeClick(nodeId) {
// alert('clicked ' + nodeId); // alert('clicked ' + nodeId);
@ -54,8 +57,7 @@ export default function userPage() {
qs.stringify(request, { addQueryPrefix: true }); qs.stringify(request, { addQueryPrefix: true });
} else { } else {
api = api =
'/api/bs/hrmorganization/orgchart/asyncUserData?fclass=0&root=0&date=' + '/api/bs/hrmorganization/orgchart/asyncUserData?fclass=0&fisvitual=0&root=0&level=3&id=0' +
moment(new Date()).format('YYYY-MM-DD') +
'&ids=' + '&ids=' +
idsStr; idsStr;
} }
@ -72,13 +74,23 @@ export default function userPage() {
} }
} }
/**
* 时间轴点击
* @param {*} timeline
*/
const timeLineSearch = (timeline) => {
setId(timeline.id);
let requestData = { ...topbar.state.requestData, id: timeline.id };
handleSearch(requestData, false);
};
// //
function getDepartmentImage() { function getDepartmentImage() {
let index = Math.floor(Math.random() * 8) + 1; let index = Math.floor(Math.random() * 8) + 1;
return `./img/department/${index}.png`; return `./img/department/${index}.png`;
} }
// //
function getSubcompanyImage() { function getSubcompanyImage() {
let index = Math.floor(Math.random() * 3) + 1; let index = Math.floor(Math.random() * 3) + 1;
return `./img/subcompany/${index}.png`; return `./img/subcompany/${index}.png`;
@ -87,11 +99,10 @@ export default function userPage() {
// //
useEffect(() => { useEffect(() => {
document.cookie = document.cookie =
'ecology_JSessionid=aaabAoBxcpmhQ5GSTpXJy; JSESSIONID=aaabAoBxcpmhQ5GSTpXJy; Systemlanguid=7; languageidweaver=7; loginuuids=1; __randcode__=1e1d21ef-3a75-4eaa-b3b3-277fa0ca0ef3; loginidweaver=sysadmin'; 'ecology_JSessionid=aaaMxyh0rOLot5nEk86Jy; JSESSIONID=aaaMxyh0rOLot5nEk86Jy; __randcode__=39ee6033-5f6f-4e53-ad53-5a3de97645eb; Systemlanguid=7; languageidweaver=7; loginidweaver=sysadmin; loginuuids=1';
d3.json( d3.json(
// "/user/data" // "/user/data"
'/api/bs/hrmorganization/orgchart/userData?fclass=0&root=0&date=' + '/api/bs/hrmorganization/orgchart/userData?fclass=0&fisvitual=0&root=0&level=3&id=0',
moment(new Date()).format('YYYY-MM-DD'),
).then((data) => { ).then((data) => {
setData(data.data); setData(data.data);
setHasRight(data?.hasRight); setHasRight(data?.hasRight);
@ -196,7 +207,10 @@ export default function userPage() {
} }
}; };
const handleSearch = (requestData) => { const handleSearch = (requestData, cache = true) => {
if (cache) {
requestData = { ...requestData, id: id };
}
setTpBarSearchRequest(requestData); setTpBarSearchRequest(requestData);
let api = let api =
'/api/bs/hrmorganization/orgchart/userData' + '/api/bs/hrmorganization/orgchart/userData' +
@ -215,22 +229,6 @@ export default function userPage() {
}); });
}; };
const handleSynchronous = (requestData) => {
setDisabled(true);
let api = '/api/bs/hrmorganization/orgchart/synchronousData';
fetch(api)
.then((res) => res.json())
.then((data) => {
if (data.code == 200) {
message.success('同步成功,请重新查询');
} else {
message.error('数据同步失败');
}
setDisabled(false);
//this.handleSearch(requestData);
});
};
useEffect(() => { useEffect(() => {
if (active == 'left') { if (active == 'left') {
orgChart && orgChart &&
@ -309,7 +307,7 @@ export default function userPage() {
? d.data.fleaderimg ? d.data.fleaderimg
: d.data.ftype == 0 || d.data.ftype == 1 : d.data.ftype == 0 || d.data.ftype == 1
? './img/company.png' ? './img/company.png'
: './img/default_avator.png' : './img/department.png'
}" style="width: 58px; height: 58px;position:absolute;left:29px; border-radius: 50%; margin-top: 16px;position:absolute;left:29px;z-index:999"/> }" style="width: 58px; height: 58px;position:absolute;left:29px; border-radius: 50%; margin-top: 16px;position:absolute;left:29px;z-index:999"/>
</div> </div>
<div style="display: inline-block; margin-left: 6px;width: 55%" > <div style="display: inline-block; margin-left: 6px;width: 55%" >
@ -506,6 +504,7 @@ export default function userPage() {
hasRight && ( hasRight && (
<div className={styles.contentWrapper}> <div className={styles.contentWrapper}>
<TopBar <TopBar
ref={(r) => (topbar = r)}
onExport={(type) => { onExport={(type) => {
handleExport(type); handleExport(type);
}} }}
@ -513,12 +512,8 @@ export default function userPage() {
setRequestRes(requestData); setRequestRes(requestData);
handleSearch(requestData); handleSearch(requestData);
}} }}
onSynchronous={(requestData) => {
handleSynchronous(requestData);
}}
disabled={disabled}
type="user" type="user"
url="/api/bs/hrmorganization/orgchart/getCondition?type=user" url="/api/bs/hrmorganization/orgchart/getCondition?fclass=0&type=user"
/> />
<ToolBar <ToolBar
onTopLayoutClick={handleTopLayoutClick} onTopLayoutClick={handleTopLayoutClick}
@ -526,6 +521,12 @@ export default function userPage() {
onZoomOut={(progressBtn) => handleZoomOut(progressBtn)} onZoomOut={(progressBtn) => handleZoomOut(progressBtn)}
onZoomIn={(progressBtn) => handleZoomIn(progressBtn)} onZoomIn={(progressBtn) => handleZoomIn(progressBtn)}
/> />
<TimeLine
onClick={(timeline) => {
timeLineSearch(timeline);
}}
url={'/api/bs/hrmorganization/orgchart/timelines?id=' + id}
/>
<OrgChartComponent <OrgChartComponent
setChart={(chart) => (orgChart = chart)} setChart={(chart) => (orgChart = chart)}
setClick={(click) => (addNodeChildFunc = click)} setClick={(click) => (addNodeChildFunc = click)}

Loading…
Cancel
Save