销售数据子维度分析

feature/2.0-sales-trade
尹诚诚 3 years ago
parent ca41fa993d
commit a8db4f71f3

@ -16,6 +16,7 @@ import WhatsApp_session from "./charts/WhatsApp_session";
import Credit_card_bill from "./views/Credit_card_bill"; import Credit_card_bill from "./views/Credit_card_bill";
import exchange_rate from "./charts/ExchangeRate"; import exchange_rate from "./charts/ExchangeRate";
import Sale from "./views/Sale"; import Sale from "./views/Sale";
import Sale_sub from "./views/Sale_sub";
import Logo from "./logo.png"; import Logo from "./logo.png";
import { stores_Context } from "./config"; import { stores_Context } from "./config";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
@ -101,6 +102,7 @@ const App = () => {
</Route> </Route>
<Route element={<ProtectedRoute auth={["admin", "director_bu", "sale"]} />}> <Route element={<ProtectedRoute auth={["admin", "director_bu", "sale"]} />}>
<Route path="/sale" element={<Sale />} /> <Route path="/sale" element={<Sale />} />
<Route path="/sale_sub/:type_sub" element={<Sale_sub />} />
</Route> </Route>
</Routes> </Routes>
</Content> </Content>

@ -2,5 +2,5 @@ import React from "react";
export const stores_Context = React.createContext(); export const stores_Context = React.createContext();
export const DATE_FORMAT = "YYYY-MM-DD"; export const DATE_FORMAT = "YYYY-MM-DD";
//export const HT_HOST = 'https://p9axztuwd7x8a7.mycht.cn'; export const HT_HOST = 'https://p9axztuwd7x8a7.mycht.cn';
export const HT_HOST = "http://202.103.68.100:890"; //889正式库 //export const HT_HOST = "http://202.103.68.100:890"; //889正式库

@ -9,7 +9,7 @@ class AuthStore {
constructor(rootStore) { constructor(rootStore) {
this.rootStore = rootStore; this.rootStore = rootStore;
makeAutoObservable(this); makeAutoObservable(this);
//this.get_auth(); //放到钉钉环境才能开启 this.get_auth(); //放到钉钉环境才能开启
} }
auth = ['admin']; //开发时候用,正式环境留空 auth = ['admin']; //开发时候用,正式环境留空

@ -2,6 +2,7 @@ import { makeAutoObservable, runInAction } from "mobx";
import moment from "moment"; import moment from "moment";
import * as config from "../config"; import * as config from "../config";
import * as comm from "../utils/commons"; import * as comm from "../utils/commons";
import { NavLink } from "react-router-dom";
//销售数据 //销售数据
class SaleStore { class SaleStore {
@ -18,6 +19,7 @@ class SaleStore {
groups = ["1,2,28,7"]; groups = ["1,2,28,7"];
ml_data = []; //毛利数据 ml_data = []; //毛利数据
type_data = []; //类型的数据 type_data = []; //类型的数据
type_data_sub = []; //类型的子维度数据
date_title = "date_title"; //日期段,只用于显示,防止日期选择控件的变化导致页面刷新 date_title = "date_title"; //日期段,只用于显示,防止日期选择控件的变化导致页面刷新
//选择事业部 //选择事业部
@ -53,8 +55,8 @@ class SaleStore {
this.date_title += ` ${date2_start}~${date2_end}`; this.date_title += ` ${date2_start}~${date2_end}`;
} }
fetch(config.HT_HOST + url) fetch(config.HT_HOST + url)
.then(response => response.json()) .then((response) => response.json())
.then(json => { .then((json) => {
result.push(...json.result1); result.push(...json.result1);
if (!comm.empty(json.result2) && !comm.empty(date_moment.start_date_cp)) { if (!comm.empty(json.result2) && !comm.empty(date_moment.start_date_cp)) {
let diff_days = date_moment.start_date.diff(date_moment.start_date_cp, "days"); let diff_days = date_moment.start_date.diff(date_moment.start_date_cp, "days");
@ -72,7 +74,7 @@ class SaleStore {
this.loading = false; this.loading = false;
}); });
}) })
.catch(error => { .catch((error) => {
this.loading = false; this.loading = false;
console.log("fetch data failed", error); console.log("fetch data failed", error);
}); });
@ -95,8 +97,8 @@ class SaleStore {
this.date_title += ` ${date2_start}~${date2_end}`; this.date_title += ` ${date2_start}~${date2_end}`;
} }
fetch(config.HT_HOST + url) fetch(config.HT_HOST + url)
.then(response => response.json()) .then((response) => response.json())
.then(json => { .then((json) => {
if (!comm.empty(json.result2) && !comm.empty(date_moment.start_date_cp)) { if (!comm.empty(json.result2) && !comm.empty(date_moment.start_date_cp)) {
} else { } else {
if (this.active_tab_key == "All") { if (this.active_tab_key == "All") {
@ -112,40 +114,41 @@ class SaleStore {
}, },
{ {
title: "毛利", title: "毛利",
children: [{ title: "毛利合计", dataIndex: "COLI_ML" }], children: [{ title: json.result1.reduce((a, b) => a + comm.price_to_number(b.COLI_ML), 0), dataIndex: "COLI_ML" }],
sorter: (a, b) => parseInt(b.COLI_ML.replace(/,/g, "")) - parseInt(a.COLI_ML.replace(/,/g, "")), sorter: (a, b) => comm.price_to_number(b.COLI_ML) - comm.price_to_number(a.COLI_ML),
}, },
{ {
title: "成行率", title: "成行率",
children: [{ title: "平均成行率", dataIndex: "COLI_CJrate" }], children: [{ title: "", dataIndex: "COLI_CJrate" }],
sorter: (a, b) => parseInt(b.COLI_CJrate) - parseInt(a.COLI_CJrate), sorter: (a, b) => parseInt(b.COLI_CJrate) - parseInt(a.COLI_CJrate),
}, },
{ {
title: "成团数", title: "成团数",
children: [{ title: "成团数合计", dataIndex: "COLI_CJCount" }], children: [{ title: json.result1.reduce((a, b) => a + b.COLI_CJCount, 0), dataIndex: "COLI_CJCount" }],
sorter: (a, b) => b.COLI_CJCount - a.COLI_CJCount, sorter: (a, b) => b.COLI_CJCount - a.COLI_CJCount,
}, },
{ {
title: "订单数", title: "订单数",
children: [{ title: "订单数合计", dataIndex: "COLI_OrderCount" }], children: [{ title: json.result1.reduce((a, b) => a + b.COLI_OrderCount, 0), dataIndex: "COLI_OrderCount" }],
sorter: (a, b) => b.COLI_OrderCount - a.COLI_OrderCount, sorter: (a, b) => b.COLI_OrderCount - a.COLI_OrderCount,
}, },
{ {
title: "单团毛利", title: "单团毛利",
children: [{ title: "平均单团毛利", dataIndex: "COLI_SingleML" }], children: [{ title: "", dataIndex: "COLI_SingleML" }],
sorter: (a, b) => parseInt(b.COLI_SingleML.replace(/,/g, "")) - parseInt(a.COLI_SingleML.replace(/,/g, "")), sorter: (a, b) => comm.price_to_number(b.COLI_SingleML) - comm.price_to_number(a.COLI_SingleML),
}, },
{ {
title: "成团周期", title: "成团周期",
children: [{ title: "平均成团周期", dataIndex: "COLI_Cycle" }], children: [{ title: "", dataIndex: "COLI_Cycle" }],
sorter: (a, b) => b.COLI_Cycle - a.COLI_Cycle, sorter: (a, b) => b.COLI_Cycle - a.COLI_Cycle,
}, },
]; ];
result.dataSource = json.result1; result.dataSource = json.result1;
} else if (this.active_tab_key == "Country") { } else {
//if (this.active_tab_key == "Country")
//获取类型的项目,去掉重复,作为列名 //获取类型的项目,去掉重复,作为列名
let type_name_arr = []; let type_name_arr = [];
json.result1.map(item => { json.result1.map((item) => {
type_name_arr[item.SubTypeSN] = { SubTypeSN: item.SubTypeSN, SubTypeName: item.SubTypeName }; type_name_arr[item.SubTypeSN] = { SubTypeSN: item.SubTypeSN, SubTypeName: item.SubTypeName };
}); });
@ -153,25 +156,35 @@ class SaleStore {
let type_data_arr = []; let type_data_arr = [];
for (let item of json.result1) { for (let item of json.result1) {
if (comm.empty(type_data["OP_" + item.OPI_SN])) { let op_sn = "OP_" + item.OPI_SN; //顾问的SN
type_data["OP_" + item.OPI_SN] = [{ key: item.OPI_SN }, { T_name: item.OPI_Name }, { T_total: item.OPI_TotalYJLY }]; let items = json.result1.filter((d) => d.OPI_SN == item.OPI_SN); //筛选出有当前顾问的记录
let total_data_value = items.length ? items.reduce((a, b) => a + b.COLI_YJLY, 0) : ""; //记录累加
if (comm.empty(type_data[op_sn])) {
type_data[op_sn] = [{ key: item.OPI_SN }, { T_name: item.OPI_Name }, { T_total: total_data_value }];
} }
type_data["OP_" + item.OPI_SN].push({ ["T_" + item.SubTypeSN]: item.COLI_YJLY }); type_data[op_sn].push({ ["T_" + item.SubTypeSN]: item.COLI_YJLY });
} }
Object.values(type_data).map(item => { Object.values(type_data).map((item) => {
type_data_arr.push( type_data_arr.push(
Object.assign( Object.assign(
...item.map(it => { ...item.map((it) => {
return it; return it;
}) })
) )
); );
}); });
result.columns.push({ title: "顾问", dataIndex: "T_name" }, { title: "合计", dataIndex: "T_total" }); result.columns.push(
type_name_arr.map((item, index) => { { title: "顾问", children: [{ title: "", dataIndex: "T_name", render: (text, record) => <NavLink to={`/sale_sub/${this.active_tab_key}`}>{text}</NavLink> }] },
{ title: "合计", children: [{ title: type_data_arr.reduce((a, b) => a + b.T_total, 0), dataIndex: "T_total" }], sorter: (a, b) => b.T_total - a.T_total }
);
Object.values(type_name_arr).map((item, index) => {
let data_index = "T_" + item.SubTypeSN;
let items = type_data_arr.filter((d) => d[data_index]); //筛选出有对应类型的记录
let total_data_value = items.length ? items.reduce((a, b) => a + b[data_index], 0) : ""; //记录累加
result.columns.push({ result.columns.push({
title: item.SubTypeName, title: item.SubTypeName,
dataIndex: "T_" + item.SubTypeSN, children: [{ title: total_data_value, dataIndex: data_index }],
sorter: (a, b) => b[data_index] - a[data_index],
}); });
}); });
result.dataSource = type_data_arr; result.dataSource = type_data_arr;
@ -182,11 +195,88 @@ class SaleStore {
this.loading_table = false; this.loading_table = false;
}); });
}) })
.catch(error => { .catch((error) => {
this.loading_table = false; this.loading_table = false;
console.log("fetch data failed", error); console.log("fetch data failed", error);
}); });
} }
//子维度查询 beign
get_department_order_ml_by_type_sub(date_moment, type_sub) {
let result = { dataSource: [], columns: [] };
const date1_start = date_moment.start_date.format(config.DATE_FORMAT);
const date1_end = date_moment.end_date.format(config.DATE_FORMAT);
const date2_start = comm.empty(date_moment.start_date_cp) ? "" : date_moment.start_date_cp.format(config.DATE_FORMAT);
const date2_end = comm.empty(date_moment.end_date_cp) ? "" : date_moment.end_date_cp.format(config.DATE_FORMAT);
let url = "/service-web/QueryData/GetDepartmentOrderMLByType_sub";
url += `?DepartmentList=${this.groups.toString()}&DateType=${this.date_type}&subType=${type_sub}&subTypeVal=-1`;
url += `&Date1=${date1_start}&Date2=${date1_end}%2023:59:59`;
if (date2_start && date2_end) {
url += `&OldDate1=${date2_start}&OldDate2=${date2_end}%2023:59:59`;
this.date_title += ` ${date2_start}~${date2_end}`;
}
fetch(config.HT_HOST + url)
.then((response) => response.json())
.then((json) => {
if (!comm.empty(json.result2) && !comm.empty(date_moment.start_date_cp)) {
} else {
result.columns = [
{
title: "",
dataIndex: "OPI_Name",
},
{
title: "毛利",
dataIndex: "COLI_ML",
sorter: (a, b) => b.COLI_ML - a.COLI_ML,
},
{
title: "成行率",
dataIndex: "COLI_CJrate",
sorter: (a, b) => parseFloat(b.COLI_CJrate) - parseFloat(a.COLI_CJrate),
},
{
title: "成团数",
dataIndex: "COLI_CJCount",
},
{
title: "订单数",
dataIndex: "COLI_OrderCount",
sorter: (a, b) => b.COLI_OrderCount - a.COLI_OrderCount,
},
{
title: "单团毛利",
dataIndex: "COLI_SingleML",
},
{
title: "成团周期",
dataIndex: "COLI_Cycle",
},
];
//数据处理,把相同类型放入同一个数组
let type_data = [];
!comm.empty(json.result1) &&
Object.values(json.result1).map((item) => {
let subtype_sn = "type_" + item.subType;
if (comm.empty(type_data[subtype_sn])) {
type_data[subtype_sn] = { subType: item.subType, subType_name: item.subTypeVal, data: [item] };
} else {
type_data[subtype_sn].data.push(item);
}
});
result.dataSource = Object.values(type_data);
}
runInAction(() => {
this.type_data_sub = result;
});
})
.catch((error) => {
console.log("fetch data failed", error);
});
}
//子维度查询 end
} }
export default SaleStore; export default SaleStore;

@ -1,238 +1,254 @@
// https://github.com/uxitten/polyfill/blob/master/string.polyfill.js // https://github.com/uxitten/polyfill/blob/master/string.polyfill.js
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart
import {Tag} from "antd"; import { Tag } from "antd";
import { import { CaretUpOutlined, CaretDownOutlined } from "@ant-design/icons";
CaretUpOutlined,
CaretDownOutlined
} from '@ant-design/icons';
import moment from "moment"; import moment from "moment";
if (!String.prototype.padStart) { if (!String.prototype.padStart) {
String.prototype.padStart = function padStart(targetLength, padString) { String.prototype.padStart = function padStart(targetLength, padString) {
targetLength = targetLength >> 0; //floor if number or convert non-number to 0; targetLength = targetLength >> 0; //floor if number or convert non-number to 0;
padString = String((typeof padString !== 'undefined' ? padString : ' ')); padString = String(typeof padString !== "undefined" ? padString : " ");
if (this.length > targetLength) { if (this.length > targetLength) {
return String(this); return String(this);
} else { } else {
targetLength = targetLength - this.length; targetLength = targetLength - this.length;
if (targetLength > padString.length) { if (targetLength > padString.length) {
padString += padString.repeat(targetLength / padString.length); //append to original to ensure we are longer than needed padString += padString.repeat(targetLength / padString.length); //append to original to ensure we are longer than needed
} }
return padString.slice(0, targetLength) + String(this); return padString.slice(0, targetLength) + String(this);
} }
}; };
} }
export function copy(obj) { export function copy(obj) {
return JSON.parse(JSON.stringify(obj)); return JSON.parse(JSON.stringify(obj));
} }
export function named(value) { export function named(value) {
return function (target) { return function (target) {
target.definedName = value; target.definedName = value;
} };
} }
export function formatCurrency(name) { export function formatCurrency(name) {
if (name === 'USD') { if (name === "USD") {
return '$'; return "$";
} else if (name === 'RMB') { } else if (name === "RMB") {
return '¥'; return "¥";
} else if (name === 'EUR') { } else if (name === "EUR") {
return '€' return "€";
} else if (name === 'GBP') { } else if (name === "GBP") {
return '£' return "£";
} else { } else {
return name + ' '; return name + " ";
} }
} }
export function formatPrice(price) { export function formatPrice(price) {
return Math.ceil(price).toLocaleString(); return Math.ceil(price).toLocaleString();
}
//千分符的金额转成数字默认为0
export function price_to_number(price) {
let num_string = (price + "").replace(/,/g, "");
let number = parseFloat(num_string);
return isNaN(number) ? 0 : number;
} }
export function formatPercent(number) { export function formatPercent(number) {
return Math.round(number * 100) + '%' return Math.round(number * 100) + "%";
} }
export function formatDate(date) { export function formatDate(date) {
if (isEmpty(date)) { if (isEmpty(date)) {
return 'NaN'; return "NaN";
} }
const year = date.getFullYear(); const year = date.getFullYear();
const month = date.getMonth() + 1; const month = date.getMonth() + 1;
const day = date.getDate(); const day = date.getDate();
const monthStr = ('' + month).padStart(2, 0); const monthStr = ("" + month).padStart(2, 0);
const dayStr = ('' + day).padStart(2, 0); const dayStr = ("" + day).padStart(2, 0);
const formatted = year + '-' + monthStr + '-' + dayStr; const formatted = year + "-" + monthStr + "-" + dayStr;
return formatted; return formatted;
} }
export function formatTime(date) { export function formatTime(date) {
const hours = date.getHours(); const hours = date.getHours();
const minutes = date.getMinutes(); const minutes = date.getMinutes();
const hoursStr = ('' + hours).padStart(2, 0); const hoursStr = ("" + hours).padStart(2, 0);
const minutesStr = ('' + minutes).padStart(2, 0); const minutesStr = ("" + minutes).padStart(2, 0);
const formatted = hoursStr + ':' + minutesStr; const formatted = hoursStr + ":" + minutesStr;
return formatted; return formatted;
} }
export function formatDatetime(date) { export function formatDatetime(date) {
const year = date.getFullYear();
const month = date.getMonth() + 1;
const day = date.getDate();
const year = date.getFullYear(); const monthStr = ("" + month).padStart(2, 0);
const month = date.getMonth() + 1; const dayStr = ("" + day).padStart(2, 0);
const day = date.getDate();
const monthStr = ('' + month).padStart(2, 0);
const dayStr = ('' + day).padStart(2, 0);
const hours = date.getHours(); const hours = date.getHours();
const minutes = date.getMinutes(); const minutes = date.getMinutes();
const hoursStr = ('' + hours).padStart(2, 0); const hoursStr = ("" + hours).padStart(2, 0);
const minutesStr = ('' + minutes).padStart(2, 0); const minutesStr = ("" + minutes).padStart(2, 0);
const formatted = year + '-' + monthStr + '-' + dayStr + ' ' + hoursStr + ':' + minutesStr; const formatted = year + "-" + monthStr + "-" + dayStr + " " + hoursStr + ":" + minutesStr;
return formatted; return formatted;
} }
export function mixins(...list) { export function mixins(...list) {
return function (target) { return function (target) {
list.forEach(val => { list.forEach(val => {
const mixinObj = Object.create(val.prototype, {}) const mixinObj = Object.create(val.prototype, {});
const name = Object.getPrototypeOf(mixinObj).constructor.name; const name = Object.getPrototypeOf(mixinObj).constructor.name;
const camelCase = name.substr(0, 1).toLowerCase() + name.substr(1); const camelCase = name.substr(0, 1).toLowerCase() + name.substr(1);
Object.assign(target.prototype, {[camelCase]: mixinObj}) Object.assign(target.prototype, { [camelCase]: mixinObj });
}) });
} };
} }
export function camelCase(name) { export function camelCase(name) {
return name.substr(0, 1).toLowerCase() + name.substr(1); return name.substr(0, 1).toLowerCase() + name.substr(1);
} }
export class UrlBuilder { export class UrlBuilder {
constructor(url) { constructor(url) {
this.url = url; this.url = url;
this.paramList = []; this.paramList = [];
} }
append(name, value) { append(name, value) {
if (isNotEmpty(value)) { if (isNotEmpty(value)) {
this.paramList.push({'name': name, 'value': value}); this.paramList.push({ name: name, value: value });
} }
return this; return this;
} }
build() { build() {
this.paramList.forEach((e, i, a) => { this.paramList.forEach((e, i, a) => {
if (i === 0) { if (i === 0) {
this.url += '?'; this.url += "?";
} else { } else {
this.url += '&'; this.url += "&";
} }
this.url += e.name + '=' + e.value; this.url += e.name + "=" + e.value;
}); });
return this.url; return this.url;
} }
} }
export function isNotEmpty(val) { export function isNotEmpty(val) {
return val !== undefined && val !== null && val !== ''; return val !== undefined && val !== null && val !== "";
} }
export function isEmpty(val) { export function isEmpty(val) {
return val === undefined || val === null || val === ''; return val === undefined || val === null || val === "";
} }
export function empty(a) { export function empty(a) {
if (a === "") return true; //检验空字符串 if (a === "") return true; //检验空字符串
if (a === "null") return true; //检验字符串类型的null if (a === "null") return true; //检验字符串类型的null
if (a === "undefined") return true; //检验字符串类型的 undefined if (a === "undefined") return true; //检验字符串类型的 undefined
if (!a && a !== 0 && a !== "") return true; //检验 undefined 和 null if (!a && a !== 0 && a !== "") return true; //检验 undefined 和 null
if (Array.prototype.isPrototypeOf(a) && a.length === 0) return true; //检验空数组 if (Array.prototype.isPrototypeOf(a) && a.length === 0) return true; //检验空数组
if (Object.prototype.isPrototypeOf(a) && Object.keys(a).length === 0) return true; //检验空对象 if (Object.prototype.isPrototypeOf(a) && Object.keys(a).length === 0) return true; //检验空对象
return false; return false;
} }
export function prepareUrl(url) { export function prepareUrl(url) {
return new UrlBuilder(url); return new UrlBuilder(url);
} }
export function debounce(fn, delay = 500) { export function debounce(fn, delay = 500) {
let timer; let timer;
return (e) => { return e => {
e.persist(); e.persist();
clearTimeout(timer); clearTimeout(timer);
timer = setTimeout(() => { timer = setTimeout(() => {
fn(e); fn(e);
}, delay); }, delay);
}; };
}; }
export function throttle(fn, delay, atleast) { export function throttle(fn, delay, atleast) {
let timeout = null, let timeout = null,
startTime = new Date(); startTime = new Date();
return function () { return function () {
let curTime = new Date(); let curTime = new Date();
clearTimeout(timeout); clearTimeout(timeout);
if (curTime - startTime >= atleast) { if (curTime - startTime >= atleast) {
fn(); fn();
startTime = curTime; startTime = curTime;
} else { } else {
timeout = setTimeout(fn, delay); timeout = setTimeout(fn, delay);
} }
} };
} }
export function clickUrl(url) { export function clickUrl(url) {
const httpLink = document.createElement('a'); const httpLink = document.createElement("a");
httpLink.href = url; httpLink.href = url;
httpLink.target = '_blank'; httpLink.target = "_blank";
httpLink.click(); httpLink.click();
} }
export function show_vs_tag(vs, vs_diff, data1, data2) { export function show_vs_tag(vs, vs_diff, data1, data2) {
let tag = '-'; let tag = "-";
if (parseInt(vs) < 0) { if (parseInt(vs) < 0) {
tag = <Tag icon={<CaretDownOutlined/>} color="gold">{vs} {vs_diff}</Tag> tag = (
} else if (parseInt(vs) > 0) { <Tag icon={<CaretDownOutlined />} color="gold">
tag = <Tag icon={< CaretUpOutlined/>} color="lime">{vs} {vs_diff}</Tag> {vs} {vs_diff}
}// else { </Tag>
// tag = <Tag icon={< CaretUpOutlined/>} color="lime">{vs} {vs_diff}</Tag> );
// } } else if (parseInt(vs) > 0) {
return <span><div>{data1} vs {data2} </div> {tag} </span> tag = (
<Tag icon={<CaretUpOutlined />} color="lime">
{vs} {vs_diff}
</Tag>
);
}
return (
<span>
<div>
{data1} vs {data2}
</div>
{tag}
</span>
);
} }
//数组去掉重复 //数组去掉重复
export function unique(arr) { export function unique(arr) {
let x = new Set(arr); let x = new Set(arr);
return [...x]; return [...x];
} }
export function getWeek (date) { // 参数时间戳 export function getWeek(date) {
let week = moment(date).day(); // 参数时间戳
switch (week) { let week = moment(date).day();
case 1: switch (week) {
return '周一' case 1:
case 2: return "周一";
return '周二' case 2:
case 3: return "周二";
return '周三' case 3:
case 4: return "周三";
return '周四' case 4:
case 5: return "周四";
return '周五' case 5:
case 6: return "周五";
return '周六' case 6:
case 0: return "周六";
return '周日' case 0:
} return "周日";
}
} }

