1、问题描述
本来以为哪吒面板删除服务器后会自动对其进行重新排序,结果确实会1,代码如下:
1 | if err == nil { // 删除服务器 singleton.ServerLock.Lock() onServerDelete(id) singleton.ServerLock.Unlock() singleton.ReSortServer() } |
然而删除之后 ID 还是不连续的,这让我强迫症犯了非常的难受,而且后台显示不连续就算了,访客查看居然也是不连续的(使用 Neko-Mdui 主题,其他主题不显示服务器 ID,可能没有这个困扰)。
2、代码分析
问题出在哪里呢?我们来看看 ReSortServer
方法,根据说明实现了一个排序功能:
ReSortServer 根据服务器ID 对服务器列表进行排序(ID越大越靠前)。2
代码如下:
1 | func ReSortServer() { ServerLock.RLock() defer ServerLock.RUnlock() SortedServerLock.Lock() defer SortedServerLock.Unlock() SortedServerList = []*model.Server{} SortedServerListForGuest = []*model.Server{} for _, s := range ServerList { SortedServerList = append(SortedServerList, s) if !s.HideForGuest { SortedServerListForGuest = append(SortedServerListForGuest, s) } } // 按照服务器 ID 排序的具体实现(ID越大越靠前) sort.SliceStable(SortedServerList, func(i, j int) bool { if SortedServerList[i].DisplayIndex == SortedServerList[j].DisplayIndex { return SortedServerList[i].ID < SortedServerList[j].ID } return SortedServerList[i].DisplayIndex > SortedServerList[j].DisplayIndex }) sort.SliceStable(SortedServerListForGuest, func(i, j int) bool { if SortedServerListForGuest[i].DisplayIndex == SortedServerListForGuest[j].DisplayIndex { return SortedServerListForGuest[i].ID < SortedServerListForGuest[j].ID } return SortedServerListForGuest[i].DisplayIndex > SortedServerListForGuest[j].DisplayIndex }) } |
嗯,没学过 Golang 看不懂,但是大致可以根据命名看出这个方法仅对列表进行排序,并不重新设置 ID。
3、解决方法
直接编辑 /opt/nezha/dashboard/data/sqlite.db
,执行:
1 | UPDATE servers SET id = ( SELECT COUNT(*) FROM servers AS s WHERE s.rowid <= servers.rowid ); |
即可解决。
4、花絮
根据面向 ChatGPT 编程深入研究,最早得出的 SQL 语句是:
1 | -- 创建临时表,并按照原始id的顺序填充连续的序列号 WITH RankedServers AS ( SELECT id, ROW_NUMBER() OVER (ORDER BY id) AS NewId FROM servers ) -- 使用UPDATE语句将servers表中的id更新为连续的序列号 UPDATE servers SET id = RankedServers.NewId FROM RankedServers WHERE servers.id = RankedServers.id; |
然而执行后直接报错语法错误,打回去让 GPT 重写:
1 | -- 创建一个临时表来存储原始id和新的连续id CREATE TEMP TABLE TempServers AS SELECT id, ROW_NUMBER() OVER (ORDER BY id) AS NewId FROM servers; -- 删除原始表中的数据 DELETE FROM servers; -- 将临时表中的数据插入原始表中 INSERT INTO servers(id, other_columns) SELECT NewId, other_columns FROM TempServers; -- 删除临时表 DROP TABLE TempServers; |
还是不行,最后强调是 SQLite 环境后才得出上述可以运行的代码。
然后根据哪吒面板的代码,可以再加上:
1 | func UpdateServersID() { ServerLock.Lock() defer ServerLock.Unlock() for i, s := range ServerList { count := 0 for _, s2 := range ServerList[:i+1] { if s2.RowID <= s.RowID { count++ } } s.ID = count } } |
实现 ID 重设,但是我没有 Golang 调试环境,就不去瞎改代码了(XD),有能力的可以参考此段代码去提个 Pull Request。
- 见 member_api.go 第 205 行 ↩
- 见 singleton package 页面 ↩
解决哪吒面板删除服务器后 ID 不连续
评论