From a02fa37f174b4c76000641a82d7943ac2d14bc30 Mon Sep 17 00:00:00 2001 From: Lei OT Date: Tue, 22 Apr 2025 16:08:18 +0800 Subject: [PATCH] =?UTF-8?q?fear:=20CRM=E7=BB=9F=E8=AE=A1:=20=E4=B8=AA?= =?UTF-8?q?=E4=BA=BA=E7=9C=8B=E6=9D=BF;=20=E8=BF=9D=E8=A7=84=E6=98=8E?= =?UTF-8?q?=E7=BB=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.jsx | 7 +- src/stores/SalesCRMData.js | 98 ++++- src/views/OPRisk.jsx | 69 --- .../Dashboard.jsx} | 23 +- .../{OPProcess.jsx => sales-crm/Process.jsx} | 13 +- src/views/sales-crm/Risk.jsx | 397 ++++++++++++++++++ 6 files changed, 499 insertions(+), 108 deletions(-) delete mode 100644 src/views/OPRisk.jsx rename src/views/{OPDashboard.jsx => sales-crm/Dashboard.jsx} (94%) rename src/views/{OPProcess.jsx => sales-crm/Process.jsx} (94%) create mode 100644 src/views/sales-crm/Risk.jsx diff --git a/src/App.jsx b/src/App.jsx index 5ccfc8f..1169655 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -52,9 +52,9 @@ import SalesCustomerCareRegular from './views/SalesCustomerCareRegular'; import { stores_Context, APP_VERSION } from './config'; import { WaterMark } from '@ant-design/pro-components'; import CooperationIcon from './components/icons/CooperationIcon'; -import OPDashboard from './views/OPDashboard'; -import OPProcess from './views/OPProcess'; -import OPRisk from './views/OPRisk'; +import OPDashboard from './views/sales-crm/Dashboard'; +import OPProcess from './views/sales-crm/Process'; +import OPRisk from './views/sales-crm/Risk'; import Cruise from './views/Cruise'; import Hotel from './views/Hotel'; @@ -280,6 +280,7 @@ const App = () => { } /> } /> } /> + } /> diff --git a/src/stores/SalesCRMData.js b/src/stores/SalesCRMData.js index c0b9610..696a0bb 100644 --- a/src/stores/SalesCRMData.js +++ b/src/stores/SalesCRMData.js @@ -1,7 +1,7 @@ -import { makeAutoObservable, runInAction, toJS } from 'mobx'; +import { makeAutoObservable, runInAction } from 'mobx'; import { fetchJSON } from '../utils/request'; -import { isEmpty, sortDescBy, objectMapper, groupBy, pick, unique, cloneDeep } from '../utils/commons'; -import { groupsMappedByCode, dataFieldAlias } from './../libs/ht'; +import { isEmpty, sortDescBy, groupBy, pick, unique } from '../utils/commons'; +import { groupsMappedByCode } from './../libs/ht'; import { DATE_FORMAT, SMALL_DATETIME_FORMAT } from './../config'; import moment from 'moment'; @@ -33,6 +33,20 @@ const fetchProcessData = async (param) => { return json.errcode === 0 ? json.result : []; }; +const fetchRiskDetailData = async (param) => { + const defaultParam = { + opisn: -1, + DateType: '', + WebCode: 'All', + DepartmentList: '', + Date1: '', + Date2: '', + IncludeTickets: '1', + }; + const json = await fetchJSON('/service-Analyse2/sales_crm_process_detail', {...defaultParam, ...param}); + return json.errcode === 0 ? json.result : []; +}; + class SalesCRMData { constructor(appStore) { this.appStore = appStore; @@ -42,7 +56,18 @@ class SalesCRMData { async get90n180Data(param = {}) { const retProps = param?.retLabel || ''; - const retKey = param.groupDateType === '' ? (param.groupType === 'overview' ? 'dataSource' : 'details') : 'byDate'; + let retKey = param.groupDateType === '' ? (param.groupType === 'overview' ? 'dataSource' : 'details') : 'byDate'; + retKey = param.opisn ? `operator_${param.opisn}`: retKey; + if (param.opisn ) { + if (!isEmpty(this.results.details)) { + const _this_opi_row = this.results.details.filter(ele => ele.groupsKey === param.opisn); + this.results[retKey] = _this_opi_row; + return; + } + if (!isEmpty(this.results[retKey])) { + return; + } + } this.results.loading = true; const date90=this.searchValues.date90; const date180=this.searchValues.date180; @@ -62,17 +87,21 @@ class SalesCRMData { }; }); // console.log(result2, '+++++ +++', retKey); - // console.log(this.results[retKey].length); + // console.log(this.results[retKey]?.length); runInAction(() => { this.results.loading = false; - this.results[retKey] = [].concat(this.results[retKey], result2); + this.results[retKey] = [].concat((this.results[retKey] || []), result2); }); return this.results; } async getResultData(param = {}) { - const retKey = param.groupDateType === '' ? 'byOperator' : 'byDate'; + let retKey = param.groupDateType === '' ? 'byOperator' : 'byDate'; + retKey = param.opisn ? `operator_byDate_${param.opisn}`: retKey; + if (!isEmpty(this.results[retKey])) { + return; + } this.results.loading = true; this.results[retKey] = []; const res = await fetchResultsData({ ...this.searchValuesToSub, ...param }); @@ -85,19 +114,42 @@ class SalesCRMData { async getProcessData(param = {}) { // const retKey = param.groupDateType === '' ? 'byOperator' : 'byDate'; - const retKey = param.groupDateType === '' ? (param.groupType !== 'operator' ? 'dataSource' : 'details') : 'byDate'; + let retKey = param.groupDateType === '' ? (param.groupType !== 'operator' ? 'dataSource' : 'details') : 'byDate'; + retKey = param.opisn ? `operator_${param.opisn}`: retKey; + if (param.opisn) { + if (!isEmpty(this.process.details)) { + const _this_opi_row = this.process.details.filter(ele => ele.groupsKey === param.opisn); + this.process[retKey] = _this_opi_row; + return; + } + if (!isEmpty(this.process[retKey])) { + return; + } + } this.process.loading = true; this.process[retKey] = []; const res = await fetchProcessData({ ...this.searchValuesToSub, ...param }); runInAction(() => { this.process.loading = false; this.process[retKey] = [].concat(this.process[retKey], res); - // this.process[retKey] =retKey === 'byOperator' ? res.filter(ele => ele.) + }); + } + + async getRiskDetailData(param = {}) { + this.risk.loading = true; + this.risk.dataSource = []; + const res = await fetchRiskDetailData({ ...this.searchValuesToSub, ...param }); + runInAction(() => { + this.risk.loading = false; + this.risk.dataSource = res; + this.risk.byLostType = groupBy(res, 'lost_type'); }); } searchValues = { date: moment(), + Date1: moment().startOf("week").subtract(7, "days"), + Date2: moment().endOf("week").subtract(7, "days"), DateType: { key: 'applyDate', label: '提交日期'}, WebCode: { key: 'All', label: '所有来源' }, // IncludeTickets: { key: '1', label: '含门票'}, @@ -114,7 +166,16 @@ class SalesCRMData { } }; - searchValuesToSub = {}; + searchValuesToSub = { + date: moment().format(DATE_FORMAT), + Date1: moment().startOf("week").subtract(7, "days").format(DATE_FORMAT), + Date2: moment().endOf("week").subtract(7, "days").format(SMALL_DATETIME_FORMAT), + DateType: 'applyDate', + DepartmentList: groupsMappedByCode.GH.value, + WebCode: 'All', + operator: '-1', + opisn: '-1', + }; setSearchValues(obj, values) { this.searchValues = { ...this.searchValues, ...values }; @@ -128,21 +189,20 @@ class SalesCRMData { Date2: (values.date.clone()).subtract(50, 'days').format(SMALL_DATETIME_FORMAT), }; } - this.searchValuesToSub = obj; + this.searchValuesToSub = {...this.searchValuesToSub, ...obj}; } results = { loading: false, dataSource: [], details: [], byDate: [], byOperator: [] }; process = { loading: false, dataSource: [], details: [], byDate: [], byOperator: [] }; - resetData = () => { - this.results.loading = false; - for (const key of Object.keys(this.results)) { - if (key !== 'loading') { - this.results[key] = []; - } + risk = { loading: false, dataSource: [], byLostType: {}, }; + resetData = (rootKey = '') => { + if (rootKey === '') { + return false; } - for (const key of Object.keys(this.process)) { + this[rootKey].loading = false; + for (const key of Object.keys(this[rootKey])) { if (key !== 'loading') { - this.process[key] = []; + this[rootKey][key] = []; } } }; diff --git a/src/views/OPRisk.jsx b/src/views/OPRisk.jsx deleted file mode 100644 index d966a24..0000000 --- a/src/views/OPRisk.jsx +++ /dev/null @@ -1,69 +0,0 @@ -import React, { useContext, useState } from 'react'; -import { observer } from 'mobx-react'; -import { stores_Context } from '../config'; -import moment from 'moment'; -import { SlackOutlined, SketchOutlined, AntCloudOutlined, RedditOutlined, GithubOutlined } from '@ant-design/icons'; -import { Row, Col, Table, Select, Space, Typography, Progress, Spin, Divider, Button, Switch } from 'antd'; -import SearchForm from './../components/search/SearchForm'; - -export default observer((props) => { - const { sale_store, date_picker_store: searchFormStore } = useContext(stores_Context); - - const { formValues, siderBroken } = searchFormStore; - - const riskTableProps = { - loading: false, - // sticky: true, - // scroll: { x: 1000, y: 400 }, - pagination: false, - columns: [ - { title: '客人姓名', dataIndex: 'WebCode', key: 'WebCode' }, - { title: '团号', dataIndex: 'o_id', key: 'o_id' }, - { title: '表单内容', dataIndex: 'COLI_LineClass', key: 'COLI_LineClass' }, - { title: '顾问', dataIndex: 'SourceType', key: 'SourceType' }, - { title: '预定时间', dataIndex: 'applyDate', key: 'applyDate' }, - ], - }; - return ( - <> - - - { - sale_store.setSearchValues(obj, form); - // pageRefresh(obj); - }} - /> - - -
-

>24H回复

- - -
-

首次报价周期>48h

-
- -
-

报价次数<1

-
- -
-

报价次数<2

-
- - - ); -}); diff --git a/src/views/OPDashboard.jsx b/src/views/sales-crm/Dashboard.jsx similarity index 94% rename from src/views/OPDashboard.jsx rename to src/views/sales-crm/Dashboard.jsx index 6fedf58..8706560 100644 --- a/src/views/OPDashboard.jsx +++ b/src/views/sales-crm/Dashboard.jsx @@ -1,14 +1,14 @@ import React, { useContext, useState, useEffect } from 'react'; import { observer } from 'mobx-react'; -import { stores_Context, DATE_FORMAT, SMALL_DATETIME_FORMAT } from '../config'; +import { Link } from 'react-router-dom'; +import { stores_Context, DATE_FORMAT, SMALL_DATETIME_FORMAT } from '../../config'; import moment from 'moment'; -import { SlackOutlined, SketchOutlined, AntCloudOutlined, RedditOutlined, GithubOutlined } from '@ant-design/icons'; -import { Row, Col, Table, Select, Space, Typography, Progress, Spin, Divider, Button, Switch, Tag } from 'antd'; -import SearchForm from './../components/search/SearchForm'; -import MixFieldsDetail from '../components/MixFieldsDetail'; -import { cloneDeep, fixTo2Decimals, sortBy, isEmpty, pick } from '../utils/commons'; -import Column from '../components/Column'; -import { groupsMappedByKey } from './../libs/ht'; +import { Row, Col, Table, Select, Spin, Tag } from 'antd'; +import SearchForm from '../../components/search/SearchForm'; +import MixFieldsDetail from '../../components/MixFieldsDetail'; +import { fixTo2Decimals, isEmpty, pick } from '../../utils/commons'; +import Column from '../../components/Column'; +import { groupsMappedByKey } from '../../libs/ht'; const COLOR_SETS = [ "#FFFFFF", @@ -38,7 +38,7 @@ export default observer((props) => { // console.log(operatorObjects); const pageRefresh = async (obj) => { - resetData(); + resetData('results'); const deptList = obj.DepartmentList.split(','); const includeCH = ['1', '2', '7'].some(ele => deptList.includes(ele)); const includeAH = ['28'].every(ele => deptList.includes(ele)); @@ -87,8 +87,8 @@ export default observer((props) => { // console.log('formValuesToSub --- getFullYearDiagramData', formValuesToSub.DepartmentList); await SalesCRMDataStore.getResultData({ ..._formValuesToSub, - Date1: moment().startOf('year').format(DATE_FORMAT), - Date2: moment().endOf('year').format(SMALL_DATETIME_FORMAT), + Date1: moment(obj.date).startOf('year').format(DATE_FORMAT), + Date2: moment(obj.date).endOf('year').format(SMALL_DATETIME_FORMAT), groupType: 'overview', // groupType: 'operator', groupDateType: 'month', @@ -199,6 +199,7 @@ export default observer((props) => { filterSearch: true, filters: operatorObjects.sort((a, b) => a.text.localeCompare(b.text)), onFilter: (value, record) => record.groupsKey === value || record.groupType === 'overview', + render: (text, record) => (record.groupType !== 'operator' ? text : {text}), }, { title: () => (<>前90 -30天
{searchValues.date90.Date1} 至 {searchValues.date90.Date2}), diff --git a/src/views/OPProcess.jsx b/src/views/sales-crm/Process.jsx similarity index 94% rename from src/views/OPProcess.jsx rename to src/views/sales-crm/Process.jsx index 78d2bee..7db82ff 100644 --- a/src/views/OPProcess.jsx +++ b/src/views/sales-crm/Process.jsx @@ -1,10 +1,11 @@ import React, { useContext } from 'react'; +import { Link } from 'react-router-dom'; import { observer } from 'mobx-react'; -import { stores_Context } from '../config'; +import { stores_Context } from '../../config'; import { InfoCircleOutlined } from '@ant-design/icons'; import { Row, Col, Table, Tooltip } from 'antd'; -import SearchForm from '../components/search/SearchForm'; -import { pick } from '../utils/commons'; +import SearchForm from '../../components/search/SearchForm'; +import { pick } from '../../utils/commons'; const COLOR_SETS = [ "#FFFFFF", @@ -29,7 +30,7 @@ export default observer((props) => { const operatorObjects = process.details.map((v) => ({ key: v.groupsKey, value: v.groupsKey, label: v.groupsLabel, text: v.groupsLabel })); const pageRefresh = async (obj) => { - resetData(); + resetData('process'); Promise.allSettled([ SalesCRMDataStore.getProcessData({ ...(obj || _formValuesToSub), @@ -63,6 +64,7 @@ export default observer((props) => { filterSearch: true, filters: operatorObjects.sort((a, b) => a.text.localeCompare(b.text)), onFilter: (value, record) => record.groupsKey === value || record.groupType !== 'operator', + render: (text, record) => (record.groupType !== 'operator' ? text : {text}), }, // 维度: 顾问 { title: '顾问动作', @@ -203,8 +205,7 @@ export default observer((props) => { filterSearch: true, filters: operatorObjects.sort((a, b) => a.text.localeCompare(b.text)), onFilter: (value, record) => record.groupsKey === value || record.groupType !== 'operator', - // render: (text, record) => { // todo: 点击查看不成行订单明细 - // }, + render: (text, record) => (record.groupType !== 'operator' ? text : {text}), }, // 维度: 顾问 { title: '>24H回复', dataIndex: 'lostTouch24', key: 'lostTouch24', sorter: (a, b) => tableSorter(a, b, 'lostTouch24'), diff --git a/src/views/sales-crm/Risk.jsx b/src/views/sales-crm/Risk.jsx new file mode 100644 index 0000000..ba0aacb --- /dev/null +++ b/src/views/sales-crm/Risk.jsx @@ -0,0 +1,397 @@ +import React, { useContext, useEffect } from 'react'; +import { NavLink, useParams } from 'react-router-dom'; +import { observer } from 'mobx-react'; +import { stores_Context, DATE_FORMAT, SMALL_DATETIME_FORMAT } from '../../config'; +import { InfoCircleOutlined } from '@ant-design/icons'; +import { Row, Col, Table, Divider, Button, Popover, Tooltip } from 'antd'; +import { fixTo2Decimals } from '../../utils/commons'; +import MixFieldsDetail from '../../components/MixFieldsDetail'; + +const COLOR_SETS = [ + '#FFFFFF', + // "#5B8FF9", + // "#FF6B3B", + '#9FB40F', + '#76523B', + '#DAD5B5', + '#E19348', + '#F383A2', +]; +const transparentHex = '1A'; +const percentageRender = (val) => (val ? `${val}%` : ''); +const numberConvert10K = (number, scale = 10) => { + return fixTo2Decimals((number/(1000*scale))); +}; +const retPropsMinRatesSet = { 'CH': 12, 'AH': 8, 'default': 10 }; // + +export default observer((props) => { + const { opisn, opi_name } = useParams(); + + const { sale_store, SalesCRMDataStore, date_picker_store: searchFormStore } = useContext(stores_Context); + + const { formValues, siderBroken } = searchFormStore; + const { searchValues, searchValuesToSub, resetData, results, process, risk } = SalesCRMDataStore; + + + useEffect(() => { + Promise.allSettled([ + // 结果指标 + SalesCRMDataStore.get90n180Data({ opisn, groupType: 'operator', groupDateType: '' }), + // 结果: 全年业绩 + SalesCRMDataStore.getResultData({ + opisn, + Date1: searchValues.date.clone().startOf('year').format(DATE_FORMAT), + Date2: searchValues.date.clone().endOf('year').format(SMALL_DATETIME_FORMAT), + groupType: 'overview', + // groupType: 'operator', + groupDateType: 'month', + }), + // 过程 + SalesCRMDataStore.getProcessData({ opisn, groupType: 'operator', groupDateType: '' }), + // 违规明细 + SalesCRMDataStore.getRiskDetailData({ opisn }), + ]); + }, [opisn]); + + const dataFields = (suffix, colRootIndex) => [ + { + key: 'ConfirmRates' + suffix, + title: '成行率', + dataIndex: [suffix, 'ConfirmRates'], + width: '5em', + // CH个人成行率<12%, AH个人成行率<8%刷红 + render: (val, r) => ({ + props: { style: { color: val < (retPropsMinRatesSet?.[r?.retProps || 'default'] || retPropsMinRatesSet.default) ? 'red' : 'green', backgroundColor: COLOR_SETS[colRootIndex]+transparentHex } }, + children: val ? `${val}%` : '', + }), + sorter: (a, b) => (a.groupType === 'overview' ? -1 : b.groupType === 'overview' ? 0 : a[suffix].ConfirmRates - b[suffix].ConfirmRates), + }, + { + key: 'SumML' + suffix, + title: '业绩/万', + dataIndex: [suffix, 'SumML'], + width: '5em', + render: (_, r) => ({ + props: { style: { backgroundColor: COLOR_SETS[colRootIndex]+transparentHex } }, + children: numberConvert10K(_), + }), + sorter: (a, b) => (a.groupType === 'overview' ? -1 : b.groupType === 'overview' ? 0 : a[suffix].SumML - b[suffix].SumML), + }, + { + key: 'ConfirmOrder' + suffix, + title: '团数', + dataIndex: [suffix, 'ConfirmOrder'], + width: '5em', + render: (_, r) => ({ + props: { style: { backgroundColor: COLOR_SETS[colRootIndex]+transparentHex } }, + children: _, + }), + sorter: (a, b) => (a.groupType === 'overview' ? -1 : b.groupType === 'overview' ? 0 : a[suffix].ConfirmOrder - b[suffix].ConfirmOrder), + }, + { + key: 'SumOrder' + suffix, + title: '订单数', + dataIndex: [suffix, 'SumOrder'], + width: '5em', + render: (_, r) => ({ + props: { style: { backgroundColor: COLOR_SETS[colRootIndex]+transparentHex } }, + children: _, + }), + sorter: (a, b) => (a.groupType === 'overview' ? -1 : b.groupType === 'overview' ? 0 : a[suffix].SumOrder - b[suffix].SumOrder), + }, + { + key: 'ResumeOrder' + suffix, + title: '老客户团数', + dataIndex: [suffix, 'ResumeOrder'], + width: '5em', + render: (_, r) => ({ + props: { style: { backgroundColor: COLOR_SETS[colRootIndex]+transparentHex } }, + children: _, + }), + sorter: (a, b) => (a.groupType === 'overview' ? -1 : b.groupType === 'overview' ? 0 : a[suffix].ResumeOrder - b[suffix].ResumeOrder), + }, + { + key: 'ResumeRates' + suffix, + title: '老客户成行率', + dataIndex: [suffix, 'ResumeRates'], + width: '5em', + render: (val, r) => ({ + props: { style: { backgroundColor: COLOR_SETS[colRootIndex]+transparentHex } }, + children: val ? `${val}%` : '' + }), + sorter: (a, b) => (a.groupType === 'overview' ? -1 : b.groupType === 'overview' ? 0 : a[suffix].ResumeRates - b[suffix].ResumeRates), + }, + ]; + const dashboardTableProps = { + rowKey: 'groupsKey', + pagination: false, + size: 'small', + showSorterTooltip: false, + columns: [ + { + title: '', + dataIndex: 'groupsLabel', + key: 'name', + width: '5em', + }, + { + title: () => (<>前90 -30天
{searchValues.date90.Date1} 至 {searchValues.date90.Date2}), + key: 'date', + children: dataFields('result90', 0), + }, + { + title: () => (<>前180 -50天
{searchValues.date180.Date1} 至 {searchValues.date180.Date2}), + key: 'department', + children: dataFields('result180', 1), + }, + ], + rowClassName: (record, rowIndex) => { + return record.groupType === 'overview' ? 'ant-tag-blue' : ''; + }, + }; + const activityTableProps = { + rowKey: 'groupsKey', + pagination: false, + size: 'small', + rowClassName: (record, rowIndex) => { + return record.groupType === 'operator' ? '' : 'ant-tag-blue'; + }, + showSorterTooltip: false, + columns: [ + { title: '', dataIndex: 'groupsLabel', key: 'groupsLabel', width: '6rem' }, // 维度: 顾问 + { + title: '顾问动作', + key: 'date', + children: [ + { + title: () => ( + <> + 首次响应率24H{' '} + + + + + ), + dataIndex: 'firstTouch24', + key: 'firstTouch24', + render: percentageRender, + }, + { + title: () => ( + <> + 48H内报价率{' '} + + + + + ), + dataIndex: 'firstQuote48', + key: 'firstQuote48', + render: percentageRender, + }, + { + title: () => ( + <> + 一次报价率{' '} + + + + + ), + dataIndex: 'quote1', + key: 'quote1', + render: percentageRender, + }, + { + title: () => ( + <> + 二次报价率{' '} + + + + + ), + dataIndex: 'quote2', + key: 'quote2', + render: percentageRender, + }, + { + title: () => ( + <> + >50条会话{' '} + + + + + ), + dataIndex: 'turnsGT50', + key: 'turnsGT50', + render: percentageRender, + }, + { + title: () => ( + <> + 违规数{' '} + + + + + ), + dataIndex: 'violations', + key: 'violations', + }, + ], + }, + { + title: '客人回复', + key: 'department', + children: [ + { + title: () => ( + <> + 首次回复率24H{' '} + + + + + ), + dataIndex: 'firstReply24', + key: 'firstReply24', + render: (_, r) => ({ + props: { style: { backgroundColor: COLOR_SETS[1] + transparentHex } }, + children: percentageRender(_), + }), + }, + { + title: () => ( + <> + 48H内报价回复率{' '} + + + + + ), + dataIndex: 'replyQuote48', + key: 'replyQuote48', + render: (_, r) => ({ + props: { style: { backgroundColor: COLOR_SETS[1] + transparentHex } }, + children: percentageRender(_), + }), + }, + { + title: () => ( + <> + 一次报价回复率{' '} + + + + + ), + dataIndex: 'replyQuote1', + key: 'replyQuote1', + render: (_, r) => ({ + props: { style: { backgroundColor: COLOR_SETS[1] + transparentHex } }, + children: percentageRender(_), + }), + }, + { + title: () => ( + <> + 二次报价回复率{' '} + + + + + ), + dataIndex: 'replyQuote2', + key: 'replyQuote2', + render: (_, r) => ({ + props: { style: { backgroundColor: COLOR_SETS[1] + transparentHex } }, + children: percentageRender(_), + }), + }, + ], + }, + ], + }; + const riskTableProps = { + loading: risk.loading, + sticky: true, + // scroll: { x: 1000, y: 400 }, + pagination: false, + rowKey: (row) => row.coli_id, + columns: [ + { title: '客人姓名', dataIndex: 'guest_name', key: 'guest_name', width: '6rem' }, + { title: '团号', dataIndex: 'coli_id', key: 'coli_id', width: '6rem' }, + { + title: '表单内容', + dataIndex: 'coli_contents', + key: 'coli_contents', + width: '6rem', + render: (text, record) => ( + } + trigger={['click']} + placement="right" + overlayStyle={{ width: '500px', maxHeight: '500px' }} + autoAdjustOverflow={false} + > + + + ), + }, + { title: '顾问', dataIndex: 'opi_name', key: 'opi_name', width: '6rem' }, + { title: '预定时间', dataIndex: 'coli_applydate', key: 'coli_applydate', width: '6rem' }, + ], + }; + + const chartsConfig = { + colFields: ['ConfirmOrder', 'SumOrder'], + lineFields: ['SumML', 'ConfirmRates'], + seriesField: null, + xField: 'groupDateVal', + }; + + return ( + <> + + + 返回 + + +
+

结果指标 @ {searchValues.date.format(DATE_FORMAT)}

+
+ +
+

全年每月业绩 @ {searchValues.date.format('YYYY')}

+ +
+ +
+

过程指标 @ {searchValuesToSub.Date1} 至 {searchValuesToSub.Date2}

+
+ +
+

违规明细

+

>24H回复

+
+ +
+

首次报价周期>48h

+
+ +
+

报价次数<1

+
+ +
+

报价次数<2

+
+ + + ); +});