|
@@ -0,0 +1,331 @@
|
|
|
+import React from 'react';
|
|
|
+import ajax from 'jquery/src/ajax/xhr.js';
|
|
|
+import $ from 'jquery/src/ajax';
|
|
|
+import moment from 'moment';
|
|
|
+import '@/manageCenter/financialManage/distribute/public.less';
|
|
|
+import { Button, Spin, DatePicker, Radio, message } from 'antd';
|
|
|
+import { getToday, ShowModal } from '@/tools';
|
|
|
+import ShowModalDiv from "@/showModal.jsx";
|
|
|
+import './index.less';
|
|
|
+
|
|
|
+import ReactEcharts from 'echarts-for-react/lib/core';
|
|
|
+import echarts from 'echarts/lib/echarts';
|
|
|
+import 'echarts/lib/chart/line';
|
|
|
+import 'echarts/lib/component/legend';
|
|
|
+import 'echarts/lib/component/title';
|
|
|
+import 'echarts/lib/component/tooltip';
|
|
|
+import 'echarts/lib/component/toolbox';
|
|
|
+import 'echarts/lib/component/grid';
|
|
|
+
|
|
|
+const RadioButton = Radio.Button;
|
|
|
+const RadioGroup = Radio.Group;
|
|
|
+const { RangePicker } = DatePicker
|
|
|
+
|
|
|
+const Statistics = React.createClass({
|
|
|
+
|
|
|
+ getInitialState() {
|
|
|
+ return {
|
|
|
+ status: 1,
|
|
|
+ releaseDate: getToday(1),
|
|
|
+ info: {},
|
|
|
+ data: {},
|
|
|
+ htmlMenus: [],
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ componentWillMount() {
|
|
|
+ this.loadData();
|
|
|
+ this.getData();
|
|
|
+ this.mainMenu();
|
|
|
+ },
|
|
|
+
|
|
|
+ mainMenu() {
|
|
|
+ $.ajax({
|
|
|
+ method: "get",
|
|
|
+ dataType: "json",
|
|
|
+ crossDomain: false,
|
|
|
+ url: globalConfig.context + "/api/admin/selectNavList",
|
|
|
+ data: {},
|
|
|
+ success: function (data) {
|
|
|
+ if (!data.data) {
|
|
|
+ if (data.error && data.error.length) {
|
|
|
+ message.warning(data.error[0].message);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ let menu = data.data;
|
|
|
+ this.setState({
|
|
|
+ htmlMenus: menu,
|
|
|
+ });
|
|
|
+ }.bind(this),
|
|
|
+ }).always(
|
|
|
+ function (data) {
|
|
|
+ this.setState({
|
|
|
+ loading: false,
|
|
|
+ });
|
|
|
+ }.bind(this)
|
|
|
+ );
|
|
|
+ },
|
|
|
+
|
|
|
+ loadData() {
|
|
|
+ const { releaseDate } = this.state
|
|
|
+ this.setState({
|
|
|
+ loading: true,
|
|
|
+ });
|
|
|
+ $.ajax({
|
|
|
+ method: "get",
|
|
|
+ dataType: "json",
|
|
|
+ crossDomain: false,
|
|
|
+ url: globalConfig.context + "/api/admin/statistics/info",
|
|
|
+ data: {
|
|
|
+ startTime: releaseDate[0],
|
|
|
+ endTime: releaseDate[1],
|
|
|
+ },
|
|
|
+ success: function (data) {
|
|
|
+ ShowModal(this);
|
|
|
+ this.setState({
|
|
|
+ loading: false,
|
|
|
+ });
|
|
|
+ if (data.error && data.error.length === 0) {
|
|
|
+ this.setState({
|
|
|
+ info: data.data
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ message.warning(data.error[0].message);
|
|
|
+ }
|
|
|
+ }.bind(this),
|
|
|
+ }).always(
|
|
|
+ function () {
|
|
|
+ this.setState({
|
|
|
+ loading: false,
|
|
|
+ });
|
|
|
+ }.bind(this)
|
|
|
+ );
|
|
|
+ },
|
|
|
+
|
|
|
+ getData() {
|
|
|
+ $.ajax({
|
|
|
+ method: "get",
|
|
|
+ dataType: "json",
|
|
|
+ crossDomain: false,
|
|
|
+ url: globalConfig.context + "/api/admin/statistics/lists",
|
|
|
+ success: function (data) {
|
|
|
+ if (data.error && data.error.length === 0) {
|
|
|
+ this.setState({
|
|
|
+ data: data.data,
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ message.warning(data.error[0].message);
|
|
|
+ }
|
|
|
+ }.bind(this),
|
|
|
+ }).always(
|
|
|
+ function () {
|
|
|
+ this.setState({
|
|
|
+ loading: false,
|
|
|
+ });
|
|
|
+ }.bind(this)
|
|
|
+ );
|
|
|
+ },
|
|
|
+
|
|
|
+ search() {
|
|
|
+ this.loadData();
|
|
|
+ },
|
|
|
+
|
|
|
+ reset() {
|
|
|
+ this.state.releaseDate = []
|
|
|
+ this.loadData();
|
|
|
+ },
|
|
|
+
|
|
|
+ getNewUrl(url, cd) {
|
|
|
+ const { htmlMenus = [] } = this.state
|
|
|
+ let id = ''
|
|
|
+ htmlMenus.map(function (item) {
|
|
|
+ if (item.url == url) {
|
|
|
+ id = item.id;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return `${url}?rid=${id}#${cd}`
|
|
|
+ },
|
|
|
+
|
|
|
+ render() {
|
|
|
+ const { status, info, data } = this.state
|
|
|
+ const list = [
|
|
|
+ { color: "#99FFFF", title: "总项目数:", sum: info.signSum, tit: "项目数", number: info.rangeSignSum, url: this.getNewUrl("/admin/customer.html", "companySign") },
|
|
|
+ { color: "#FFFFCC", title: "总进行中数:", sum: info.privateSum, tit: "进行中", number: info.rangePrivateSum, url: this.getNewUrl("/admin/customer.html", "companyIntention") },
|
|
|
+ { color: "#FFCCCC", title: "总完成数:", sum: info.channelSum, tit: "完成数", number: info.rangeChannelSum, url: this.getNewUrl("/admin/channelList.html", "channelunit") },
|
|
|
+ { color: "#99CCFF", title: "总未启动数:", sum: info.publicReleaseSum, tit: "未启动", number: info.rangePublicReleaseSum, url: "" },
|
|
|
+ { color: "#99FFCC", title: "总暂停数:", sum: info.followSum, tit: "暂停数", number: info.rangeFollowSum, url: this.getNewUrl("/admin/customer.html", "followUpSummaryOrdinary") },
|
|
|
+ { color: "#CC99CC", title: "总公出数:", sum: info.orderSum, tit: "公出数", number: info.rangeOrderSum, url: this.getNewUrl("/admin/order.html", "billing") },
|
|
|
+ { color: "#99CCCC", title: "总协单数:", sum: info.receivables, tit: "协单数", number: info.rangeReceivables, url: this.getNewUrl("/admin/order.html", "press") },
|
|
|
+ {
|
|
|
+ color: "#FFCC99", title: "待紧急处理事项",
|
|
|
+ list: [
|
|
|
+ { key: "待变更订单:", value: info.changeSum, url: this.getNewUrl("/admin/order.html", "contractChangeYxy") },
|
|
|
+ { key: "待成本付款处理:", value: info.projectCheckSum, url: this.getNewUrl("/admin/project.html", "businessManagement") },]
|
|
|
+ },
|
|
|
+ ]
|
|
|
+ const option = {
|
|
|
+ title: {
|
|
|
+ text: ''
|
|
|
+ },
|
|
|
+ tooltip: {
|
|
|
+ trigger: 'axis'
|
|
|
+ },
|
|
|
+ legend: {
|
|
|
+ data: ['签单客户数', '私有客户数', '私有渠道数', '公出企业数', '跟进客户数', '订单数',]
|
|
|
+ },
|
|
|
+ grid: {
|
|
|
+ left: '3%',
|
|
|
+ right: '4%',
|
|
|
+ bottom: '3%',
|
|
|
+ containLabel: true
|
|
|
+ },
|
|
|
+ toolbox: {
|
|
|
+ feature: {
|
|
|
+ saveAsImage: {}
|
|
|
+ }
|
|
|
+ },
|
|
|
+ xAxis: {
|
|
|
+ type: 'category',
|
|
|
+ boundaryGap: false,
|
|
|
+ // axisLabel: {
|
|
|
+ // interval: 0, // 设置X轴刻度间隔为0
|
|
|
+ // },
|
|
|
+ data: data.dates
|
|
|
+ },
|
|
|
+ yAxis: {
|
|
|
+ type: 'value'
|
|
|
+ },
|
|
|
+ color: ['#99FFFF', '#cccca3', '#FFCCCC', '#99CCFF', '#99FFCC', '#CC99CC'],
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ name: '签单客户数',
|
|
|
+ type: 'line',
|
|
|
+ data: data.signList,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '私有客户数',
|
|
|
+ type: 'line',
|
|
|
+ data: data.privateList,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '私有渠道数',
|
|
|
+ type: 'line',
|
|
|
+ data: data.channelList,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '公出企业数',
|
|
|
+ type: 'line',
|
|
|
+ data: data.publicReleaseList,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '跟进客户数',
|
|
|
+ type: 'line',
|
|
|
+ data: data.userFollowList,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '订单数',
|
|
|
+ type: 'line',
|
|
|
+ data: data.orderList,
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ return (
|
|
|
+ <div className="user-content">
|
|
|
+ <ShowModalDiv ShowModal={this.state.showModal} seeInfo={() => { this.props.handlekey("normal") }} />
|
|
|
+ <div className="content-title" style={{ marginBottom: 10 }}>
|
|
|
+ <span style={{ fontWeight: 900, fontSize: 16 }}>数据统计</span>
|
|
|
+ </div>
|
|
|
+ <div className="user-search">
|
|
|
+ <RadioGroup value={status}
|
|
|
+ onChange={e => {
|
|
|
+ this.setState({
|
|
|
+ status: e.target.value
|
|
|
+ })
|
|
|
+ if (e.target.value == 0) {
|
|
|
+ this.setState({
|
|
|
+ releaseDate: []
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ this.setState({
|
|
|
+ releaseDate: getToday(e.target.value)
|
|
|
+ }, () => {
|
|
|
+ this.loadData()
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <RadioButton value={1}>今日</RadioButton>
|
|
|
+ <RadioButton value={2}>昨日</RadioButton>
|
|
|
+ <RadioButton value={3}>近7日</RadioButton>
|
|
|
+ <RadioButton value={4}>近15日</RadioButton>
|
|
|
+ <RadioButton value={5}>近30日</RadioButton>
|
|
|
+ <RadioButton value={0}>自定义</RadioButton>
|
|
|
+ </RadioGroup>
|
|
|
+ {
|
|
|
+ status == 0 &&
|
|
|
+ <span>
|
|
|
+ <RangePicker
|
|
|
+ style={{ width: 200, marginLeft: 15 }}
|
|
|
+ value={[
|
|
|
+ this.state.releaseDate[0]
|
|
|
+ ? moment(this.state.releaseDate[0])
|
|
|
+ : null,
|
|
|
+ this.state.releaseDate[1]
|
|
|
+ ? moment(this.state.releaseDate[1])
|
|
|
+ : null,
|
|
|
+ ]}
|
|
|
+ onChange={(data, dataString) => {
|
|
|
+ this.setState({ releaseDate: dataString })
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ <Button style={{ margin: "0 15px" }} type="primary" onClick={this.search}>搜索</Button>
|
|
|
+ <Button onClick={this.reset}>重置</Button>
|
|
|
+ </span>
|
|
|
+ }
|
|
|
+ </div>
|
|
|
+ <div className="patent-table">
|
|
|
+ <Spin spinning={this.state.loading}>
|
|
|
+ <div className='plist'>
|
|
|
+ {
|
|
|
+ list.map((item, index) =>
|
|
|
+ <div className='plitem' style={{ background: item.color }} key={index}>
|
|
|
+ <div className='plititle'>
|
|
|
+ <span style={{ fontWeight: item.title == "待紧急处理事项" && "bold" }}>{item.title}</span>
|
|
|
+ {/* <span className='plisum'>{item.sum}</span> */}
|
|
|
+ <a href={globalConfig.context + item.url}>
|
|
|
+ <span className='plisum'>{item.sum}</span>
|
|
|
+ </a>
|
|
|
+ </div>
|
|
|
+ {
|
|
|
+ item.title == "待紧急处理事项"
|
|
|
+ ? <div className='list'>
|
|
|
+ {
|
|
|
+ item.list.map((t, i) =>
|
|
|
+ <div key={i}>
|
|
|
+ <span>{t.key}</span>
|
|
|
+ <a href={globalConfig.context + t.url}>
|
|
|
+ <span style={{ textDecoration: "underline", color: "#0000FF" }}>{t.value}</span>
|
|
|
+ </a>
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+ }
|
|
|
+ </div>
|
|
|
+ : <div className='count'>
|
|
|
+ <a href={globalConfig.context + item.url}><div className='plinum'>{item.number}</div></a>
|
|
|
+ <div className='plitit'>{item.tit}</div>
|
|
|
+ </div>
|
|
|
+ }
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+ }
|
|
|
+ </div>
|
|
|
+ </Spin>
|
|
|
+ <ReactEcharts option={option} echarts={echarts} />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ },
|
|
|
+});
|
|
|
+
|
|
|
+export default Statistics;
|