{
+ makeInitialTable(e);
+ }}
+ />,
+ ,
+ ];
+ }}
+ editable={{
+ type: 'multiple',
+ editableKeys: editableRowsKeys,
+ actionRender: (row, config, defaultDoms) => {
+ return [defaultDoms.delete];
+ },
+ onDelete: (_key, _row) => {
+ // console.log('del', _key, _row);
+ const rowKpiIds = (_row?.kpiData || []).map(ele => ele.kpi_id);
+ rowKpiIds.push(_row?.kpiYear?.kpi_id);
+ setDelKpiIds(rowKpiIds);
+ },
+ onValuesChange: (record, recordList) => {
+ // console.log('on edit, onValuesChange',record, recordList);
+ onTableChange(recordList);
+ },
+ onChange: (editableKeys, editableRows) => {
+ setEditableRowKeys(editableKeys);
+ },
+ }}
+ />
+ >
+ );
+});
diff --git a/src/components/kpi/SubjectTable/Profit.jsx b/src/components/kpi/SubjectTable/Profit.jsx
new file mode 100644
index 0000000..777adb4
--- /dev/null
+++ b/src/components/kpi/SubjectTable/Profit.jsx
@@ -0,0 +1,252 @@
+import { useContext, useState, useEffect, useMemo } from 'react';
+import { observer } from 'mobx-react';
+import moment from 'moment';
+import { stores_Context } from './../../../config';
+import { Button, Switch, Input, Space, Typography, Row, Col, message } from 'antd';
+import { EditableProTable } from '@ant-design/pro-components';
+import { KPIObjects } from './../../../libs/ht';
+import { isEmpty, fixTo2Decimals, fixTo4Decimals, cloneDeep, numberFormatter, fixToInt } from './../../../utils/commons';
+
+export const KPIObjectsMapped = KPIObjects.reduce((a, c) => ({ ...a, [String(c.key)]: c }), {});
+const { Text } = Typography;
+const initialPercentKey = new Array(12).fill(1).reduce((r, v, i) => ({ ...r, [`M${i + 1}Percent`]: [8, 9].includes(i) ? 10 : 8 }), {});
+const numberConvert10K = (number, scale = 10) => {
+ return fixTo2Decimals(number / (1000 * scale)) + '万';
+};
+
+export default observer((props) => {
+ const { KPIStore, date_picker_store: searchFormStore } = useContext(stores_Context);
+ const { curObject, objects, onSearchSubmit } = props;
+ const curObjectItem = KPIObjectsMapped[curObject];
+
+ const [dataSource, setDataSource] = useState(KPIStore.pageData);
+ const [editOpen, setEditOpen] = useState(false);
+ const [editableRowsKeys, setEditableRowKeys] = useState([]);
+ useEffect(() => {
+ setDataSource(KPIStore.pageData);
+ setEditOpen(false);
+ return () => {};
+ }, [KPIStore.pageData]);
+
+
+ const PercentInput = useMemo(
+ () =>
+ // eslint-disable-next-line react/display-name
+ ({ value, onChange, record, ...extProps }) => {
+ // // eslint-disable-next-line react-hooks/rules-of-hooks
+ const [inputValue, setInputValue] = useState(value);
+ const handleInputChange = (e) => {
+ setInputValue(e.target.value);
+ onChange?.(e.target.value);
+ };
+ const calcV = inputValue ? numberConvert10K(fixToInt((Number(record?.yearValue) * inputValue) / 100)) : 0;
+ return (
+
+
+ {calcV}
+
+ );
+ },
+ []
+ );
+ const RenderMonthCell = (row, mon) => {
+ return (
+
+
+ {fixTo2Decimals(row?.[`M${mon}Percent`])}
+ %
+
+ {numberConvert10K(fixTo4Decimals((Number(row?.yearValue) * row?.[`M${mon}Percent`]) / 100))}
+
+ );
+ };
+ const monthCol = new Array(12).fill(1).map((_, index) => {
+ return {
+ title: `${index + 1}月`,
+ dataIndex: `M${index + 1}Percent`,
+ valueType: 'digit',
+ width: '6.5em',
+ // fieldProps: { min: 0, max: 100, style: { width: '4em' } },
+ renderFormItem: ({ dataIndex, ...item }, { record, isEditable, ...e }, form) => {
+ return ;
+ },
+ render: (_, row) => RenderMonthCell(row, index + 1),
+ };
+ });
+ const columns = [
+ {
+ title: curObjectItem.label,
+ dataIndex: 'object_id',
+ editable: false,
+ render: (_, r) => r.object_name,
+ },
+ {
+ title: '年度目标',
+ dataIndex: 'yearValue',
+ valueType: 'digit',
+ fieldProps: { style: { width: '100%' }, step: 10000*100 },
+ formItemProps: {
+ style: { width: '100%' },
+ },
+ },
+ ...monthCol,
+ {
+ title: (
+
+ 操作
+ {
+ makeInitialTable(e);
+ }}
+ />
+
+ ),
+ valueType: 'option',
+ // width: 250,
+ render: () => {
+ return null;
+ },
+ },
+ ];
+
+ const onTableChange = (...argrs) => {
+ setEditableRowKeys(argrs[0].map((ele) => ele.key));
+ setDataSource(argrs[0]);
+ };
+ const onTableSubmit = () => {
+ const tableData = dataSource.reduce((r, curObj) => {
+ const allMonth = new Array(12).fill(1).map((_, index) => {
+ const mIndex = index + 1;
+ const mVal = (Number(curObj.yearValue) * Number(curObj[`M${mIndex}Percent`])) / 100;
+ const startM = moment([KPIStore.settingYear, index, 1]);
+ const pick = (({ object, object_name, object_id, subject, date_type }) => ({
+ object,
+ object_name,
+ object_id,
+ subject,
+ date_type,
+ }))(curObj);
+ return {
+ ...pick,
+ start_date: startM.format('YYYY-MM-DD'),
+ end_date: startM.endOf('M').format('YYYY-MM-DD HH:mm'),
+ value: mVal,
+ kpi_id: curObj.kpiDataMapped?.[`M${mIndex}`]?.kpi_id || undefined,
+ key: undefined,
+ };
+ });
+ return r.concat(allMonth);
+ }, []);
+ const yearRow = (({ object, object_name, object_id, subject, date_type, yearValue, kpiYear }) => ({
+ object,
+ object_name,
+ object_id,
+ subject,
+ date_type,
+ value: yearValue,
+ start_date: moment([KPIStore.settingYear, 0, 1]).format('YYYY-MM-DD'),
+ end_date: moment([KPIStore.settingYear, 11, 1]).endOf('M').format('YYYY-MM-DD HH:mm'),
+ kpi_id: kpiYear?.kpi_id || undefined,
+ }))(dataSource?.[0] || {});
+ tableData.unshift(yearRow);
+ console.log('sub', tableData, 'del:', delKpiIds);
+ // return false; // debug:
+ KPIStore.onSubmit(tableData, { delQueue: delKpiIds }).then((res) => {
+ if (res) {
+ message.success('保存成功');
+ setEditOpen(false);
+ setEditableRowKeys([]);
+ setDelKpiIds([]);
+ onSearchSubmit(searchFormStore.formValuesToSub);
+ return false;
+ }
+ message.error('失败, 请重试');
+ });
+ };
+ const initialRow = monthCol.reduce(
+ (r, v) => ({
+ ...r,
+ [v.dataIndex]: 0,
+ yearValue: 10000 * 100,
+ object: curObject,
+ object_name: '',
+ object_id: -1,
+ subject: 'sum_profit',
+ date_type: searchFormStore.formValuesToSub.DateType,
+ kpiDataMapped: {},
+ key: Date.now().toString(32),
+ }),
+ {}
+ ); // v.formItemProps.initialValue
+ const makeInitialTable = (e) => {
+ setEditOpen(e);
+ // todo: 单独设置之后, 清空筛选会导致无法批量设置新的
+ if (e && isEmpty(dataSource)) {
+ const _initialRow = Object.assign({}, initialRow, initialPercentKey);
+ const _objects = isEmpty(objects) ? (curObjectItem?.data || []) : objects;
+ console.log('ooo', objects, isEmpty(objects), curObjectItem?.data || []);
+ const _initialTable = _objects.map((obj) => ({
+ ...cloneDeep(_initialRow),
+ object_name: obj.label,
+ object_id: obj.value,
+ key: Date.now().toString(32) + obj.value,
+ }));
+ console.log(_initialRow, 'iiiii');
+ setDataSource(_initialTable);
+ setEditableRowKeys(_initialTable.map((ele) => ele.key));
+ return false;
+ }
+ setEditableRowKeys(e ? dataSource.map((ele) => ele.key) : []);
+ };
+ const [delKpiIds, setDelKpiIds] = useState([]);
+ return (
+ <>
+
+
+ {
+ return [defaultDoms.delete];
+ },
+ onDelete: (_key, _row) => {
+ // console.log('del', _key, _row);
+ const rowKpiIds = (_row?.kpiData || []).map((ele) => ele.kpi_id);
+ rowKpiIds.push(_row?.kpiYear?.kpi_id);
+ setDelKpiIds(rowKpiIds);
+ },
+ onValuesChange: (record, recordList) => {
+ // console.log('on edit, onValuesChange',record, recordList);
+ onTableChange(recordList);
+ },
+ onChange: (editableKeys, editableRows) => {
+ setEditableRowKeys(editableKeys);
+ },
+ }}
+ />
+
+
+
+
+
+ >
+ );
+});
diff --git a/src/components/kpi/SumProfitPanel.jsx b/src/components/kpi/SumProfitPanel.jsx
new file mode 100644
index 0000000..0818a00
--- /dev/null
+++ b/src/components/kpi/SumProfitPanel.jsx
@@ -0,0 +1,57 @@
+import { useContext } from 'react';
+import { observer } from 'mobx-react';
+// import { stores_Context } from '../config';
+import { Button, Table, Switch, Input, Space, Typography, Row, Col, Spin, Radio, Tabs } from 'antd';
+import SearchForm from './../search/SearchForm';
+import { bu, KPIObjects } from './../../libs/ht';
+
+export default observer((props) => {
+ // const { } = useContext(stores_Context);
+ return (
+ <>
+
+
+ {
+ // TradeStore.setStateSearch(form);
+ // pageRefresh(obj);
+ }}
+ />
+
+
+
+
+ {
+ const id = String(i);
+ return {
+ ...ele,
+ children: `Content of tab ${id}`,
+ };
+ })}
+ />
+
+
+ >
+ );
+});
diff --git a/src/components/search/BusinessSelect.jsx b/src/components/search/BusinessSelect.jsx
index b97fcb3..cb94770 100644
--- a/src/components/search/BusinessSelect.jsx
+++ b/src/components/search/BusinessSelect.jsx
@@ -5,16 +5,23 @@ import { biz } from '../../libs/ht';
const Business_unit = (props) => {
- const {store} = props;
+ const { store, mode, value, onChange, show_all, ...extProps } = props;
return (
);
};
-
+/**
+ * 基于组织架构
+ */
export default observer(Business_unit);
diff --git a/src/components/search/BusinessUnitSelect.jsx b/src/components/search/BusinessUnitSelect.jsx
new file mode 100644
index 0000000..1b0738c
--- /dev/null
+++ b/src/components/search/BusinessUnitSelect.jsx
@@ -0,0 +1,36 @@
+import React, {Component} from 'react';
+import {Select} from 'antd';
+import {observer} from "mobx-react";
+import { biz, bu } from '../../libs/ht';
+
+
+const Business_unit = (props) => {
+ const { store, mode, value, onChange, show_all, ...extProps } = props;
+ const _show_all = ['tags', 'multiple'].includes(mode) ? false : show_all;
+ return (
+
+
+
+ );
+};
+/**
+ * HT的事业部
+ */
+export default observer(Business_unit);
diff --git a/src/components/search/DataTypeSelect.jsx b/src/components/search/DataTypeSelect.jsx
index e6f185d..731c81b 100644
--- a/src/components/search/DataTypeSelect.jsx
+++ b/src/components/search/DataTypeSelect.jsx
@@ -8,15 +8,30 @@ class DataTypeSelect extends Component {
super(props);
}
+ // debug:
+ // componentDidMount() {
+ // console.log(this.props, 'DataTypeSelect props');
+ // }
+
+ handleChange = (value) => {
+ if (this.props.store) {
+ this.props.store.onChange_datetype(value);
+ }
+ if (this.props.onChange) {
+ this.props.onChange(value);
+ }
+ };
+
render() {
const store = this.props.store;
return (
-
-
-
);
}
}
diff --git a/src/components/search/DatePickerCharts.jsx b/src/components/search/DatePickerCharts.jsx
index c8bca41..d6dc4f0 100644
--- a/src/components/search/DatePickerCharts.jsx
+++ b/src/components/search/DatePickerCharts.jsx
@@ -1,5 +1,5 @@
import React, { Component } from "react";
-import { Col, DatePicker, Row } from "antd";
+import { Col, DatePicker, Row, Form } from "antd";
import { observer } from "mobx-react";
import * as config from "../../config";
import moment from "moment";
@@ -7,6 +7,16 @@ import "moment/locale/zh-cn";
import locale from "antd/es/date-picker/locale/zh_CN";
import { stores_Context } from "../../config";
+// 1.0的搜索组件 不需要Form包裹
+const SectionWrapper = ({ isform, id, title, children, right, ...extProps }) =>
+ !isform ? (
+ <>{children}>
+ ) : (
+
+ {children}
+
+ );
+
// 用于日期选择,计算上一时间段、同比时间等
class DatePickerCharts extends Component {
static contextType = stores_Context;
@@ -17,17 +27,27 @@ class DatePickerCharts extends Component {
render() {
const { date_picker_store } = this.context;
+ const { isform } = this.props;
+ const defaultV = [date_picker_store.start_date, date_picker_store.end_date];
+ const defaultVdiff = [date_picker_store.start_date_cp, date_picker_store.end_date_cp];
return (
+
{
+ date_picker_store.onChange_dataPicker(e);
+ if (typeof this.props.onChange === 'function') {
+ this.props.onChange(e);
+ }
+ }
+ }
ranges={{
本周: [moment().startOf("week"), moment().endOf("week")],
上周: [moment().startOf("week").subtract(7, "days"), moment().endOf("week").subtract(7, "days")],
@@ -40,19 +60,27 @@ class DatePickerCharts extends Component {
去年: [moment().subtract(1, "year").startOf("year"), moment().subtract(1, "year").endOf("year")],
}}
/>
+
{this.props.hide_vs ? (
""
) : (
+
{
+ if (typeof this.props.onChange === 'function') {
+ this.props.onChange(value);
+ }
+ date_picker_store?.onChange_dataPicker_cp(value);
+ }}
ranges={{
上一时间段: date_picker_store.previous_date(),
去年同期: date_picker_store.previous_year(),
@@ -62,7 +90,7 @@ class DatePickerCharts extends Component {
前三个月: [moment().subtract(5, "month").startOf("month"), moment().subtract(3, "month").endOf("month")],
去年: [moment().subtract(1, "year").startOf("year"), moment().subtract(1, "year").endOf("year")],
}}
- />
+ />
)}
diff --git a/src/components/search/GroupSelect.jsx b/src/components/search/GroupSelect.jsx
index 95a0e6e..24daa00 100644
--- a/src/components/search/GroupSelect.jsx
+++ b/src/components/search/GroupSelect.jsx
@@ -10,23 +10,29 @@ class GroupSelect extends Component {
render() {
const { store, mode, value, onChange, show_all, ...extProps } = this.props;
+ const _mode = mode || store?.group_select_mode || null;
+ const _show_all = ['tags', 'multiple'].includes(_mode) ? false : show_all;
return (