1
This commit is contained in:
parent
aeb70460bb
commit
172e8c8235
@ -2,12 +2,13 @@
|
|||||||
|
|
||||||
- [x] 当用户充值达到5刀时,自动提升为vip分组;
|
- [x] 当用户充值达到5刀时,自动提升为vip分组;
|
||||||
- [x] 修改颜色
|
- [x] 修改颜色
|
||||||
- [x] 日志页面新增快速筛选日期、修复渠道ID查询、自动更新消耗额度、修改日志详情;
|
- [x] 日志页面新增快速筛选日期、修复渠道ID查询、自动更新消耗额度、修改日志详情(改为单价);
|
||||||
- [x] 用户管理界面,支持快速设置用户组,在`web\src\components\UsersTable.js`处修改相关值;
|
- [x] 用户管理界面,支持快速设置用户组,在`web\src\components\UsersTable.js`处修改相关值;
|
||||||
- [x] Key界面,删除无用的多种复制、聊天等按钮;
|
- [x] Key界面,删除无用的多种复制、聊天等按钮;
|
||||||
- [x] 删除系统访问Key;
|
- [x] 删除系统访问Key;
|
||||||
- [x] 在个人设置页面显示分组,使用信息等;
|
- [x] 在个人设置页面显示分组,使用信息等;
|
||||||
- [x] 前端全部以美金展示;
|
- [x] 前端全部以美金展示;
|
||||||
|
- [x] 渠道表,增加 本月已用、总已用、代理url、模型;
|
||||||
---
|
---
|
||||||
<p align="right">
|
<p align="right">
|
||||||
<strong>中文</strong> | <a href="./README.en.md">English</a> | <a href="./README.ja.md">日本語</a>
|
<strong>中文</strong> | <a href="./README.en.md">English</a> | <a href="./README.ja.md">日本語</a>
|
||||||
|
@ -72,15 +72,6 @@ func init() {
|
|||||||
Root: "dall-e-3",
|
Root: "dall-e-3",
|
||||||
Parent: nil,
|
Parent: nil,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Id: "dall-e-3",
|
|
||||||
Object: "model",
|
|
||||||
Created: 1677649963,
|
|
||||||
OwnedBy: "openai",
|
|
||||||
Permission: permission,
|
|
||||||
Root: "dall-e-3",
|
|
||||||
Parent: nil,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
Id: "whisper-1",
|
Id: "whisper-1",
|
||||||
Object: "model",
|
Object: "model",
|
||||||
|
@ -57,18 +57,61 @@ const ChannelsTable = () => {
|
|||||||
const [searching, setSearching] = useState(false);
|
const [searching, setSearching] = useState(false);
|
||||||
const [updatingBalance, setUpdatingBalance] = useState(false);
|
const [updatingBalance, setUpdatingBalance] = useState(false);
|
||||||
const [showPrompt, setShowPrompt] = useState(shouldShowPrompt("channel-test"));
|
const [showPrompt, setShowPrompt] = useState(shouldShowPrompt("channel-test"));
|
||||||
|
const [monthlyQuotas, setMonthlyQuotas] = useState({});
|
||||||
|
|
||||||
|
// 获取本月的开始和结束时间戳
|
||||||
|
function getMonthStartAndEndTimestamps() {
|
||||||
|
const now = new Date();
|
||||||
|
const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1);
|
||||||
|
const endOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0, 23, 59, 59, 999); // 设置到月末的最后一刻
|
||||||
|
|
||||||
|
// 将日期转换为UNIX时间戳(秒数)
|
||||||
|
const startTimestamp = Math.floor(startOfMonth.getTime() / 1000);
|
||||||
|
const endTimestamp = Math.floor(endOfMonth.getTime() / 1000);
|
||||||
|
|
||||||
|
return { startTimestamp, endTimestamp };
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取本月的配额
|
||||||
|
const fetchMonthlyQuotasAndChannels = async (fetchedChannels) => {
|
||||||
|
const { startTimestamp, endTimestamp } = getMonthStartAndEndTimestamps();
|
||||||
|
|
||||||
|
const quotaRequests = fetchedChannels.map(channel => (
|
||||||
|
API.get(`/api/log/stat?type=0&start_timestamp=${startTimestamp}&end_timestamp=${endTimestamp}&channel=${channel.id}`)
|
||||||
|
));
|
||||||
|
|
||||||
|
try {
|
||||||
|
const quotaResponses = await Promise.all(quotaRequests);
|
||||||
|
const quotaPerUnit = localStorage.getItem('quota_per_unit') || 500000;
|
||||||
|
const newMonthlyQuotas = quotaResponses.reduce((acc, response, index) => {
|
||||||
|
const quota = (response.data.data.quota / quotaPerUnit).toFixed(3);
|
||||||
|
const channelId = fetchedChannels[index].id;
|
||||||
|
acc[channelId] = parseFloat(quota);
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
setMonthlyQuotas(newMonthlyQuotas);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取月度配额失败:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 加载频道列表
|
||||||
const loadChannels = async (startIdx) => {
|
const loadChannels = async (startIdx) => {
|
||||||
const res = await API.get(`/api/channel/?p=${startIdx}`);
|
const res = await API.get(`/api/channel/?p=${startIdx}`);
|
||||||
const { success, message, data } = res.data;
|
const { success, message, data } = res.data;
|
||||||
if (success) {
|
if (success) {
|
||||||
|
const fetchedChannels = data;
|
||||||
|
|
||||||
if (startIdx === 0) {
|
if (startIdx === 0) {
|
||||||
setChannels(data);
|
setChannels(fetchedChannels);
|
||||||
} else {
|
} else {
|
||||||
let newChannels = [...channels];
|
let newChannels = [...channels];
|
||||||
newChannels.splice(startIdx * ITEMS_PER_PAGE, data.length, ...data);
|
newChannels.splice(startIdx * ITEMS_PER_PAGE, fetchedChannels.length, ...fetchedChannels);
|
||||||
setChannels(newChannels);
|
setChannels(newChannels);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fetchMonthlyQuotasAndChannels(fetchedChannels); // 在这里调用函数
|
||||||
} else {
|
} else {
|
||||||
showError(message);
|
showError(message);
|
||||||
}
|
}
|
||||||
@ -97,6 +140,9 @@ const ChannelsTable = () => {
|
|||||||
showError(reason);
|
showError(reason);
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const manageChannel = async (id, action, idx, value) => {
|
const manageChannel = async (id, action, idx, value) => {
|
||||||
let data = { id };
|
let data = { id };
|
||||||
@ -304,17 +350,22 @@ const ChannelsTable = () => {
|
|||||||
setLoading(false);
|
setLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Truncate string
|
||||||
function truncateString(str, num) {
|
function truncateString(str, num) {
|
||||||
if (str.length <= num) return str;
|
if (str.length <= num) return str;
|
||||||
return str.slice(0, num) + "...";
|
return str.slice(0, num) + "...";
|
||||||
}
|
}
|
||||||
|
// 总已用额度
|
||||||
function formatUsedQuota(usedQuota) {
|
function formatUsedQuota(usedQuota) {
|
||||||
const quotaPerUnit = localStorage.getItem('quota_per_unit') || 500000; // 如果未设置,则使用 1 作为默认值
|
const quotaPerUnit = localStorage.getItem('quota_per_unit') || 500000; // 如果未设置,则使用 1 作为默认值
|
||||||
return `$${(usedQuota / quotaPerUnit).toFixed(2)}`;
|
return `$${(usedQuota / quotaPerUnit).toFixed(3)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Form onSubmit={searchChannels}>
|
<Form onSubmit={searchChannels}>
|
||||||
@ -401,7 +452,7 @@ const ChannelsTable = () => {
|
|||||||
sortChannel('used_quota');
|
sortChannel('used_quota');
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
已用额度
|
本月已用额度
|
||||||
</Table.HeaderCell>
|
</Table.HeaderCell>
|
||||||
<Table.HeaderCell
|
<Table.HeaderCell
|
||||||
style={{ cursor: 'pointer' }}
|
style={{ cursor: 'pointer' }}
|
||||||
@ -462,7 +513,13 @@ const ChannelsTable = () => {
|
|||||||
basic
|
basic
|
||||||
/>
|
/>
|
||||||
</Table.Cell>
|
</Table.Cell>
|
||||||
<Table.Cell>{formatUsedQuota(channel.used_quota)}</Table.Cell>
|
<Table.Cell>
|
||||||
|
<Popup
|
||||||
|
trigger={<span>${monthlyQuotas[channel.id]}</span>}
|
||||||
|
content={`总: ${formatUsedQuota(channel.used_quota)}`}
|
||||||
|
basic
|
||||||
|
/>
|
||||||
|
</Table.Cell>
|
||||||
<Table.Cell>
|
<Table.Cell>
|
||||||
<Popup
|
<Popup
|
||||||
trigger={<span onClick={() => {
|
trigger={<span onClick={() => {
|
||||||
|
Loading…
Reference in New Issue
Block a user