操作日志中文化与功能优化
- 后端操作描述统一使用中文冒号(:)替换英文冒号(:) - 前端资源名称列 ID 显示改为中文冒号 - 清理日志改为弹窗内独立日期选择器,不再依赖筛选条件 - 侧边栏操作记录移至渠道管理上方 - RPM/TPM 卡片标签改为中文显示
This commit is contained in:
parent
006e723ac5
commit
01900f1a3a
|
|
@ -1348,7 +1348,7 @@ func AddChannel(c *gin.Context) {
|
|||
if addChannelRequest.Channel != nil {
|
||||
channelName = addChannelRequest.Channel.Name
|
||||
}
|
||||
service.RecordCreateOperation(c, "channel", 0, channelName, "创建渠道: "+channelName, "")
|
||||
service.RecordCreateOperation(c, "channel", 0, channelName, "创建渠道:"+channelName, "")
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "",
|
||||
|
|
@ -1366,7 +1366,7 @@ func DeleteChannel(c *gin.Context) {
|
|||
}
|
||||
model.InitChannelCache()
|
||||
// 记录操作日志
|
||||
service.RecordDeleteOperation(c, "channel", id, "", fmt.Sprintf("删除渠道 (ID: %d)", id), "")
|
||||
service.RecordDeleteOperation(c, "channel", id, "", fmt.Sprintf("删除渠道 (ID:%d)", id), "")
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "",
|
||||
|
|
@ -1721,7 +1721,7 @@ func UpdateChannel(c *gin.Context) {
|
|||
channel.Key = ""
|
||||
clearChannelInfo(&channel.Channel)
|
||||
// 记录操作日志
|
||||
service.RecordUpdateOperation(c, "channel", channel.Id, channel.Name, "更新渠道: "+channel.Name, "")
|
||||
service.RecordUpdateOperation(c, "channel", channel.Id, channel.Name, "更新渠道:"+channel.Name, "")
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "",
|
||||
|
|
|
|||
|
|
@ -270,7 +270,7 @@ func CreateModelMeta(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
model.RefreshPricing()
|
||||
service.RecordCreateOperation(c, "model", m.Id, m.ModelName, "创建模型: "+m.ModelName, "")
|
||||
service.RecordCreateOperation(c, "model", m.Id, m.ModelName, "创建模型:"+m.ModelName, "")
|
||||
common.ApiSuccess(c, &m)
|
||||
}
|
||||
|
||||
|
|
@ -319,7 +319,7 @@ func UpdateModelMeta(c *gin.Context) {
|
|||
}
|
||||
}
|
||||
model.RefreshPricing()
|
||||
service.RecordUpdateOperation(c, "model", m.Id, m.ModelName, "更新模型: "+m.ModelName, "")
|
||||
service.RecordUpdateOperation(c, "model", m.Id, m.ModelName, "更新模型:"+m.ModelName, "")
|
||||
common.ApiSuccess(c, &m)
|
||||
}
|
||||
|
||||
|
|
@ -336,7 +336,7 @@ func DeleteModelMeta(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
model.RefreshPricing()
|
||||
service.RecordDeleteOperation(c, "model", id, "", fmt.Sprintf("删除模型 (ID: %d)", id), "")
|
||||
service.RecordDeleteOperation(c, "model", id, "", fmt.Sprintf("删除模型 (ID:%d)", id), "")
|
||||
common.ApiSuccess(c, nil)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -690,10 +690,10 @@ func UpdateOption(c *gin.Context) {
|
|||
if modelPricingOptionKeys[option.Key] {
|
||||
changes := computeModelPricingDiff(oldVal, valStr)
|
||||
if len(changes) > 0 {
|
||||
service.RecordUpdateWithDiff(c, "setting", 0, option.Key, "更新系统设置: "+option.Key, changes, "")
|
||||
service.RecordUpdateWithDiff(c, "setting", 0, option.Key, "更新系统设置:"+option.Key, changes, "")
|
||||
}
|
||||
} else {
|
||||
service.RecordUpdateOperation(c, "setting", 0, option.Key, "更新系统设置: "+option.Key, "")
|
||||
service.RecordUpdateOperation(c, "setting", 0, option.Key, "更新系统设置:"+option.Key, "")
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ func AddRedemption(c *gin.Context) {
|
|||
}
|
||||
keys = append(keys, key)
|
||||
}
|
||||
service.RecordCreateOperation(c, "redemption", 0, redemption.Name, "创建兑换码: "+redemption.Name, "")
|
||||
service.RecordCreateOperation(c, "redemption", 0, redemption.Name, "创建兑换码:"+redemption.Name, "")
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "",
|
||||
|
|
@ -122,7 +122,7 @@ func DeleteRedemption(c *gin.Context) {
|
|||
common.ApiError(c, err)
|
||||
return
|
||||
}
|
||||
service.RecordDeleteOperation(c, "redemption", id, "", fmt.Sprintf("删除兑换码 (ID: %d)", id), "")
|
||||
service.RecordDeleteOperation(c, "redemption", id, "", fmt.Sprintf("删除兑换码 (ID:%d)", id), "")
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "",
|
||||
|
|
@ -161,7 +161,7 @@ func UpdateRedemption(c *gin.Context) {
|
|||
common.ApiError(c, err)
|
||||
return
|
||||
}
|
||||
service.RecordUpdateOperation(c, "redemption", cleanRedemption.Id, cleanRedemption.Name, "更新兑换码: "+cleanRedemption.Name, "")
|
||||
service.RecordUpdateOperation(c, "redemption", cleanRedemption.Id, cleanRedemption.Name, "更新兑换码:"+cleanRedemption.Name, "")
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "",
|
||||
|
|
|
|||
|
|
@ -228,7 +228,7 @@ func AddToken(c *gin.Context) {
|
|||
common.ApiError(c, err)
|
||||
return
|
||||
}
|
||||
service.RecordCreateOperation(c, "token", cleanToken.Id, cleanToken.Name, "创建令牌: "+cleanToken.Name, "")
|
||||
service.RecordCreateOperation(c, "token", cleanToken.Id, cleanToken.Name, "创建令牌:"+cleanToken.Name, "")
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "",
|
||||
|
|
@ -243,7 +243,7 @@ func DeleteToken(c *gin.Context) {
|
|||
common.ApiError(c, err)
|
||||
return
|
||||
}
|
||||
service.RecordDeleteOperation(c, "token", id, "", fmt.Sprintf("删除令牌 (ID: %d)", id), "")
|
||||
service.RecordDeleteOperation(c, "token", id, "", fmt.Sprintf("删除令牌 (ID:%d)", id), "")
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "",
|
||||
|
|
@ -308,7 +308,7 @@ func UpdateToken(c *gin.Context) {
|
|||
common.ApiError(c, err)
|
||||
return
|
||||
}
|
||||
service.RecordUpdateOperation(c, "token", cleanToken.Id, cleanToken.Name, "更新令牌: "+cleanToken.Name, "")
|
||||
service.RecordUpdateOperation(c, "token", cleanToken.Id, cleanToken.Name, "更新令牌:"+cleanToken.Name, "")
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "",
|
||||
|
|
|
|||
|
|
@ -1206,7 +1206,7 @@ func UpdateUser(c *gin.Context) {
|
|||
if originUser.DistributorCommissionBps != updatedUser.DistributorCommissionBps {
|
||||
changes = append(changes, service.FieldChange{Field: "分销佣金比例", OldValue: fmt.Sprintf("%d‱", originUser.DistributorCommissionBps), NewValue: fmt.Sprintf("%d‱", updatedUser.DistributorCommissionBps)})
|
||||
}
|
||||
service.RecordUpdateWithDiff(c, "user", updatedUser.Id, updatedUser.Username, "更新用户: "+updatedUser.Username, changes, "")
|
||||
service.RecordUpdateWithDiff(c, "user", updatedUser.Id, updatedUser.Username, "更新用户:"+updatedUser.Username, changes, "")
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
|
|
@ -1246,7 +1246,7 @@ func AdminClearUserBinding(c *gin.Context) {
|
|||
}
|
||||
|
||||
model.RecordLog(user.Id, model.LogTypeManage, fmt.Sprintf("admin cleared %s binding for user %s", bindingType, user.Username))
|
||||
service.RecordDeleteOperation(c, "user_binding", user.Id, user.Username, "清除用户绑定["+bindingType+"]: "+user.Username, "")
|
||||
service.RecordDeleteOperation(c, "user_binding", user.Id, user.Username, "清除用户绑定["+bindingType+"]:"+user.Username, "")
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
|
|
@ -1421,7 +1421,7 @@ func DeleteUser(c *gin.Context) {
|
|||
})
|
||||
return
|
||||
}
|
||||
service.RecordDeleteOperation(c, "user", id, originUser.Username, "删除用户: "+originUser.Username, "")
|
||||
service.RecordDeleteOperation(c, "user", id, originUser.Username, "删除用户:"+originUser.Username, "")
|
||||
}
|
||||
|
||||
func DeleteSelf(c *gin.Context) {
|
||||
|
|
@ -1501,7 +1501,7 @@ func CreateUser(c *gin.Context) {
|
|||
common.ApiError(c, err)
|
||||
return
|
||||
}
|
||||
service.RecordCreateOperation(c, "user", cleanUser.Id, cleanUser.Username, "创建用户: "+cleanUser.Username, "")
|
||||
service.RecordCreateOperation(c, "user", cleanUser.Id, cleanUser.Username, "创建用户:"+cleanUser.Username, "")
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
|
|
@ -1781,7 +1781,7 @@ func ManageUser(c *gin.Context) {
|
|||
}
|
||||
changes = append(changes, service.FieldChange{Field: "学员", OldValue: oldLabel, NewValue: newLabel})
|
||||
}
|
||||
service.RecordUpdateWithDiff(c, "user", user.Id, user.Username, label+": "+user.Username, changes, "")
|
||||
service.RecordUpdateWithDiff(c, "user", user.Id, user.Username, label+":"+user.Username, changes, "")
|
||||
}
|
||||
|
||||
switch req.Action {
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@ func commonActionLabel(action string, targetType string, targetName string) stri
|
|||
}
|
||||
|
||||
if targetName != "" {
|
||||
return actionLabel + typeLabel + ": " + targetName
|
||||
return actionLabel + typeLabel + ":" + targetName
|
||||
}
|
||||
return actionLabel + typeLabel
|
||||
}
|
||||
|
|
|
|||
|
|
@ -207,6 +207,12 @@ const SiderBar = ({ onNavigate = () => {} }) => {
|
|||
|
||||
const adminItems = useMemo(() => {
|
||||
const items = [
|
||||
{
|
||||
text: t('操作记录'),
|
||||
itemKey: 'operation-log',
|
||||
to: '/console/operation-log',
|
||||
className: isAdmin() ? '' : 'tableHiddle',
|
||||
},
|
||||
{
|
||||
text: t('渠道管理'),
|
||||
itemKey: 'channel',
|
||||
|
|
@ -249,12 +255,6 @@ const SiderBar = ({ onNavigate = () => {} }) => {
|
|||
to: '/user',
|
||||
className: isAdmin() ? '' : 'tableHiddle',
|
||||
},
|
||||
{
|
||||
text: t('操作记录'),
|
||||
itemKey: 'operation-log',
|
||||
to: '/console/operation-log',
|
||||
className: isAdmin() ? '' : 'tableHiddle',
|
||||
},
|
||||
{
|
||||
text: t('代理管理'),
|
||||
itemKey: 'distributor',
|
||||
|
|
|
|||
|
|
@ -202,7 +202,7 @@ const RechargeCard = ({
|
|||
{
|
||||
key: 'rpm',
|
||||
icon: Gauge,
|
||||
label: t('RPM'),
|
||||
label: t('每分钟请求'),
|
||||
value: rpmTpmData?.rpm,
|
||||
sublabel: t('最近1分钟'),
|
||||
raw: true,
|
||||
|
|
@ -211,7 +211,7 @@ const RechargeCard = ({
|
|||
{
|
||||
key: 'tpm',
|
||||
icon: TrendingUp,
|
||||
label: t('TPM'),
|
||||
label: t('每分钟Token'),
|
||||
value: rpmTpmData?.tpm,
|
||||
sublabel: t('最近1分钟'),
|
||||
raw: true,
|
||||
|
|
|
|||
|
|
@ -85,6 +85,10 @@ const OperationLog = () => {
|
|||
const [detailVisible, setDetailVisible] = useState(false);
|
||||
const [selectedLog, setSelectedLog] = useState(null);
|
||||
|
||||
// Cleanup modal
|
||||
const [deleteModalVisible, setDeleteModalVisible] = useState(false);
|
||||
const [deleteDate, setDeleteDate] = useState(null);
|
||||
|
||||
const fetchLogs = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
|
|
@ -132,14 +136,17 @@ const OperationLog = () => {
|
|||
fetchLogs();
|
||||
};
|
||||
|
||||
const handleDeleteOldLogs = async () => {
|
||||
if (!dateRange || !dateRange[1]) {
|
||||
const handleDeleteOldLogs = () => {
|
||||
setDeleteDate(null);
|
||||
setDeleteModalVisible(true);
|
||||
};
|
||||
|
||||
const handleConfirmDelete = () => {
|
||||
if (!deleteDate) {
|
||||
showError('请选择截止日期');
|
||||
return;
|
||||
}
|
||||
const targetTimestamp = Math.floor(
|
||||
new Date(dateRange[1]).getTime() / 1000
|
||||
);
|
||||
const targetTimestamp = Math.floor(new Date(deleteDate).getTime() / 1000);
|
||||
Modal.confirm({
|
||||
title: '确认清理',
|
||||
content: `确定要清理 ${timestamp2string(targetTimestamp)} 之前的操作日志吗?此操作不可逆。`,
|
||||
|
|
@ -151,6 +158,7 @@ const OperationLog = () => {
|
|||
const { success, data, message } = res.data;
|
||||
if (success) {
|
||||
showSuccess(`成功清理 ${data} 条操作日志`);
|
||||
setDeleteModalVisible(false);
|
||||
fetchLogs();
|
||||
} else {
|
||||
showError(message);
|
||||
|
|
@ -206,7 +214,7 @@ const OperationLog = () => {
|
|||
dataIndex: 'target_name',
|
||||
key: 'target_name',
|
||||
width: 160,
|
||||
render: (text, record) => text || `ID: ${record.target_id}`,
|
||||
render: (text, record) => text || `ID:${record.target_id}`,
|
||||
},
|
||||
{
|
||||
title: t('操作描述'),
|
||||
|
|
@ -339,6 +347,27 @@ const OperationLog = () => {
|
|||
/>
|
||||
</Card>
|
||||
|
||||
<Modal
|
||||
title={t('清理日志')}
|
||||
visible={deleteModalVisible}
|
||||
onCancel={() => setDeleteModalVisible(false)}
|
||||
onOk={handleConfirmDelete}
|
||||
okText={t('确认清理')}
|
||||
cancelText={t('取消')}
|
||||
width={420}
|
||||
>
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
|
||||
<Text>{t('选择截止日期,将清理该日期之前的所有操作日志。此操作不可逆。')}</Text>
|
||||
<DatePicker
|
||||
type='dateTime'
|
||||
placeholder={t('选择截止日期')}
|
||||
value={deleteDate}
|
||||
onChange={setDeleteDate}
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
<Modal
|
||||
title={t('操作详情')}
|
||||
visible={detailVisible}
|
||||
|
|
|
|||
Loading…
Reference in New Issue