@ -108,9 +108,14 @@ class Orders extends Component {
], ],
}, },
]; ];
//1.找出两个数组OrderType相同的数据做比较显示 2.找出两组数据OrderType都不相同的数据做显示
let has_same_type = false; //数组1在数组2中是否找到相同的类型
for (let item of data.ordercount1) { for (let item of data.ordercount1) {
has_same_type = false;
//数组1在数组2中相同的类型
for (let item2 of data.ordercount2) { for (let item2 of data.ordercount2) {
if (item.OrderType == item2.OrderType) { if (item.OrderType == item2.OrderType) {
has_same_type = true;
result.dataSource.push({ result.dataSource.push({
key: item.key, key: item.key,
OrderType: item.OrderType, OrderType: item.OrderType,
@ -124,6 +129,42 @@ class Orders extends Component {
}); });
} }
} }
//数组1中不在数组2的类型
if (has_same_type == false) {
result.dataSource.push({
key: item.key,
OrderType: item.OrderType,
OrderTypeSN: item.OrderTypeSN,
OrderCount: comm.show_vs_tag(comm.formatPercent(item.OrderCount), item.OrderCount, item.OrderCount, 0),
CJCount: comm.show_vs_tag(comm.formatPercent(item.CJCount), item.CJCount, item.CJCount, 0),
CJPersonNum: comm.show_vs_tag(comm.formatPercent(item.CJPersonNum), item.CJPersonNum, item.CJPersonNum, 0),
CJrate: comm.show_vs_tag(item.CJrate, item.CJrate, item.CJrate, 0),
YJLY: comm.show_vs_tag(comm.formatPercent(item.YJLY), item.YJLY, item.YJLY, 0),
Ordervalue: comm.show_vs_tag(comm.formatPercent(item.Ordervalue), item.Ordervalue, item.Ordervalue, 0),
});
}
}
//数组2中不在数组1的类型
for (let item2 of data.ordercount2) {
has_same_type = false;
for (let item of data.ordercount1) {
if (item.OrderType == item2.OrderType) {
has_same_type = true;
}
}
if (has_same_type == false) {
result.dataSource.push({
key: item2.key,
OrderType: item2.OrderType,
OrderTypeSN: item2.OrderTypeSN,
OrderCount: comm.show_vs_tag(comm.formatPercent(-item2.OrderCount), -item2.OrderCount, 0, item2.OrderCount),
CJCount: comm.show_vs_tag(comm.formatPercent(-item2.CJCount), -item2.CJCount, 0, item2.CJCount),
CJPersonNum: comm.show_vs_tag(comm.formatPercent(-item2.CJPersonNum), -item2.CJPersonNum, 0, item2.CJPersonNum),
CJrate: comm.show_vs_tag(-item2.CJrate, -item2.CJrate, 0, item2.CJrate),
YJLY: comm.show_vs_tag(comm.formatPercent(-item2.YJLY), -item2.YJLY, 0, item2.YJLY),
Ordervalue: comm.show_vs_tag(comm.formatPercent(-item2.Ordervalue), -item2.Ordervalue, 0, item2.Ordervalue),
});
}
} }
} else { } else {
result.columns = [ result.columns = [

@ -2,7 +2,7 @@ import React, { useContext, useEffect } from "react";
import { Row, Col, Button, Tabs, Table, Space, Radio, Select } from "antd"; import { Row, Col, Button, Tabs, Table, Space, Radio, Select } from "antd";
import { ContainerOutlined, SearchOutlined } from "@ant-design/icons"; import { ContainerOutlined, SearchOutlined } from "@ant-design/icons";
import { stores_Context } from "../config"; import { stores_Context } from "../config";
import { Column } from "@ant-design/charts"; import { Column, Pie } from "@ant-design/charts";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import DatePickerCharts from "../charts/DatePickerCharts"; import DatePickerCharts from "../charts/DatePickerCharts";
import { NavLink, useParams } from "react-router-dom"; import { NavLink, useParams } from "react-router-dom";
@ -27,11 +27,53 @@ const Sale = () => {
legend: { legend: {
itemValue: { itemValue: {
formatter: (text, item) => { formatter: (text, item) => {
const items = ml_data.filter(d => d.groups === item.value); //按分组筛选 const items = ml_data.filter((d) => d.groups === item.value); //按分组筛选
return items.length ? items.reduce((a, b) => a + b.COLI_YJLY, 0) : ""; //计算总数 return items.length ? items.reduce((a, b) => a + b.COLI_YJLY, 0) : ""; //计算总数
}, },
}, },
}, },
tooltip: {
// customContent: (title, items) => {
// const data = items[0]?.data || {};
// return `<div>${title}</div><div>${data.seriesField} ${data.yField}</div>`;
// }
title: (title, datum) => {
return title + " " + comm.getWeek(datum.COLI_Date); //显示周几
},
},
};
//格式化数据,饼图只支持数字模式
const format_data_for_pie = (data) => {
let result_arr = [];
if (!comm.empty(data)) {
data.map((item) => {
item.COLI_ML_number = comm.price_to_number(item.COLI_ML);
result_arr.push(item);
});
}
return result_arr;
};
const pie_config = {
appendPadding: 10,
data: format_data_for_pie(type_data.dataSource),
angleField: "COLI_ML_number",
colorField: "OPI_Name",
radius: 0.8,
label: {
type: "outer",
content: "{name} {value} \n {percentage}",
},
legend: false, //不显示图例
interactions: [
{
type: "element-selected",
},
{
type: "element-active",
},
],
}; };
return ( return (
@ -42,8 +84,8 @@ const Sale = () => {
<Row> <Row>
<Col md={24} lg={7} xxl={6}> <Col md={24} lg={7} xxl={6}>
<GroupSelect store={sale_store} /> <GroupSelect store={sale_store} />
<Select value={sale_store.date_type} style={{ width: "95%" }} onChange={value => sale_store.onChange_datetype(value)}> <Select value={sale_store.date_type} style={{ width: "95%" }} onChange={(value) => sale_store.onChange_datetype(value)}>
<Select.Option key="1" value="okDate"> <Select.Option key="1" value="ConfirmDate">
确认日期 确认日期
</Select.Option> </Select.Option>
<Select.Option key="2" value="applyDate"> <Select.Option key="2" value="applyDate">
@ -81,31 +123,55 @@ const Sale = () => {
<Col className="gutter-row" md={24}> <Col className="gutter-row" md={24}>
<Tabs <Tabs
activeKey={sale_store.active_tab_key} activeKey={sale_store.active_tab_key}
onChange={active_key => { onChange={(active_key) => {
sale_store.onChange_Tabs(active_key); sale_store.onChange_Tabs(active_key);
sale_store.get_department_order_ml_by_type(date_picker_store); sale_store.get_department_order_ml_by_type(date_picker_store);
}}> }}>
<Tabs.TabPane <Tabs.TabPane
tab={ tab={
<span> <span>
<ContainerOutlined /> <ContainerOutlined /> 总览
概览
</span> </span>
} }
key="All"></Tabs.TabPane> key="All"></Tabs.TabPane>
<Tabs.TabPane <Tabs.TabPane
tab={ tab={
<span> <span>
<ContainerOutlined /> <ContainerOutlined /> 国籍
国籍
</span> </span>
} }
key="Country"></Tabs.TabPane> key="Country"></Tabs.TabPane>
<Tabs.TabPane
tab={
<span>
<ContainerOutlined />
产品类型
</span>
}
key="Product"></Tabs.TabPane>
<Tabs.TabPane
tab={
<span>
<ContainerOutlined />
出行目的
</span>
}
key="TravelMotivation"></Tabs.TabPane>
<Tabs.TabPane
tab={
<span>
<ContainerOutlined />
成员关系
</span>
}
key="GuestGroupType"></Tabs.TabPane>
</Tabs> </Tabs>
<Row> <Row>
<Col span={24}> <Col span={24}>
{sale_store.date_title} <Table dataSource={type_data.dataSource} columns={type_data.columns} size="small" rowKey={(record) => record.key} loading={sale_store.loading_table} pagination={false} scroll={{ x: "100%" }} />
<Table dataSource={type_data.dataSource} columns={type_data.columns} size="small" rowKey={record => record.key} loading={sale_store.loading_table} pagination={false} scroll={{ x: "100%" }} /> </Col>
<Col sm={24} lg={12}>
{sale_store.active_tab_key == "All" ? <Pie {...pie_config} /> : ""}
</Col> </Col>
</Row> </Row>
</Col> </Col>

@ -0,0 +1,44 @@
import React, { useContext, useEffect } from "react";
import { Row, Col, Button, Divider, Table, Space, Radio, Select } from "antd";
import { ContainerOutlined, SearchOutlined } from "@ant-design/icons";
import { stores_Context } from "../config";
import { Column, Pie } from "@ant-design/charts";
import { observer } from "mobx-react";
import DatePickerCharts from "../charts/DatePickerCharts";
import { NavLink, useParams } from "react-router-dom";
import * as comm from "../utils/commons";
import * as config from "../config";
import GroupSelect from "../charts/GroupSelect";
const Sale_sub = () => {
const { type_sub } = useParams();
const { sale_store, date_picker_store } = useContext(stores_Context);
useEffect(() => {
sale_store.get_department_order_ml_by_type_sub(date_picker_store, type_sub);
}, []);
const type_data = comm.empty(sale_store.type_data_sub) ? { dataSource: [], columns: [] } : sale_store.type_data_sub;
return (
<div>
<Row>
<Col span={24}>
<NavLink to={`/sale`}>返回</NavLink>
</Col>
</Row>
<Row gutter={{ sm: 16, lg: 32 }}>
{!comm.empty(type_data.dataSource) &&
type_data.dataSource.map((item) => {
return (
<Col md={24} lg={12}>
<Divider orientation="left">{item.subType_name}</Divider>
<Table key={item.subType} dataSource={item.data} columns={type_data.columns} size="small" rowKey={(record) => record.key} loading={sale_store.loading_table} pagination={false} scroll={{ x: "100%" }} />
</Col>
);
})}
</Row>
</div>
);
};
export default observer(Sale_sub);
Loading…
Cancel
Save