mirror of
https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web.git
synced 2025-10-01 23:56:39 +08:00
修复管理员界面相关问题,优化页面显示
This commit is contained in:
parent
d5e92a7b06
commit
067ccb481b
@ -6,6 +6,7 @@ import { insertUser } from "@/lib/auth";
|
||||
// import cl100k_base from "tiktoken/encoders/cl100k_base.json"
|
||||
import "tiktoken";
|
||||
import { get_encoding } from "tiktoken";
|
||||
import { addHours, subMinutes } from "date-fns";
|
||||
|
||||
function getTokenLength(input: string): number {
|
||||
// const { Tiktoken } = require("tiktoken/lite");
|
||||
@ -45,6 +46,10 @@ async function handle(
|
||||
console.log("[LOG]", "logToken", e);
|
||||
request_data.logToken = 0;
|
||||
}
|
||||
// 默认时间不准,还是手动获取一下吧。
|
||||
// 转换时区太麻烦,我还是直接减去时差
|
||||
// const current_time = new Date();
|
||||
// request_data.createdAt = subMinutes(current_time, current_time.getTimezoneOffset())
|
||||
|
||||
await prisma.logEntry.create({
|
||||
data: request_data,
|
||||
|
@ -2,7 +2,9 @@ import * as echarts from "echarts";
|
||||
import { EChartsOption } from "echarts";
|
||||
import dynamic from "next/dynamic";
|
||||
import prisma from "@/lib/prisma";
|
||||
import { addHours } from "date-fns";
|
||||
import { addHours, subMinutes } from "date-fns";
|
||||
import { log } from "util";
|
||||
import { use } from "react";
|
||||
|
||||
// import { getTokenLength } from "@/app/utils/token";
|
||||
|
||||
@ -10,53 +12,60 @@ const UsageByModelChart = dynamic(() => import("./usage-by-model-chart"), {
|
||||
ssr: false,
|
||||
});
|
||||
|
||||
function HandleLogData(
|
||||
todayLog: [{ userName: string; logEntry: string; logToken: number }],
|
||||
) {
|
||||
const data1 = todayLog.map((log) => {
|
||||
return {
|
||||
name: log.userName ?? "unknown",
|
||||
value: log.logToken,
|
||||
};
|
||||
});
|
||||
|
||||
type Accumulator = {
|
||||
[key: string]: number;
|
||||
};
|
||||
const data2 = data1.reduce<Accumulator>((acc, item) => {
|
||||
if (acc[item.name]) {
|
||||
acc[item.name] += item.value;
|
||||
} else {
|
||||
acc[item.name] = item.value;
|
||||
interface StringKeyedObject {
|
||||
[key: string]: { [key: string]: number };
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
const data3 = Object.entries(data2)
|
||||
.map(([name, value]) => ({
|
||||
name,
|
||||
value,
|
||||
}))
|
||||
.sort((a, b) => {
|
||||
return a.value - b.value;
|
||||
});
|
||||
// interface StringArray {
|
||||
// strings: string[];
|
||||
// }
|
||||
|
||||
const data4 = data3.reduce(
|
||||
(acc, cur) => {
|
||||
// @ts-ignore
|
||||
acc.name.push(cur.name);
|
||||
// @ts-ignore
|
||||
acc.value.push(cur.value);
|
||||
return acc;
|
||||
},
|
||||
{ name: [], value: [] },
|
||||
);
|
||||
return data4;
|
||||
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;
|
||||
}),
|
||||
};
|
||||
});
|
||||
console.log("看看", modelNameList);
|
||||
return {
|
||||
modelNameList,
|
||||
userNameList,
|
||||
data_by_name,
|
||||
};
|
||||
}
|
||||
|
||||
export default async function UsageByModel() {
|
||||
// 今天日期的开始和结束
|
||||
var today = new Date();
|
||||
today = addHours(today, +8);
|
||||
// today = subMinutes(today, today.getTimezoneOffset())
|
||||
const startOfTheDayInTimeZone = new Date(
|
||||
today.getFullYear(),
|
||||
today.getMonth(),
|
||||
@ -65,19 +74,7 @@ export default async function UsageByModel() {
|
||||
0,
|
||||
0,
|
||||
);
|
||||
// const endOfTheDayInTimeZone = new Date(
|
||||
// today.getFullYear(),
|
||||
// today.getMonth(),
|
||||
// today.getDate(),
|
||||
// 23,
|
||||
// 59,
|
||||
// 59,
|
||||
// ); // 当天的结束时间
|
||||
const endOfTheDayInTimeZone = addHours(startOfTheDayInTimeZone, +24); // 当天的结束时间
|
||||
|
||||
// const startDate = addHours(startOfTheDayInTimeZone, -8);
|
||||
// const endDate = addHours(endOfTheDayInTimeZone, -8);
|
||||
console.log("===", today, startOfTheDayInTimeZone, endOfTheDayInTimeZone);
|
||||
const todayLog = await prisma.logEntry.findMany({
|
||||
where: {
|
||||
createdAt: {
|
||||
@ -89,13 +86,9 @@ export default async function UsageByModel() {
|
||||
user: true,
|
||||
},
|
||||
});
|
||||
|
||||
// console.log("========", todayLog[todayLog.length - 1]);
|
||||
// @ts-ignore
|
||||
const log_data = HandleLogData(todayLog);
|
||||
|
||||
console.log("[log_data]====---==", todayLog);
|
||||
|
||||
const usageByModelOption: EChartsOption = {
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
@ -122,12 +115,12 @@ export default async function UsageByModel() {
|
||||
yAxis: [
|
||||
{
|
||||
type: "category",
|
||||
data: log_data.name,
|
||||
data: log_data.userNameList,
|
||||
},
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: "总量",
|
||||
series: log_data.modelNameList.map((item) => {
|
||||
return {
|
||||
...item,
|
||||
type: "bar",
|
||||
emphasis: {
|
||||
focus: "series",
|
||||
@ -136,12 +129,28 @@ export default async function UsageByModel() {
|
||||
show: true,
|
||||
position: "right",
|
||||
},
|
||||
colorBy: "data",
|
||||
// progress: {
|
||||
// show: true
|
||||
colorBy: "series",
|
||||
stack: "model",
|
||||
};
|
||||
}),
|
||||
|
||||
// [
|
||||
// {
|
||||
// name: "总量",
|
||||
// type: "bar",
|
||||
// emphasis: {
|
||||
// focus: "series",
|
||||
// },
|
||||
// label: {
|
||||
// show: true,
|
||||
// position: "right",
|
||||
// },
|
||||
// colorBy: "data",
|
||||
// // progress: {
|
||||
// // show: true
|
||||
// // },
|
||||
// data: log_data.value,
|
||||
// },
|
||||
data: log_data.value,
|
||||
},
|
||||
// {
|
||||
// name: 'Email',
|
||||
// type: 'bar',
|
||||
@ -220,7 +229,7 @@ export default async function UsageByModel() {
|
||||
// },
|
||||
// data: [62, 82, 91, 84, 109, 110, 120]
|
||||
// }
|
||||
],
|
||||
// ],
|
||||
};
|
||||
return (
|
||||
<>
|
||||
|
@ -252,7 +252,7 @@ function isPinYin(input: string): boolean {
|
||||
|
||||
export function isName(input: string): boolean {
|
||||
const denyList = [
|
||||
"suibian",
|
||||
"suibian", "某某", "张三", "李四"
|
||||
]
|
||||
if (denyList.includes(input)) {
|
||||
return false;
|
||||
|
Loading…
Reference in New Issue
Block a user