diff --git a/common/constants.go b/common/constants.go
index 7895203f..722df3bc 100644
--- a/common/constants.go
+++ b/common/constants.go
@@ -91,7 +91,12 @@ const (
)
const (
- ChannelTypeUnknown = 0
- ChannelTypeOpenAI = 1
- ChannelTypeAPI2D = 2
+ ChannelTypeUnknown = 0
+ ChannelTypeOpenAI = 1
+ ChannelTypeAPI2D = 2
+ ChannelTypeAzure = 3
+ ChannelTypeCloseAI = 4
+ ChannelTypeOpenAISB = 5
+ ChannelTypeOpenAIMax = 6
+ ChannelTypeOhMyGPT = 7
)
diff --git a/controller/channel.go b/controller/channel.go
index 6dd81b56..d6bc98d4 100644
--- a/controller/channel.go
+++ b/controller/channel.go
@@ -82,6 +82,8 @@ func AddChannel(c *gin.Context) {
})
return
}
+ channel.CreatedTime = common.GetTimestamp()
+ channel.AccessedTime = common.GetTimestamp()
err = channel.Insert()
if err != nil {
c.JSON(http.StatusOK, gin.H{
@@ -136,6 +138,7 @@ func UpdateChannel(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "",
+ "data": channel,
})
return
}
diff --git a/model/channel.go b/model/channel.go
index 3b885adb..7c298ee2 100644
--- a/model/channel.go
+++ b/model/channel.go
@@ -9,7 +9,7 @@ type Channel struct {
Type int `json:"type" gorm:"default:0"`
Key string `json:"key"`
Status int `json:"status" gorm:"default:1"`
- Name string `json:"name" gorm:"unique;index"`
+ Name string `json:"name" gorm:"index"`
Weight int `json:"weight"`
CreatedTime int64 `json:"created_time" gorm:"bigint"`
AccessedTime int64 `json:"accessed_time" gorm:"bigint"`
diff --git a/web/src/components/ChannelsTable.js b/web/src/components/ChannelsTable.js
index 744e44ba..40181d3c 100644
--- a/web/src/components/ChannelsTable.js
+++ b/web/src/components/ChannelsTable.js
@@ -1,40 +1,48 @@
import React, { useEffect, useState } from 'react';
import { Button, Form, Label, Pagination, Table } from 'semantic-ui-react';
import { Link } from 'react-router-dom';
-import { API, showError, showSuccess } from '../helpers';
+import { API, copy, showError, showSuccess, timestamp2string } from '../helpers';
-import { ITEMS_PER_PAGE } from '../constants';
+import { CHANNEL_OPTIONS, ITEMS_PER_PAGE } from '../constants';
-function renderRole(role) {
- switch (role) {
- case 1:
- return ;
- case 10:
- return ;
- case 100:
- return ;
- default:
- return ;
+function renderTimestamp(timestamp) {
+ return (
+ <>
+ {timestamp2string(timestamp)}
+ >
+ );
+}
+
+let type2label = undefined;
+
+function renderType(type) {
+ if (!type2label) {
+ type2label = new Map;
+ for (let i = 0; i < CHANNEL_OPTIONS.length; i++) {
+ type2label[CHANNEL_OPTIONS[i].value] = CHANNEL_OPTIONS[i];
+ }
+ type2label[0] = { value: 0, text: '未知类型', color: 'grey' };
}
+ return ;
}
const ChannelsTable = () => {
- const [users, setUsers] = useState([]);
+ const [channels, setChannels] = useState([]);
const [loading, setLoading] = useState(true);
const [activePage, setActivePage] = useState(1);
const [searchKeyword, setSearchKeyword] = useState('');
const [searching, setSearching] = useState(false);
- const loadUsers = async (startIdx) => {
- const res = await API.get(`/api/user/?p=${startIdx}`);
+ const loadChannels = async (startIdx) => {
+ const res = await API.get(`/api/channel/?p=${startIdx}`);
const { success, message, data } = res.data;
if (success) {
if (startIdx === 0) {
- setUsers(data);
+ setChannels(data);
} else {
- let newUsers = users;
- newUsers.push(...data);
- setUsers(newUsers);
+ let newChannels = channels;
+ newChannels.push(...data);
+ setChannels(newChannels);
}
} else {
showError(message);
@@ -44,55 +52,63 @@ const ChannelsTable = () => {
const onPaginationChange = (e, { activePage }) => {
(async () => {
- if (activePage === Math.ceil(users.length / ITEMS_PER_PAGE) + 1) {
+ if (activePage === Math.ceil(channels.length / ITEMS_PER_PAGE) + 1) {
// In this case we have to load more data and then append them.
- await loadUsers(activePage - 1);
+ await loadChannels(activePage - 1);
}
setActivePage(activePage);
})();
};
useEffect(() => {
- loadUsers(0)
+ loadChannels(0)
.then()
.catch((reason) => {
showError(reason);
});
}, []);
- const manageUser = (username, action, idx) => {
- (async () => {
- const res = await API.post('/api/user/manage', {
- username,
- action,
- });
- const { success, message } = res.data;
- if (success) {
- showSuccess('操作成功完成!');
- let user = res.data.data;
- let newUsers = [...users];
- let realIdx = (activePage - 1) * ITEMS_PER_PAGE + idx;
- if (action === 'delete') {
- newUsers[realIdx].deleted = true;
- } else {
- newUsers[realIdx].status = user.status;
- newUsers[realIdx].role = user.role;
- }
- setUsers(newUsers);
+ const manageChannel = async (id, action, idx) => {
+ let data = { id };
+ let res;
+ switch (action) {
+ case 'delete':
+ res = await API.delete(`/api/channel/${id}/`);
+ break;
+ case 'enable':
+ data.status = 1;
+ res = await API.put('/api/channel/', data);
+ break;
+ case 'disable':
+ data.status = 2;
+ res = await API.put('/api/channel/', data);
+ break;
+ }
+ const { success, message } = res.data;
+ if (success) {
+ showSuccess('操作成功完成!');
+ let channel = res.data.data;
+ let newChannels = [...channels];
+ let realIdx = (activePage - 1) * ITEMS_PER_PAGE + idx;
+ if (action === 'delete') {
+ newChannels[realIdx].deleted = true;
} else {
- showError(message);
+ newChannels[realIdx].status = channel.status;
}
- })();
+ setChannels(newChannels);
+ } else {
+ showError(message);
+ }
};
const renderStatus = (status) => {
switch (status) {
case 1:
- return ;
+ return ;
case 2:
return (
);
default:
@@ -104,18 +120,18 @@ const ChannelsTable = () => {
}
};
- const searchUsers = async () => {
+ const searchChannels = async () => {
if (searchKeyword === '') {
// if keyword is blank, load files instead.
- await loadUsers(0);
+ await loadChannels(0);
setActivePage(1);
return;
}
setSearching(true);
- const res = await API.get(`/api/user/search?keyword=${searchKeyword}`);
+ const res = await API.get(`/api/channel/search?keyword=${searchKeyword}`);
const { success, message, data } = res.data;
if (success) {
- setUsers(data);
+ setChannels(data);
setActivePage(1);
} else {
showError(message);
@@ -127,28 +143,28 @@ const ChannelsTable = () => {
setSearchKeyword(value.trim());
};
- const sortUser = (key) => {
- if (users.length === 0) return;
+ const sortChannel = (key) => {
+ if (channels.length === 0) return;
setLoading(true);
- let sortedUsers = [...users];
- sortedUsers.sort((a, b) => {
+ let sortedChannels = [...channels];
+ sortedChannels.sort((a, b) => {
return ('' + a[key]).localeCompare(b[key]);
});
- if (sortedUsers[0].id === users[0].id) {
- sortedUsers.reverse();
+ if (sortedChannels[0].id === channels[0].id) {
+ sortedChannels.reverse();
}
- setUsers(sortedUsers);
+ setChannels(sortedChannels);
setLoading(false);
};
return (
<>
-
{
{
- sortUser('username');
+ sortChannel('id');
}}
>
- 用户名
+ ID
{
- sortUser('display_name');
+ sortChannel('name');
}}
>
- 显示名称
+ 名称
{
- sortUser('email');
+ sortChannel('type');
}}
>
- 邮箱地址
+ 类型
{
- sortUser('role');
- }}
- >
- 用户角色
-
- {
- sortUser('status');
+ sortChannel('status');
}}
>
状态
+ {
+ sortChannel('created_time');
+ }}
+ >
+ 创建时间
+
+ {
+ sortChannel('accessed_time');
+ }}
+ >
+ 访问时间
+
操作
- {users
+ {channels
.slice(
(activePage - 1) * ITEMS_PER_PAGE,
activePage * ITEMS_PER_PAGE
)
- .map((user, idx) => {
- if (user.deleted) return <>>;
+ .map((channel, idx) => {
+ if (channel.deleted) return <>>;
return (
-
- {user.username}
- {user.display_name}
- {user.email ? user.email : '无'}
- {renderRole(user.role)}
- {renderStatus(user.status)}
+
+ {channel.id}
+ {channel.name ? channel.name : '无'}
+ {renderType(channel.type)}
+ {renderStatus(channel.status)}
+ {renderTimestamp(channel.created_time)}
+ {renderTimestamp(channel.accessed_time)}
-
-