import moment from 'moment'; import { groupBy } from '../../utils/commons'; export const datePartOptions = [ { label: '日', value: 'day' }, { label: '周', value: 'week' }, { label: '月', value: 'month' }, { label: '季', value: 'season' }, { label: '年', value: 'year' }, ]; export const datePartMethod = { 'day': (date) => { return { 'dateKey': date, 'groupKey': date, date }; }, 'week': (date, ...args) => { const dateO = moment(date); const year = dateO.weekYear(); const week = dateO.week(); // const weekOfMonth = dateO.week() - moment(date).startOf('month').week() + 1; const key = `W${String(week).padStart(2, '0')}`; const dateKey = `${year}-W${String(week).padStart(2, '0')}`; return { dateKey, 'groupKey': dateKey, date }; }, 'season': (date) => { const dateO = moment(date); // const key = dateO.format('YYYY-Q'); const key = `${dateO.year()}-${String(dateO.quarter()).padStart(2, 'Q')}`; const dateKey = `${dateO.year()}-${String(dateO.quarter()).padStart(2, 'Q')}`; return { dateKey, 'groupKey': key, date }; }, 'month': (date) => { const dateO = moment(date); const key = dateO.format('YYYY-MM'); const dateKey = dateO.format('YYYY-MM'); return { dateKey, 'groupKey': key, date }; }, 'year': (date) => { const dateO = moment(date); const key = dateO.format('YYYY'); const dateKey = dateO.format('YYYY'); return { dateKey, 'groupKey': key, date }; }, }; /** * * @param {Array} data 结果数组 * @param {*} dateType 切换的日期类型 * @param {Object} mapper 映射结果字段 * @returns {Object} { data, avg } * * data: 转换后的数组 * * avg: 平均值 */ export const parseDateType = (data, dateType = 'day', { dateKey, valueKey, seriesKey, _f }) => { const _calcF = { 'avg': (sum, len) => sum / len, }; const seriesDataMapped = data.reduce((r, v) => { const _k = v[seriesKey]; (r[_k] || (r[_k] = [])).push(v); return r; }, {}); const everySeries = Object.keys(seriesDataMapped).reduce((rs, _series) => { const e = seriesDataMapped[_series].reduce((r, v) => { const datePart = datePartMethod[dateType](v[dateKey]); const mergeKey = `${datePart.groupKey}@${_series}`; (r[mergeKey] || (r[mergeKey] = [])).push({ ...v, 'dateKey': datePart.dateKey, 'groupKey': datePart.groupKey, datePart }); return r; }, {}); return { ...rs, ...e }; }, {}); const resultKeys = Object.keys(everySeries); resultKeys.sort(); const dateArr = []; const groupSum = resultKeys.reduce((a, key) => { const [_dateKey, _seriesKey] = key.split('@'); dateArr.push(_dateKey); const containDate = everySeries[key].map((ele) => ele.datePart.date); const containDateM = [...new Set(containDate)].map((ele) => moment(ele)); const min = moment.min(containDateM).format('YYYY-MM-DD'); const max = moment.max(containDateM).format('YYYY-MM-DD'); const dateRangeStr = min === max ? min : `${min}~${max}`; const dateRange = [min, max]; const summaryVal = everySeries[key].reduce((rows, row) => rows + row[valueKey], 0); const retValue = _f === 'sum' ? summaryVal : _calcF(summaryVal, everySeries[key].length); a.push({ groupKey: key, value: retValue, dateKey: dateRangeStr, dateRange, containDate, [seriesKey]: _seriesKey, [dateKey]: _dateKey }); return a; }, []); const avgDiv = [...new Set(dateArr)].length; const avgVal = groupSum.length !== 0 ? groupSum.reduce((s, c) => s + c.value, 0) / avgDiv : 0; return { data: groupSum, avgVal }; }; /** * * @param {Array} dataRaw 结果数组 * @param {*} dateGroup 切换的日期类型, radio onchange 的值 * @param {Object} dataMapper 映射数据集字段 { data1, data2 } * @param {Object} mapper 映射结果字段 { dateKey, valueKey, _f } * * dateKey: 日期. 'ApplyDate' * * valueKey: 结果. 'orderCount' * * seriesKey: 序列. 'WebCode' * * _f: 计算方法. 'sum' | 'avg * @author LYT */ export const resultDataCb = (dataRaw, dateGroup, { data1, data2 }, fieldMapper, cb) => { const _data1 = data1 ? dataRaw[data1] : dataRaw; const _data2 = data2 ? dataRaw[data2] : []; const parse1 = parseDateType(_data1, dateGroup, fieldMapper); const parseData1 = parse1.data.map((ele) => ({ [fieldMapper.dateKey]: ele[fieldMapper.dateKey], [fieldMapper.valueKey]: ele.value, [fieldMapper.seriesKey]: ele[fieldMapper.seriesKey], groups: _data1[0].groups, dateKey: ele.dateKey, dateRange: ele.dateRange, dateGroup: ele[fieldMapper.dateKey], })); const parse2 = parseDateType(_data2, dateGroup, fieldMapper); const parseData2 = parse2.data.map((ele) => ({ [fieldMapper.dateKey]: ele[fieldMapper.dateKey], // [fieldMapper.dateKey]: ele.groupKey, [fieldMapper.valueKey]: ele.value, [fieldMapper.seriesKey]: ele[fieldMapper.seriesKey], groups: _data2[0].groups, dateKey: ele.dateKey, dateRange: ele.dateRange, dateGroup: ele[fieldMapper.dateKey], })); const data1KeyMapped = parseData1.reduce((r, v) => { const _k = v[fieldMapper.dateKey]; const allDate0 = moment.min([...new Set((r[_k] || []).concat(moment(v.dateRange[0])))]); r[_k] = [allDate0]; return r; }, {}); const data1KeyMappedStr = Object.keys(data1KeyMapped).reduce((r, v) => ({...r, [v]: data1KeyMapped[v][0].format('YYYY-MM-DD')}), {}); const data2KeyMapped = parseData2.reduce((r, v) => { const _k = v[fieldMapper.dateKey]; const allDate0 = moment.min([...new Set((r[_k] || []).concat(moment(v.dateRange[0])))]); r[_k] = [allDate0]; return r; }, {}); const data2KeyMappedStr = Object.keys(data2KeyMapped).reduce((r, v) => ({...r, [v]: data2KeyMapped[v][0].format('YYYY-MM-DD')}), {}); const groupBykeyD1 = Object.keys(groupBy(parseData1, ele => ele[fieldMapper.dateKey])); const groupBykeyD2 = Object.keys(groupBy(parseData2, ele => ele[fieldMapper.dateKey])); const keyMapped = { ...groupBykeyD2.reduce((obj, k, i) => ({...obj, [k]: groupBykeyD1[i] || k}), {}) }; const reindexData2 = parseData2.map((ele, index) => ({ ...ele, [fieldMapper.dateKey]: keyMapped[ele[fieldMapper.dateKey]], dateKey: ele.dateKey, })); const retData = [].concat(parseData1, reindexData2 ).map(ele => ({...ele, [fieldMapper.dateKey]: data1KeyMappedStr[ele[fieldMapper.dateKey]] || data2KeyMappedStr[ele[fieldMapper.dateKey]]})); const avg1 = parse1.avgVal; // console.log('callback', dateGroup, retData, avg1, parse2.avgVal, data1KeyMappedStr, data2KeyMappedStr); cb(dateGroup, retData, avg1, parse2.avgVal); };