diff --git a/controller/user.go b/controller/user.go
index d7eb42d7..ecaf2583 100644
--- a/controller/user.go
+++ b/controller/user.go
@@ -459,6 +459,9 @@ func GetSelf(c *gin.Context) {
})
return
}
+ // Hide admin remarks: set to empty to trigger omitempty tag, ensuring the remark field is not included in JSON returned to regular users
+ user.Remark = ""
+
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "",
diff --git a/model/user.go b/model/user.go
index 1b3a04b6..6a695457 100644
--- a/model/user.go
+++ b/model/user.go
@@ -41,6 +41,7 @@ type User struct {
DeletedAt gorm.DeletedAt `gorm:"index"`
LinuxDOId string `json:"linux_do_id" gorm:"column:linux_do_id;index"`
Setting string `json:"setting" gorm:"type:text;column:setting"`
+ Remark string `json:"remark,omitempty" gorm:"type:varchar(255)" validate:"max=255"`
}
func (user *User) ToBaseUser() *UserBase {
@@ -366,6 +367,7 @@ func (user *User) Edit(updatePassword bool) error {
"display_name": newUser.DisplayName,
"group": newUser.Group,
"quota": newUser.Quota,
+ "remark": newUser.Remark,
}
if updatePassword {
updates["password"] = newUser.Password
diff --git a/web/src/components/table/UsersTable.js b/web/src/components/table/UsersTable.js
index a027af59..d245c56f 100644
--- a/web/src/components/table/UsersTable.js
+++ b/web/src/components/table/UsersTable.js
@@ -26,6 +26,7 @@ import {
Space,
Table,
Tag,
+ Tooltip,
Typography
} from '@douyinfe/semi-ui';
import {
@@ -110,6 +111,27 @@ const UsersTable = () => {
{
title: t('用户名'),
dataIndex: 'username',
+ render: (text, record) => {
+ const remark = record.remark;
+ if (!remark) {
+ return {text};
+ }
+ const maxLen = 10;
+ const displayRemark = remark.length > maxLen ? remark.slice(0, maxLen) + '…' : remark;
+ return (
+
+ {text}
+
+
+
+
+
+
+ );
+ },
},
{
title: t('分组'),
diff --git a/web/src/i18n/locales/en.json b/web/src/i18n/locales/en.json
index ba23ca5c..358c86bb 100644
--- a/web/src/i18n/locales/en.json
+++ b/web/src/i18n/locales/en.json
@@ -1658,5 +1658,6 @@
"清除失效兑换码": "Clear invalid redemption codes",
"确定清除所有失效兑换码?": "Are you sure you want to clear all invalid redemption codes?",
"将删除已使用、已禁用及过期的兑换码,此操作不可撤销。": "This will delete all used, disabled, and expired redemption codes, this operation cannot be undone.",
- "选择过期时间(可选,留空为永久)": "Select expiration time (optional, leave blank for permanent)"
+ "选择过期时间(可选,留空为永久)": "Select expiration time (optional, leave blank for permanent)",
+ "请输入备注(仅管理员可见)": "Please enter a remark (only visible to administrators)"
}
\ No newline at end of file
diff --git a/web/src/pages/User/AddUser.js b/web/src/pages/User/AddUser.js
index 99620cfe..259a7750 100644
--- a/web/src/pages/User/AddUser.js
+++ b/web/src/pages/User/AddUser.js
@@ -16,6 +16,7 @@ import {
IconClose,
IconKey,
IconUserAdd,
+ IconEdit,
} from '@douyinfe/semi-icons';
import { useTranslation } from 'react-i18next';
@@ -27,10 +28,11 @@ const AddUser = (props) => {
username: '',
display_name: '',
password: '',
+ remark: '',
};
const [inputs, setInputs] = useState(originInputs);
const [loading, setLoading] = useState(false);
- const { username, display_name, password } = inputs;
+ const { username, display_name, password, remark } = inputs;
const handleInputChange = (name, value) => {
setInputs((inputs) => ({ ...inputs, [name]: value }));
@@ -175,6 +177,20 @@ const AddUser = (props) => {
required
/>
+
+
+ {t('备注')}
+ handleInputChange('remark', value)}
+ value={remark}
+ autoComplete="off"
+ size="large"
+ className="!rounded-lg"
+ prefix={}
+ showClear
+ />
+
diff --git a/web/src/pages/User/EditUser.js b/web/src/pages/User/EditUser.js
index dceb670a..8c028d74 100644
--- a/web/src/pages/User/EditUser.js
+++ b/web/src/pages/User/EditUser.js
@@ -22,6 +22,7 @@ import {
IconLink,
IconUserGroup,
IconPlus,
+ IconEdit,
} from '@douyinfe/semi-icons';
import { useTranslation } from 'react-i18next';
@@ -42,6 +43,7 @@ const EditUser = (props) => {
email: '',
quota: 0,
group: 'default',
+ remark: '',
});
const [groupOptions, setGroupOptions] = useState([]);
const {
@@ -55,6 +57,7 @@ const EditUser = (props) => {
email,
quota,
group,
+ remark,
} = inputs;
const handleInputChange = (name, value) => {
setInputs((inputs) => ({ ...inputs, [name]: value }));
@@ -247,6 +250,20 @@ const EditUser = (props) => {
showClear
/>
+
+
+ {t('备注')}
+ handleInputChange('remark', value)}
+ value={remark}
+ autoComplete="off"
+ size="large"
+ className="!rounded-lg"
+ prefix={}
+ showClear
+ />
+