ChatGPT-Next-Web/app/api/admin/charts/route.ts
sijinhui 0b713200fd 123
2024-04-26 22:52:35 +08:00

120 lines
3.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { NextRequest, NextResponse } from "next/server";
import prisma from "@/lib/prisma";
import { addHours, subMinutes } from "date-fns";
import { EChartsOption } from "echarts";
import { getCurStartEnd } from "@/app/utils/custom";
interface StringKeyedObject {
[key: string]: { [key: string]: number };
}
type StringSet = Set<string>;
type StringArray = string[];
function HandleLogData(
todayLog: [{ userName: string; logToken: number; model: string }],
) {
// 先遍历一遍,获取所有的模型和名字。
let all_models: StringSet = new Set();
let all_names: StringSet = new Set();
// 拼接数据结构
let data_by_name: StringKeyedObject = {};
todayLog.map((log) => {
all_models.add(log.model);
all_names.add(log.userName);
data_by_name[log.userName] = data_by_name[log.userName] ?? {};
data_by_name[log.userName][log.model] =
(data_by_name[log.userName][log.model] || 0) + log.logToken;
// 这么顺利,顺便加个总数吧。
data_by_name[log.userName]["all_token"] =
(data_by_name[log.userName]["all_token"] || 0) + log.logToken;
});
//
// 然后遍历并以all_token排序。
const userNameList: StringArray = Array.from(all_names).sort((a, b) => {
return data_by_name[a]["all_token"] - data_by_name[b]["all_token"];
});
// 将值按模型分为两个序列
const modelNameList = Array.from(all_models).map((model) => {
return {
name: model,
data: userNameList.map((userName) => {
return data_by_name[userName][model] ?? null;
}),
};
});
return {
modelNameList,
userNameList,
data_by_name,
};
}
async function handle(req: NextRequest) {
const { searchParams } = new URL(req.url);
const { startOfTheDayInTimeZone, endOfTheDayInTimeZone } = getCurStartEnd();
const todayLog = await prisma.logEntry.findMany({
where: {
createdAt: {
gte: startOfTheDayInTimeZone.toISOString(), // gte 表示 '大于等于'
lte: endOfTheDayInTimeZone.toISOString(), // lte 表示 '小于等于'
},
},
include: {
user: true,
},
});
// @ts-ignore
const log_data = HandleLogData(todayLog);
// console.log('log_data', log_data)
const usageByModelOption: EChartsOption = {
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow",
},
},
title: {
show: true,
text: "token使用分析",
},
legend: {},
grid: {
left: "3%",
right: "4%",
bottom: "3%",
containLabel: true,
},
xAxis: [
{
type: "value",
},
],
yAxis: [
{
type: "category",
data: log_data.userNameList,
},
],
series: log_data.modelNameList.map((item) => {
return {
...item,
type: "bar",
emphasis: {
focus: "series",
},
label: {
show: true,
position: "right",
},
colorBy: "series",
stack: "model",
};
}),
};
return NextResponse.json(usageByModelOption);
}
export const GET = handle;
// export const POST = handle;