操作日志中文化与功能优化
- 后端操作描述统一使用中文冒号(:)替换英文冒号(:) - 前端资源名称列 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 {
|
if addChannelRequest.Channel != nil {
|
||||||
channelName = addChannelRequest.Channel.Name
|
channelName = addChannelRequest.Channel.Name
|
||||||
}
|
}
|
||||||
service.RecordCreateOperation(c, "channel", 0, channelName, "创建渠道: "+channelName, "")
|
service.RecordCreateOperation(c, "channel", 0, channelName, "创建渠道:"+channelName, "")
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"success": true,
|
"success": true,
|
||||||
"message": "",
|
"message": "",
|
||||||
|
|
@ -1366,7 +1366,7 @@ func DeleteChannel(c *gin.Context) {
|
||||||
}
|
}
|
||||||
model.InitChannelCache()
|
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{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"success": true,
|
"success": true,
|
||||||
"message": "",
|
"message": "",
|
||||||
|
|
@ -1721,7 +1721,7 @@ func UpdateChannel(c *gin.Context) {
|
||||||
channel.Key = ""
|
channel.Key = ""
|
||||||
clearChannelInfo(&channel.Channel)
|
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{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"success": true,
|
"success": true,
|
||||||
"message": "",
|
"message": "",
|
||||||
|
|
|
||||||
|
|
@ -270,7 +270,7 @@ func CreateModelMeta(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
model.RefreshPricing()
|
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)
|
common.ApiSuccess(c, &m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -319,7 +319,7 @@ func UpdateModelMeta(c *gin.Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
model.RefreshPricing()
|
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)
|
common.ApiSuccess(c, &m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -336,7 +336,7 @@ func DeleteModelMeta(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
model.RefreshPricing()
|
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)
|
common.ApiSuccess(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -690,10 +690,10 @@ func UpdateOption(c *gin.Context) {
|
||||||
if modelPricingOptionKeys[option.Key] {
|
if modelPricingOptionKeys[option.Key] {
|
||||||
changes := computeModelPricingDiff(oldVal, valStr)
|
changes := computeModelPricingDiff(oldVal, valStr)
|
||||||
if len(changes) > 0 {
|
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 {
|
} 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{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ func AddRedemption(c *gin.Context) {
|
||||||
}
|
}
|
||||||
keys = append(keys, key)
|
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{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"success": true,
|
"success": true,
|
||||||
"message": "",
|
"message": "",
|
||||||
|
|
@ -122,7 +122,7 @@ func DeleteRedemption(c *gin.Context) {
|
||||||
common.ApiError(c, err)
|
common.ApiError(c, err)
|
||||||
return
|
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{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"success": true,
|
"success": true,
|
||||||
"message": "",
|
"message": "",
|
||||||
|
|
@ -161,7 +161,7 @@ func UpdateRedemption(c *gin.Context) {
|
||||||
common.ApiError(c, err)
|
common.ApiError(c, err)
|
||||||
return
|
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{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"success": true,
|
"success": true,
|
||||||
"message": "",
|
"message": "",
|
||||||
|
|
|
||||||
|
|
@ -228,7 +228,7 @@ func AddToken(c *gin.Context) {
|
||||||
common.ApiError(c, err)
|
common.ApiError(c, err)
|
||||||
return
|
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{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"success": true,
|
"success": true,
|
||||||
"message": "",
|
"message": "",
|
||||||
|
|
@ -243,7 +243,7 @@ func DeleteToken(c *gin.Context) {
|
||||||
common.ApiError(c, err)
|
common.ApiError(c, err)
|
||||||
return
|
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{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"success": true,
|
"success": true,
|
||||||
"message": "",
|
"message": "",
|
||||||
|
|
@ -308,7 +308,7 @@ func UpdateToken(c *gin.Context) {
|
||||||
common.ApiError(c, err)
|
common.ApiError(c, err)
|
||||||
return
|
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{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"success": true,
|
"success": true,
|
||||||
"message": "",
|
"message": "",
|
||||||
|
|
|
||||||
|
|
@ -1206,7 +1206,7 @@ func UpdateUser(c *gin.Context) {
|
||||||
if originUser.DistributorCommissionBps != updatedUser.DistributorCommissionBps {
|
if originUser.DistributorCommissionBps != updatedUser.DistributorCommissionBps {
|
||||||
changes = append(changes, service.FieldChange{Field: "分销佣金比例", OldValue: fmt.Sprintf("%d‱", originUser.DistributorCommissionBps), NewValue: fmt.Sprintf("%d‱", 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{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"success": true,
|
"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))
|
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{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"success": true,
|
"success": true,
|
||||||
|
|
@ -1421,7 +1421,7 @@ func DeleteUser(c *gin.Context) {
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
service.RecordDeleteOperation(c, "user", id, originUser.Username, "删除用户: "+originUser.Username, "")
|
service.RecordDeleteOperation(c, "user", id, originUser.Username, "删除用户:"+originUser.Username, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeleteSelf(c *gin.Context) {
|
func DeleteSelf(c *gin.Context) {
|
||||||
|
|
@ -1501,7 +1501,7 @@ func CreateUser(c *gin.Context) {
|
||||||
common.ApiError(c, err)
|
common.ApiError(c, err)
|
||||||
return
|
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{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"success": true,
|
"success": true,
|
||||||
|
|
@ -1781,7 +1781,7 @@ func ManageUser(c *gin.Context) {
|
||||||
}
|
}
|
||||||
changes = append(changes, service.FieldChange{Field: "学员", OldValue: oldLabel, NewValue: newLabel})
|
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 {
|
switch req.Action {
|
||||||
|
|
|
||||||
|
|
@ -222,7 +222,7 @@ func commonActionLabel(action string, targetType string, targetName string) stri
|
||||||
}
|
}
|
||||||
|
|
||||||
if targetName != "" {
|
if targetName != "" {
|
||||||
return actionLabel + typeLabel + ": " + targetName
|
return actionLabel + typeLabel + ":" + targetName
|
||||||
}
|
}
|
||||||
return actionLabel + typeLabel
|
return actionLabel + typeLabel
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -207,6 +207,12 @@ const SiderBar = ({ onNavigate = () => {} }) => {
|
||||||
|
|
||||||
const adminItems = useMemo(() => {
|
const adminItems = useMemo(() => {
|
||||||
const items = [
|
const items = [
|
||||||
|
{
|
||||||
|
text: t('操作记录'),
|
||||||
|
itemKey: 'operation-log',
|
||||||
|
to: '/console/operation-log',
|
||||||
|
className: isAdmin() ? '' : 'tableHiddle',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
text: t('渠道管理'),
|
text: t('渠道管理'),
|
||||||
itemKey: 'channel',
|
itemKey: 'channel',
|
||||||
|
|
@ -249,12 +255,6 @@ const SiderBar = ({ onNavigate = () => {} }) => {
|
||||||
to: '/user',
|
to: '/user',
|
||||||
className: isAdmin() ? '' : 'tableHiddle',
|
className: isAdmin() ? '' : 'tableHiddle',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
text: t('操作记录'),
|
|
||||||
itemKey: 'operation-log',
|
|
||||||
to: '/console/operation-log',
|
|
||||||
className: isAdmin() ? '' : 'tableHiddle',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
text: t('代理管理'),
|
text: t('代理管理'),
|
||||||
itemKey: 'distributor',
|
itemKey: 'distributor',
|
||||||
|
|
|
||||||
|
|
@ -202,7 +202,7 @@ const RechargeCard = ({
|
||||||
{
|
{
|
||||||
key: 'rpm',
|
key: 'rpm',
|
||||||
icon: Gauge,
|
icon: Gauge,
|
||||||
label: t('RPM'),
|
label: t('每分钟请求'),
|
||||||
value: rpmTpmData?.rpm,
|
value: rpmTpmData?.rpm,
|
||||||
sublabel: t('最近1分钟'),
|
sublabel: t('最近1分钟'),
|
||||||
raw: true,
|
raw: true,
|
||||||
|
|
@ -211,7 +211,7 @@ const RechargeCard = ({
|
||||||
{
|
{
|
||||||
key: 'tpm',
|
key: 'tpm',
|
||||||
icon: TrendingUp,
|
icon: TrendingUp,
|
||||||
label: t('TPM'),
|
label: t('每分钟Token'),
|
||||||
value: rpmTpmData?.tpm,
|
value: rpmTpmData?.tpm,
|
||||||
sublabel: t('最近1分钟'),
|
sublabel: t('最近1分钟'),
|
||||||
raw: true,
|
raw: true,
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,10 @@ const OperationLog = () => {
|
||||||
const [detailVisible, setDetailVisible] = useState(false);
|
const [detailVisible, setDetailVisible] = useState(false);
|
||||||
const [selectedLog, setSelectedLog] = useState(null);
|
const [selectedLog, setSelectedLog] = useState(null);
|
||||||
|
|
||||||
|
// Cleanup modal
|
||||||
|
const [deleteModalVisible, setDeleteModalVisible] = useState(false);
|
||||||
|
const [deleteDate, setDeleteDate] = useState(null);
|
||||||
|
|
||||||
const fetchLogs = async () => {
|
const fetchLogs = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
|
|
@ -132,14 +136,17 @@ const OperationLog = () => {
|
||||||
fetchLogs();
|
fetchLogs();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDeleteOldLogs = async () => {
|
const handleDeleteOldLogs = () => {
|
||||||
if (!dateRange || !dateRange[1]) {
|
setDeleteDate(null);
|
||||||
|
setDeleteModalVisible(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleConfirmDelete = () => {
|
||||||
|
if (!deleteDate) {
|
||||||
showError('请选择截止日期');
|
showError('请选择截止日期');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const targetTimestamp = Math.floor(
|
const targetTimestamp = Math.floor(new Date(deleteDate).getTime() / 1000);
|
||||||
new Date(dateRange[1]).getTime() / 1000
|
|
||||||
);
|
|
||||||
Modal.confirm({
|
Modal.confirm({
|
||||||
title: '确认清理',
|
title: '确认清理',
|
||||||
content: `确定要清理 ${timestamp2string(targetTimestamp)} 之前的操作日志吗?此操作不可逆。`,
|
content: `确定要清理 ${timestamp2string(targetTimestamp)} 之前的操作日志吗?此操作不可逆。`,
|
||||||
|
|
@ -151,6 +158,7 @@ const OperationLog = () => {
|
||||||
const { success, data, message } = res.data;
|
const { success, data, message } = res.data;
|
||||||
if (success) {
|
if (success) {
|
||||||
showSuccess(`成功清理 ${data} 条操作日志`);
|
showSuccess(`成功清理 ${data} 条操作日志`);
|
||||||
|
setDeleteModalVisible(false);
|
||||||
fetchLogs();
|
fetchLogs();
|
||||||
} else {
|
} else {
|
||||||
showError(message);
|
showError(message);
|
||||||
|
|
@ -206,7 +214,7 @@ const OperationLog = () => {
|
||||||
dataIndex: 'target_name',
|
dataIndex: 'target_name',
|
||||||
key: 'target_name',
|
key: 'target_name',
|
||||||
width: 160,
|
width: 160,
|
||||||
render: (text, record) => text || `ID: ${record.target_id}`,
|
render: (text, record) => text || `ID:${record.target_id}`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('操作描述'),
|
title: t('操作描述'),
|
||||||
|
|
@ -339,6 +347,27 @@ const OperationLog = () => {
|
||||||
/>
|
/>
|
||||||
</Card>
|
</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
|
<Modal
|
||||||
title={t('操作详情')}
|
title={t('操作详情')}
|
||||||
visible={detailVisible}
|
visible={detailVisible}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue