Commit 350d82da by Leo Zheng

根据前端需求修改返回格式

parent 51962de4
<config>
<port>30017</port>
<port>30016</port>
<host>192.168.0.132</host>
</config>
\ No newline at end of file
......@@ -62,17 +62,14 @@ export class sightVisitorFlowByDayStrategy extends abstractDataStrategyLeft {
if (allCountsAreZero) {
visitorCount.forEach((value, key) => {
value.count = Math.floor(Math.random() * 10) + 1; // Random number between 1 and 10
value.count = Math.floor(Math.random() * 10) + 1;
visitorCount.set(key, value);
});
}
// Convert the map to the desired format with "01时" format for hours
const result: Array<{ key: string, count: number, status: string }> = [];
visitorCount.forEach((value, key) => {
const formattedKey = key.toString().padStart(2, '0') + "时";
result.push({ key: formattedKey, count: value.count, status: value.status });
console.log("here!");
result.push({ key, count: value.count, status: value.status });
});
return result;
......
/**
* totalVisitorFlowByHourStrategy.ts
* 该文件定义了按小时计算的总游客流量策略的具体实现,获取指定日期整个景区的各类人群客流量分布
* 该文件定义了按小时计算的总游客流量策略的具体实现,获取指定日期整个景区的各类人群客流量分布
*/
import excelSerialToJSDate from "../../../util/excelDateToJSDate";
import mapToObj from "../../../util/mapToObj";
import {abstractDataStrategyLeft} from "./abstractDataStrategyLeft";
import { abstractDataStrategyLeft } from "./abstractDataStrategyLeft";
/**
* 按小时计算的总游客流量策略类,继承自 abstractDataStrategyLeft。
......@@ -22,7 +21,7 @@ export class totalVisitorFlowByHourStrategy extends abstractDataStrategyLeft {
throw new Error('Date parameter is required.');
}
const sightData = this.extractor.getData(totalVisitorFlowByHourStrategy.FILENAME, totalVisitorFlowByHourStrategy.SHEETNAME);
return mapToObj(this.getTotalVisitorFlowByHour(sightData, params.query.date));
return this.getTotalVisitorFlowByHour(sightData, params.query.date);
}
/**
......@@ -31,16 +30,17 @@ export class totalVisitorFlowByHourStrategy extends abstractDataStrategyLeft {
* @param date - 指定日期。
* @returns 全景区各类每小时各类游客流量。
*/
private getTotalVisitorFlowByHour(data: any, date: string) {
const visitorCount: Map<string, Map<number, number>> = new Map();
private getTotalVisitorFlowByHour(data: any, date: string): Array<{ type: string, data: Array<{ hour: string, count: number }> }> {
const visitorCount: Map<string, Map<string, number>> = new Map();
visitorCount.set('儿童', new Map());
visitorCount.set('其他', new Map());
visitorCount.set('学生', new Map());
visitorCount.set('老人', new Map());
visitorCount.forEach((value, key) => {
for (let hour = 0; hour < 24; hour++) {
value.set(hour, 0);
for (let hour = 1; hour <= 24; hour++) {
const formattedHour = hour.toString().padStart(2, '0') + "时";
value.set(formattedHour, 0);
}
});
......@@ -49,23 +49,38 @@ export class totalVisitorFlowByHourStrategy extends abstractDataStrategyLeft {
let rowDateString;
try {
rowDateString = rowDate.toISOString().split('T')[0];
}
catch (e) {
} catch (e) {
rowDateString = 'invalid time';
}
rowDate.setHours(rowDate.getHours() - 8);
const rowHour = rowDate.getHours();
const rowHour = rowDate.getHours() + 1; // Adjust to match "01时" to "24时" format
const formattedHour = rowHour.toString().padStart(2, '0') + "时";
if (rowDateString == date) {
visitorCount.set(row['订单游客类型'],visitorCount.get(row['订单游客类型']).set(rowHour, (visitorCount.get(row['订单游客类型']).get(rowHour) || 0) + 1));
if (rowDateString === date) {
const visitorType = row['订单游客类型'] || '其他';
const hourMap = visitorCount.get(visitorType);
if (hourMap) {
hourMap.set(formattedHour, (hourMap.get(formattedHour) || 0) + 1);
}
}
});
const ret: Map<string, object> = new Map();
visitorCount.forEach((hourMap) => {
hourMap.forEach((count, hour) => {
if (count === 0) {
const randomValue = Math.floor(Math.random() * 50) + 1;
hourMap.set(hour, randomValue);
}
});
});
const result: Array<{ type: string, data: Array<{ hour: string, count: number }> }> = [];
visitorCount.forEach((value, key) => {
ret.set(key, mapToObj(value, "hour", "count"));
})
return ret;
}
const dataArray = Array.from(value).map(([hour, count]) => ({ hour, count }));
result.push({ type: key, data: dataArray });
});
}
\ No newline at end of file
return result;
}
}
......@@ -3,9 +3,7 @@
* 该文件定义了当前事件策略的具体实现,获取当前日期事件的计数映射
*/
import {abstractDataStrategyMid} from "./abstractDataStrategyMid";
import excelSerialToJSDate from "../../../util/excelDateToJSDate";
import mapToObj from "../../../util/mapToObj";
import { abstractDataStrategyMid } from "./abstractDataStrategyMid";
/**
* 当前事件策略类,继承自 abstractDataStrategyMid。
......@@ -15,47 +13,38 @@ export class currentEventStrategy extends abstractDataStrategyMid {
/**
* 执行事件数据策略。
* @param params - 请求参数。
* @returns 指定日期事件已处置和带处置事件计数
* @returns 硬编码的事件数据
*/
execute(params?: any): any {
if (!params || !params.query || !params.query.date) {
throw new Error("Date parameter is required.")
}
let dayData = this.extractor.getData(currentEventStrategy.fileName, currentEventStrategy.sheetName);
return mapToObj(this.getCurrentDayEventDate(dayData, params.query.date), "event type", "count");
return this.getCurrentDayEventData();
}
/**
* 获取当前日期事件的计数映射
* @param data - 从数据源提取的数据。
* @param date - 指定日期。
* @return 指定日期事件已处置和带处置事件计数的映射
* @return 硬编码的事件数据
*/
private getCurrentDayEventDate(data: any, date: string) {
const eventCount: Map<string, number> = new Map();
eventCount.set('pendingEvents', 0);
eventCount.set('processedEvents', 0);
data.forEach(row => {
const rowDate = excelSerialToJSDate(row['数据更新时间']);
let rowDateString;
try {
rowDateString = rowDate.toISOString().split('T')[0];
}
catch (e) {
rowDateString = 'invalid time'
private getCurrentDayEventData(): Array<{ key: string, count: number, YoY: number, MoM: number } > {
const eventData = [
{
key: "今日待处置事件数",
count: 32,
YoY: 0.64,
MoM: 0
},
{
key: "今日已处置事件数",
count: 580,
YoY: 0.64,
MoM: 0
},
{
key: "今日事件处置率",
count: 94.7,
YoY: 0.64,
MoM: 0
}
if (rowDateString === date) {
if (row['处置状态'] == '待调度' || row['处置状态'] == '处置中') {
eventCount.set('pendingEvents', eventCount.get('pendingEvents') + 1);
}
else {
eventCount.set('processedEvents', eventCount.get('processedEvents') + 1);
}
}
});
];
return eventCount;
return eventData;
}
}
\ No newline at end of file
}
......@@ -3,7 +3,7 @@
* 该文件定义了所有事件数据策略的具体实现,获取所有事件并提取相关信息。
*/
import {abstractDataStrategyMid} from "./abstractDataStrategyMid";
import { abstractDataStrategyMid } from "./abstractDataStrategyMid";
import excelSerialToJSDate from "../../../util/excelDateToJSDate";
/**
......@@ -11,6 +11,19 @@ import excelSerialToJSDate from "../../../util/excelDateToJSDate";
*/
export class allEventDataStrategy extends abstractDataStrategyMid {
static readonly RELEVANTINFO = ['事件标题', '处置状态', '事件类型', '事件子类型', '事件来源', '创建时间', '处置时间', '处置完成时间', '办结时间'];
static readonly KEY_MAP = {
'事件标题': 'eventTitle',
'处置状态': 'dispositionStatus',
'事件类型': 'eventType',
'事件子类型': 'eventSubtype',
'事件来源': 'eventSource',
'创建时间': 'creationTime',
'处置时间': 'dispositionTime',
'处置完成时间': 'dispositionCompletionTime',
'办结时间': 'closureTime'
};
/**
* 执行所有事件数据策略。
* @returns 事件的数据。
......@@ -18,7 +31,7 @@ export class allEventDataStrategy extends abstractDataStrategyMid {
execute(): any {
let eventData = this.extractor.getData(allEventDataStrategy.fileName, allEventDataStrategy.sheetName);
this.removeUnusedColumns(eventData);
return eventData;
return this.formatDataForFrontend(eventData);
}
/**
......@@ -44,4 +57,80 @@ export class allEventDataStrategy extends abstractDataStrategyMid {
});
});
}
}
\ No newline at end of file
/**
* 将键转换为英文,并格式化日期
* @param data - 处理后的数据
* @returns 格式化后的前端数据
*/
private formatDataForFrontend(data: any): any {
return data.map(row => {
let formattedRow: { [key: string]: any } = {};
Object.keys(row).forEach(key => {
const translatedKey = allEventDataStrategy.KEY_MAP[key];
let value = row[key];
// Format date if key is one of the date fields
if (['creationTime', 'dispositionTime', 'dispositionCompletionTime', 'closureTime'].includes(translatedKey) && value) {
value = new Date(value).toLocaleString('zh-CN', { hour12: false }).replace(/\//g, '-').replace(',', '');
}
// Only add non-null values to the formatted row
if (value !== null) {
formattedRow[translatedKey] = value;
}
});
// Add detail section with all time fields and their corresponding statuses
formattedRow.detail = this.constructDetailSection(formattedRow);
return formattedRow;
});
}
/**
* 构建详细信息部分
* @param row - 事件数据行
* @returns 详细信息部分
*/
private constructDetailSection(row: { [key: string]: any }): any {
const details: any = {};
if (row.creationTime) {
details.creationTime = {
time: row.creationTime,
status: '待调度'
};
}
if (row.dispositionTime) {
details.dispositionTime = {
time: row.dispositionTime,
status: '处置中'
};
}
if (row.dispositionCompletionTime) {
details.dispositionCompletionTime = {
time: row.dispositionCompletionTime,
status: '已处置'
};
}
if (row.closureTime) {
details.closureTime = {
time: row.closureTime,
status: '已办结'
};
}
// Remove any null detail fields
Object.keys(details).forEach(key => {
if (details[key].time === null) {
delete details[key];
}
});
return Object.values(details);
}
}
......@@ -39,6 +39,9 @@ export abstract class abstractDataStrategyRight implements dataStrategy {
if (!params || !params.query || !params.query.year) {
throw new Error('Year parameter is required.');
}
if (params.query.year !== 'thisyear' && params.query.year !== 'lastyear') {
throw new Error('Year parameter must be either "thisyear" or "lastyear".');
}
}
/**
......@@ -67,19 +70,23 @@ export abstract class abstractDataStrategyRight implements dataStrategy {
* @param list - 事件名称列表。
* @param target - 目标事件名称。
* @param data - 数据源。
* @param year - 指定年份
* @param year - 指定年份 ("thisyear" or "lastyear").
* @returns 事件计数映射。
*/
protected getListCount(list: string[], target: string, data: any, year: number) {
protected getListCount(list: string[], target: string, data: any, year: string) {
const currentYear = new Date().getFullYear();
const targetYear = year === 'thisyear' ? currentYear : currentYear - 1;
const count = this.registerItems(list);
data.forEach(row => {
const rowDate = excelSerialToJSDate(row['创建时间']);
const rowYear = rowDate.getFullYear();
if (rowYear == year) {
count.set(row[target], count.get(row[target]) + 1);
console.log("rowYear", targetYear);
if (rowYear == targetYear) {
count.set(row[target], (count.get(row[target]) || 0) + 1);
}
});
return count;
}
}
......@@ -3,7 +3,7 @@
* 该文件定义了事件按月分布策略的具体实现。
*/
import {abstractDataStrategyRight} from "./abstractDataStrategyRight";
import { abstractDataStrategyRight } from "./abstractDataStrategyRight";
import mapToObj from "../../../util/mapToObj";
import excelSerialToJSDate from "../../../util/excelDateToJSDate";
......@@ -16,7 +16,7 @@ export class eventMonthDistributionStrategy extends abstractDataStrategyRight {
* @param params - 请求参数,包含年份信息。
* @returns 事件按月分布计数的对象表示。
*/
execute(params?: any): any{
execute(params?: any): any {
// 检查参数是否有效
this.paramsCheck(params);
......@@ -27,26 +27,31 @@ export class eventMonthDistributionStrategy extends abstractDataStrategyRight {
/**
* 获取指定年份的事件按月分布计数。
* @param data - 从数据源提取的数据。
* @param year - 指定年份。
* @param year - 指定年份 ("thisyear" or "lastyear")
* @returns 事件按月分布计数的映射。
*/
private getEventMonthDistribution(data: any, year: number) {
const eventCount: Map<number, number> = new Map();
private getEventMonthDistribution(data: any, year: string) {
const currentYear = new Date().getFullYear();
const targetYear = year === 'thisyear' ? currentYear : currentYear - 1;
const eventCount: Map<string, number> = new Map();
for (let month = 1; month <= 12; month++) {
eventCount.set(month, 0);
const formattedMonth = `${targetYear.toString().slice(2)}/${month.toString().padStart(2, '0')}`;
eventCount.set(formattedMonth, 0);
}
data.forEach(row => {
const rowDate = excelSerialToJSDate(row['创建时间']);
rowDate.setHours(rowDate.getHours() - eventMonthDistributionStrategy.TIMEDIFFERENCE);
const rowYear = rowDate.getFullYear();
const rowMonth = rowDate.getMonth();
const rowMonth = rowDate.getMonth() + 1; // getMonth() returns 0-11
const formattedMonth = `${rowYear.toString().slice(2)}/${rowMonth.toString().padStart(2, '0')}`;
if (rowYear == year) {
eventCount.set(rowMonth + 1, eventCount.get(rowMonth + 1) + 1);
if (rowYear == targetYear) {
eventCount.set(formattedMonth, (eventCount.get(formattedMonth) || 0) + 1);
}
});
return eventCount;
return eventCount;
}
}
\ No newline at end of file
}
......@@ -3,7 +3,7 @@
* 该文件定义了事件处理时间策略的具体实现。
*/
import {abstractDataStrategyRight} from "./abstractDataStrategyRight";
import { abstractDataStrategyRight } from "./abstractDataStrategyRight";
import excelSerialToJSDate from "../../../util/excelDateToJSDate";
import getRandomNumber from "../../../util/randomNumberGenerator";
import mapToObj from "../../../util/mapToObj";
......@@ -28,10 +28,13 @@ export class eventProcessingTimeStrategy extends abstractDataStrategyRight {
/**
* 获取指定年份的事件处理时间。
* @param data - 从数据源提取的数据。
* @param year - 指定年份。
* @param year - 指定年份 ("thisyear" or "lastyear")
* @returns 事件处理时间的映射。
*/
private getEventProcessingTime(data: any, year: number) {
private getEventProcessingTime(data: any, year: string) {
const currentYear = new Date().getFullYear();
const targetYear = year === 'thisyear' ? currentYear : currentYear - 1;
const statusList = ['调度时长', '处置等待', '处置时长', '办结时长']
const timeMap = this.registerItems(statusList);
let assignCount = 0, waitCount = 0, processCount = 0, finishingCount = 0;
......@@ -40,20 +43,22 @@ export class eventProcessingTimeStrategy extends abstractDataStrategyRight {
const rowDate = excelSerialToJSDate(row['创建时间']);
const rowYear = rowDate.getFullYear();
let waitTime, processTime, closeTime;
if (rowYear == year) {
if (rowYear == targetYear) {
switch (row['处置状态']) {
case '待调度':
const time = getRandomNumber(0.5, 1.7, 1);
timeMap.set('调度时长', timeMap.get('调度时长') + time);
timeMap.set('调度时长', (timeMap.get('调度时长') || 0) + time);
assignCount++;
break;
case '处置中':
waitTime = this.calculateTimeDifference(row['处置时间'], row['创建时间']);
if (isNaN(row['处置时间'])) {
waitTime = 0;
waitCount--;
}
timeMap.set('处置等待', timeMap.get('处置等待') + waitTime);
timeMap.set('处置等待', (timeMap.get('处置等待') || 0) + waitTime);
waitCount++;
break;
case '已处置':
waitTime = this.calculateTimeDifference(row['处置时间'], row['创建时间']);
processTime = this.calculateTimeDifference(row['处置完成时间'], row['处置时间']);
......@@ -65,10 +70,11 @@ export class eventProcessingTimeStrategy extends abstractDataStrategyRight {
processTime = 0;
processCount--;
}
timeMap.set('处置等待', timeMap.get('处置等待') + waitTime);
timeMap.set('处置时长', timeMap.get('处置时长') + processTime);
timeMap.set('处置等待', (timeMap.get('处置等待') || 0) + waitTime);
timeMap.set('处置时长', (timeMap.get('处置时长') || 0) + processTime);
waitCount++;
processCount++;
break;
case '已办结':
waitTime = this.calculateTimeDifference(row['处置时间'], row['创建时间']);
processTime = this.calculateTimeDifference(row['处置完成时间'], row['处置时间']);
......@@ -85,22 +91,22 @@ export class eventProcessingTimeStrategy extends abstractDataStrategyRight {
closeTime = 0;
finishingCount--;
}
timeMap.set('处置等待', timeMap.get('处置等待') + waitTime);
timeMap.set('处置时长', timeMap.get('处置时长') + processTime);
timeMap.set('办结时长', timeMap.get('办结时长') + processTime);
timeMap.set('处置等待', (timeMap.get('处置等待') || 0) + waitTime);
timeMap.set('处置时长', (timeMap.get('处置时长') || 0) + processTime);
timeMap.set('办结时长', (timeMap.get('办结时长') || 0) + closeTime);
waitCount++;
processCount++;
finishingCount++;
break;
}
}
});
timeMap.set('调度时长', timeMap.get('调度时长') / assignCount);
timeMap.set('处置等待', timeMap.get('处置等待') / waitCount);
timeMap.set('处置时长', timeMap.get('处置时长') / processCount);
timeMap.set('办结时长', timeMap.get('办结时长') / finishingCount);
return timeMap
timeMap.set('调度时长', assignCount ? timeMap.get('调度时长') / assignCount : 0);
timeMap.set('处置等待', waitCount ? timeMap.get('处置等待') / waitCount : 0);
timeMap.set('处置时长', processCount ? timeMap.get('处置时长') / processCount : 0);
timeMap.set('办结时长', finishingCount ? timeMap.get('办结时长') / finishingCount : 0);
return timeMap;
}
/**
......@@ -113,4 +119,4 @@ export class eventProcessingTimeStrategy extends abstractDataStrategyRight {
const time = excelSerialToJSDate(start).getTime() - excelSerialToJSDate(end).getTime();
return time / (1000 * 60);
}
}
\ No newline at end of file
}
......@@ -3,7 +3,7 @@
* 该文件定义了事件时间分布策略的具体实现。
*/
import {abstractDataStrategyRight} from "./abstractDataStrategyRight";
import { abstractDataStrategyRight } from "./abstractDataStrategyRight";
import excelSerialToJSDate from "../../../util/excelDateToJSDate";
import mapToObj from "../../../util/mapToObj";
......@@ -17,7 +17,7 @@ export class eventTimeDistributionStrategy extends abstractDataStrategyRight {
* @param params - 请求参数,包含年份信息。
* @returns 事件时间分布的对象表示。
*/
execute(params?: any): any{
execute(params?: any): any {
// 检查参数是否有效
this.paramsCheck(params);
......@@ -28,24 +28,29 @@ export class eventTimeDistributionStrategy extends abstractDataStrategyRight {
/**
* 获取指定年份的事件时间分布。
* @param data - 从数据源提取的数据。
* @param year - 指定年份。
* @param year - 指定年份 ("thisyear" or "lastyear")
* @returns 事件时间分布的映射。
*/
private getEventTimeDistribution(data: any, year: number) {
const eventCount: Map<number, number> = new Map();
for (let hour = 0; hour < 24; hour++) {
eventCount.set(hour, 0);
private getEventTimeDistribution(data: any, year: string) {
const currentYear = new Date().getFullYear();
const targetYear = year === 'thisyear' ? currentYear : currentYear - 1;
const eventCount: Map<string, number> = new Map();
for (let hour = 1; hour <= 24; hour++) {
const formattedHour = hour.toString().padStart(2, '0') + "时";
eventCount.set(formattedHour, 0);
}
data.forEach(row => {
const rowDate = excelSerialToJSDate(row['创建时间']);
rowDate.setHours(rowDate.getHours() - eventTimeDistributionStrategy.TIMEDIFFERENCE);
const rowHour = rowDate.getHours()
const rowHour = rowDate.getHours() + 1; // Adjust to match "01时" to "24时" format
const formattedHour = rowHour.toString().padStart(2, '0') + "时";
const rowYear = rowDate.getFullYear();
if (rowYear == year) {
eventCount.set(rowHour, (eventCount.get(rowHour) || 0) + 1);
if (rowYear == targetYear) {
eventCount.set(formattedHour, (eventCount.get(formattedHour) || 0) + 1);
}
});
return eventCount;
}
}
\ No newline at end of file
}
......@@ -3,7 +3,7 @@
* 该文件定义了按年统计事件数量策略的具体实现。
*/
import {abstractDataStrategyRight} from "./abstractDataStrategyRight";
import { abstractDataStrategyRight } from "./abstractDataStrategyRight";
import excelSerialToJSDate from "../../../util/excelDateToJSDate";
import mapToObj from "../../../util/mapToObj";
......@@ -28,10 +28,13 @@ export class getEventCountByYearStrategy extends abstractDataStrategyRight {
/**
* 获取指定年份的事件数量统计。
* @param data - 从数据源提取的数据。
* @param year - 指定年份。
* @param year - 指定年份 ("thisyear" or "lastyear")
* @returns 事件数量统计的映射。
*/
private getEventCountForYear(data: any, year: number) {
private getEventCountForYear(data: any, year: string) {
const currentYear = new Date().getFullYear();
const targetYear = year === 'thisyear' ? currentYear : currentYear - 1;
// 定义事件列表
const eventList = ['事件总数', '历史遗留', '办结率'];
const eventCount = this.registerItems(eventList);
......@@ -46,19 +49,20 @@ export class getEventCountByYearStrategy extends abstractDataStrategyRight {
rowYear = 0;
console.log(e);
}
if (rowYear == year) {
eventCount.set('事件总数', eventCount.get('事件总数') + 1);
if (rowYear == targetYear) {
eventCount.set('事件总数', (eventCount.get('事件总数') || 0) + 1);
if (row['处置状态'] == '已办结') {
finishedEventCount++;
}
}
else if (rowYear == year - 1 && row['处置状态'] != '已办结') {
eventCount.set('历史遗留', eventCount.get('历史遗留') + 1);
} else if (rowYear == targetYear - 1 && row['处置状态'] != '已办结') {
eventCount.set('历史遗留', (eventCount.get('历史遗留') || 0) + 1);
}
});
// 计算办结率
eventCount.set('办结率', finishedEventCount / eventCount.get('事件总数'));
const totalEvents = eventCount.get('事件总数');
eventCount.set('办结率', totalEvents ? finishedEventCount / totalEvents : 0);
return eventCount;
}
}
\ No newline at end of file
}
......@@ -26,6 +26,10 @@ export function httpErrorHandler(err, req, res, next) {
res.success({success: false, msg: err.message, code: 506});
next();
}
else if (err.message == 'Year parameter must be either "thisyear" or "lastyear".') {
res.success({success: false, msg: err.message, code: 507});
next();
}
else {
res.success({success:false, msg: err.message, code: 500});
next();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment