一、需求
最近有一個需求,要實現一個無限級結構的樹型選單,差不多長下面這個樣子
我們知道無限級實現思路都是用一個parent_id將各種層級串聯起來,頂級的parent_id為0,例如如下層級的選單
選單一
選單二
選單三
選單四
選單五
選單六
選單7
選單八
在資料庫中的儲存一般是如下形式
原理就會記錄每一個選單的父級ID(parent_id),通過這樣的父級ID會構造出一棵樹型結構,層級(level)是為了標明當前選單是處於哪個層級
問題來了,一般這樣的結果要是一條一條插入,再人工用parent_id串起來,太反人類了,低效!
產品會讓工程師通過表格匯入這樣的資料,表格差不多都長如下這個樣子
我們需要用過程式碼來實現生成上面資料庫的結果,talk is cheap, show you the code
二、程式碼實現
func ImportMenus() (res interface{}, err error) {
columns := 5 //支援的無限級選單數量,想支援多少級寫多少
templateFile := "/Users/chenqionghe/Downloads/menus.xlsx" //匯入的表格路徑
f, err := excelize.OpenFile(templateFile) //讀取表格
if err != nil {
return nil, err
}
rows, err := f.GetRows("Sheet1")
if err != nil {
return nil, err
}
var allRowIds = make([][]int, len(rows)) //初始化儲存ID的陣列,通過下標定位對應選單生成的ID
for i, _ := range rows {
allRowIds[i] = make([]int, columns)
}
var parentId int
tx := db.DB().Begin()
exception.Block{
Try: func() {
for i, row := range rows {
if i == 0 { //表頭跳過
continue
}
//構造無限級選單
for j := 0; j < columns; j++ {
if row[j] == "" { //空值不操作
continue
}
if j == 0 && row[j] != "" { //頂級按鈕父級ID是0
parentId = 0
}
if j > 0 { //非頂級,向前或向上尋找最近的父級ID
if allRowIds[i][j-1] != 0 {
parentId = allRowIds[i][j-1] //向前找ID作為父級ID
} else {
for z := i - 1; z > 0; z-- {
if allRowIds[z][j-1] != 0 {
parentId = allRowIds[z][j-1] //向上找ID作為父級ID
break
}
}
}
}
newData := &model.Menu{Name: row[j], ParentID: parentId, Level: j + 1}
if err = tx.Save(newData).Error; err != nil { //選單插入資料庫
panic(err)
}
allRowIds[i][j] = newData.ID //儲存當ID到陣列對應陣列下標中,供後續選單作為父級ID使用
}
}
tx.Commit()
err = nil
},
Catch: func(e interface{}) {
tx.Rollback()
err = fmt.Errorf("err: %v", e)
},
}.Do()
return allRowIds, err
}
三、程式碼測試
先建立對應的資料表,結構如下
CREATE TABLE `menu` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '選單ID',
`name` varchar(255) NOT NULL COMMENT '選單名稱',
`parent_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '上級選單ID',
`level` tinyint(1) NOT NULL COMMENT '層級',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='選單表';
簡單例子
我們來測試一下匯入上面的表格
執行結果如下
可以看到,結果和我們設想的資料庫結果完全一樣!
複雜例子
好,我們再測試一個更復雜的例子,表格模板如下
匯入的結果如下
這樣就用Go實現了一個支援無限級選單的表格匯入,以上程式碼由chenqionghe提供,轉載請標明出處,giao~