diff --git a/controller/usedata.go b/controller/usedata.go
index fc0a326..b936532 100644
--- a/controller/usedata.go
+++ b/controller/usedata.go
@@ -4,10 +4,33 @@ import (
"github.com/gin-gonic/gin"
"net/http"
"one-api/model"
+ "strconv"
)
func GetAllQuotaDates(c *gin.Context) {
- dates, err := model.GetAllQuotaDates()
+ startTimestamp, _ := strconv.ParseInt(c.Query("start_timestamp"), 10, 64)
+ endTimestamp, _ := strconv.ParseInt(c.Query("end_timestamp"), 10, 64)
+ dates, err := model.GetAllQuotaDates(startTimestamp, endTimestamp)
+ if err != nil {
+ c.JSON(http.StatusOK, gin.H{
+ "success": false,
+ "message": err.Error(),
+ })
+ return
+ }
+ c.JSON(http.StatusOK, gin.H{
+ "success": true,
+ "message": "",
+ "data": dates,
+ })
+ return
+}
+
+func GetUserQuotaDates(c *gin.Context) {
+ userId := c.GetInt("id")
+ startTimestamp, _ := strconv.ParseInt(c.Query("start_timestamp"), 10, 64)
+ endTimestamp, _ := strconv.ParseInt(c.Query("end_timestamp"), 10, 64)
+ dates, err := model.GetQuotaDataByUserId(userId, startTimestamp, endTimestamp)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
diff --git a/model/usedata.go b/model/usedata.go
index ce3c86c..e00c3ce 100644
--- a/model/usedata.go
+++ b/model/usedata.go
@@ -74,16 +74,23 @@ func SaveQuotaDataCache() {
CacheQuotaData = make(map[string]*QuotaData)
}
-func GetQuotaDataByUsername(username string) (quotaData []*QuotaData, err error) {
+func GetQuotaDataByUsername(username string, startTime int64, endTime int64) (quotaData []*QuotaData, err error) {
var quotaDatas []*QuotaData
// 从quota_data表中查询数据
err = DB.Table("quota_data").Where("username = ?", username).Find("aDatas).Error
return quotaDatas, err
}
-func GetAllQuotaDates() (quotaData []*QuotaData, err error) {
+func GetQuotaDataByUserId(userId int, startTime int64, endTime int64) (quotaData []*QuotaData, err error) {
var quotaDatas []*QuotaData
// 从quota_data表中查询数据
- err = DB.Table("quota_data").Find("aDatas).Error
+ err = DB.Table("quota_data").Where("user_id = ? and created_at >= ? and created_at <= ?", userId, startTime, endTime).Find("aDatas).Error
+ return quotaDatas, err
+}
+
+func GetAllQuotaDates(startTime int64, endTime int64) (quotaData []*QuotaData, err error) {
+ var quotaDatas []*QuotaData
+ // 从quota_data表中查询数据
+ err = DB.Table("quota_data").Where("created_at >= ? and created_at <= ?", startTime, endTime).Find("aDatas).Error
return quotaDatas, err
}
diff --git a/router/api-router.go b/router/api-router.go
index f39a5af..3c3b999 100644
--- a/router/api-router.go
+++ b/router/api-router.go
@@ -116,6 +116,7 @@ func SetApiRouter(router *gin.Engine) {
dataRoute := apiRouter.Group("/data")
dataRoute.GET("/", middleware.AdminAuth(), controller.GetAllQuotaDates)
+ dataRoute.GET("/self", middleware.UserAuth(), controller.GetUserQuotaDates)
logRoute.Use(middleware.CORS())
{
diff --git a/web/src/components/LogsTable.js b/web/src/components/LogsTable.js
index 8556493..347a681 100644
--- a/web/src/components/LogsTable.js
+++ b/web/src/components/LogsTable.js
@@ -422,7 +422,6 @@ const LogsTable = () => {
value={end_timestamp} type='dateTime'
name='end_timestamp'
onChange={value => handleInputChange(value, 'end_timestamp')}/>
- {/*
查询*/}
{
isAdminUser && <>
{
@@ -19,8 +18,9 @@ const Detail = (props) => {
});
const {username, token_name, model_name, start_timestamp, end_timestamp, channel} = inputs;
const isAdminUser = isAdmin();
- let modelDataChart = null;
- let modelDataPieChart = null;
+ const initialized = useRef(false)
+ const [modelDataChart, setModelDataChart] = useState(null);
+ const [modelDataPieChart, setModelDataPieChart] = useState(null);
const [loading, setLoading] = useState(true);
const [quotaData, setQuotaData] = useState([]);
const [quotaDataPie, setQuotaDataPie] = useState([]);
@@ -116,22 +116,22 @@ const Detail = (props) => {
}
};
- const loadQuotaData = async () => {
+ const loadQuotaData = async (lineChart, pieChart) => {
setLoading(true);
let url = '';
let localStartTimestamp = Date.parse(start_timestamp) / 1000;
let localEndTimestamp = Date.parse(end_timestamp) / 1000;
if (isAdminUser) {
- url = `/api/data`;
+ url = `/api/data/?username=${username}&start_timestamp=${localStartTimestamp}&end_timestamp=${localEndTimestamp}`;
} else {
- url = `/api/data/self`;
+ url = `/api/data/self/?start_timestamp=${localStartTimestamp}&end_timestamp=${localEndTimestamp}`;
}
const res = await API.get(url);
const {success, message, data} = res.data;
if (success) {
setQuotaData(data);
- updateChart(data);
+ updateChart(lineChart, pieChart, data);
} else {
showError(message);
}
@@ -139,74 +139,73 @@ const Detail = (props) => {
};
const refresh = async () => {
- await loadQuotaData();
+ await loadQuotaData(modelDataChart, modelDataPieChart);
};
- const updateChart = (data) => {
- if (isAdminUser) {
- // 将所有用户的数据累加
- let pieData = [];
- let lineData = [];
- for (let i = 0; i < data.length; i++) {
- const item = data[i];
- const {count, id, model_name, quota, user_id, username} = item;
- // 合并model_name
- let pieItem = pieData.find(item => item.model_name === model_name);
- if (pieItem) {
- pieItem.count += count;
- } else {
- pieData.push({
- "type": model_name,
- "value": count
- });
- }
- // 合并created_at和model_name 为 lineData, created_at 数据类型是小时的时间戳
- // 转换日期格式
- let createTime = timestamp2string1(item.created_at);
- let lineItem = lineData.find(item => item.Time === item.createTime && item.Model === model_name);
- if (lineItem) {
- lineItem.Usage += getQuotaWithUnit(quota);
- } else {
- lineData.push({
- "Time": createTime,
- "Model": model_name,
- "Usage": getQuotaWithUnit(quota)
- });
- }
-
- }
- // sort by count
- pieData.sort((a, b) => b.value - a.value);
- spec_line.data[0].values = lineData;
- spec_pie.data[0].values = pieData;
- // console.log('spec_line', spec_line);
- console.log('spec_pie', spec_pie);
- // modelDataChart.renderAsync();
- modelDataPieChart.updateSpec(spec_pie);
- modelDataChart.updateSpec(spec_line);
+ const initChart = async () => {
+ let lineChart = modelDataChart
+ if (!modelDataChart) {
+ lineChart = new VChart(spec_line, {dom: 'model_data'});
+ setModelDataChart(lineChart);
+ await lineChart.renderAsync();
}
+ let pieChart = modelDataPieChart
+ if (!modelDataPieChart) {
+ pieChart = new VChart(spec_pie, {dom: 'model_pie'});
+ setModelDataPieChart(pieChart);
+ await pieChart.renderAsync();
+ }
+ console.log('init vchart');
+ await loadQuotaData(lineChart, pieChart)
}
- useEffect(() => {
- refresh();
- }, []);
+ const updateChart = (lineChart, pieChart, data) => {
+ if (isAdminUser) {
+ // 将所有用户合并
+ }
+ let pieData = [];
+ let lineData = [];
+ for (let i = 0; i < data.length; i++) {
+ const item = data[i];
+ const {count, id, model_name, quota, user_id, username} = item;
+ // 合并model_name
+ let pieItem = pieData.find(item => item.type === model_name);
+ if (pieItem) {
+ pieItem.count += count;
+ } else {
+ pieData.push({
+ "type": model_name,
+ "value": count
+ });
+ }
+ // 合并created_at和model_name 为 lineData, created_at 数据类型是小时的时间戳
+ // 转换日期格式
+ let createTime = timestamp2string1(item.created_at);
+ let lineItem = lineData.find(item => item.Time === item.createTime && item.Model === model_name);
+ if (lineItem) {
+ lineItem.Usage += getQuotaWithUnit(quota);
+ } else {
+ lineData.push({
+ "Time": createTime,
+ "Model": model_name,
+ "Usage": getQuotaWithUnit(quota)
+ });
+ }
+
+ }
+ // sort by count
+ pieData.sort((a, b) => b.value - a.value);
+ pieChart.updateData('id0', pieData);
+ lineChart.updateData('barData', lineData);
+
+ }
useEffectOnce(() => {
- // 创建 vchart 实例
- if (!modelDataChart) {
- modelDataChart = new VChart(spec_line, {dom: 'model_data'});
- // 绘制
- modelDataChart.renderAsync();
+ if (!initialized.current) {
+ initialized.current = true;
+ initChart();
}
-
- if (!modelDataPieChart) {
- modelDataPieChart = new VChart(spec_pie, {dom: 'model_pie'});
- // 绘制
- modelDataPieChart.renderAsync();
- }
-
- console.log('render vchart');
- })
+ });
return (
<>
@@ -227,7 +226,6 @@ const Detail = (props) => {
value={end_timestamp} type='dateTime'
name='end_timestamp'
onChange={value => handleInputChange(value, 'end_timestamp')}/>
- {/*查询*/}
{/*{*/}
{/* isAdminUser && <>*/}
{/* {
{/* onChange={value => handleInputChange(value, 'username')}/>*/}
{/* >*/}
{/*}*/}
- {/**/}
- {/* */}
- {/**/}
+
+
+
>