[后端] 增加应用分组

This commit is contained in:
Sun
2023-11-15 22:27:07 +08:00
parent ebf9500529
commit 7c409112ba
10 changed files with 173 additions and 19 deletions

View File

@@ -16,7 +16,7 @@ COPY . /build
RUN pnpm run build
# build backend
FROM golang:1.19 as server_image
FROM golang:1.20 as server_image
WORKDIR /build

View File

@@ -1,7 +1,8 @@
package panel
type ApiPanel struct {
ItemIcon ItemIcon
UserConfig UserConfig
UsersApi UsersApi
ItemIcon ItemIcon
UserConfig UserConfig
UsersApi UsersApi
ItemIconGroup ItemIconGroup
}

View File

@@ -0,0 +1,89 @@
package panel
import (
"sun-panel/api/api_v1/common/apiData/commonApiStructs"
"sun-panel/api/api_v1/common/apiReturn"
"sun-panel/api/api_v1/common/base"
"sun-panel/global"
"sun-panel/models"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
)
type ItemIconGroup struct {
}
func (a *ItemIconGroup) Edit(c *gin.Context) {
userInfo, _ := base.GetCurrentUserInfo(c)
req := models.ItemIconGroup{}
if err := c.ShouldBindBodyWith(&req, binding.JSON); err != nil {
apiReturn.ErrorParamFomat(c, err.Error())
return
}
req.UserId = userInfo.ID
if req.ID != 0 {
// 修改
global.Db.Model(&models.ItemIconGroup{}).
Select("IconJson", "Icon", "Title", "Url", "LanUrl", "Description", "OpenMethod", "Sort", "GroupId", "UserId").
Where("id=?", req.ID).Updates(&req)
} else {
// 创建
global.Db.Create(&req)
}
apiReturn.SuccessData(c, req)
}
func (a *ItemIconGroup) GetList(c *gin.Context) {
userInfo, _ := base.GetCurrentUserInfo(c)
groups := []models.ItemIconGroup{}
if err := global.Db.Order("sort ,created_at").Where("user_id=?", userInfo.ID).Find(&groups, "user_id=?", 1, userInfo.ID).Error; err != nil {
apiReturn.ErrorDatabase(c, err.Error())
return
}
// 判断分组是否为空,为空将自动创建默认分组
if len(groups) == 0 {
defaultGroup := models.ItemIconGroup{
Title: "APP",
UserId: userInfo.ID,
Icon: "material-symbols:folder-outline"}
if err := global.Db.Create(&defaultGroup).Error; err != nil {
apiReturn.ErrorDatabase(c, err.Error())
return
}
// 并将当前账号下所有无分组的图标更新到当前组
if err := global.Db.Model(&models.ItemIcon{}).Where("user_id=?", userInfo.ID).Update("item_icon_group_id", defaultGroup.ID).Error; err != nil {
apiReturn.ErrorDatabase(c, err.Error())
return
}
groups = append(groups, defaultGroup)
}
apiReturn.SuccessListData(c, groups, 0)
}
func (a *ItemIconGroup) Deletes(c *gin.Context) {
req := commonApiStructs.RequestDeleteIds[uint]{}
if err := c.ShouldBindBodyWith(&req, binding.JSON); err != nil {
apiReturn.ErrorParamFomat(c, err.Error())
return
}
userInfo, _ := base.GetCurrentUserInfo(c)
if err := global.Db.Delete(&models.ItemIconGroup{}, "id in ? AND user_id=?", req.Ids, userInfo.ID).Error; err != nil {
apiReturn.ErrorDatabase(c, err.Error())
return
}
apiReturn.Success(c)
}

View File

@@ -25,8 +25,7 @@ func (a *ItemIcon) Edit(c *gin.Context) {
}
req.UserId = userInfo.ID
req.GroupId = 1
req.Sort = 1
req.Sort = 9999
// json转字符串
if j, err := json.Marshal(req.Icon); err == nil {
@@ -87,7 +86,7 @@ func (a *ItemIcon) GetListByGroupId(c *gin.Context) {
userInfo, _ := base.GetCurrentUserInfo(c)
itemIcons := []models.ItemIcon{}
if err := global.Db.Order("sort ,created_at DESC").Where("user_id=?", userInfo.ID).Find(&itemIcons, "group_id = ? AND user_id=?", 1, userInfo.ID).Error; err != nil {
if err := global.Db.Order("sort ,created_at").Where("user_id=?", userInfo.ID).Find(&itemIcons, "group_id = ? AND user_id=?", 1, userInfo.ID).Error; err != nil {
apiReturn.ErrorDatabase(c, err.Error())
return
}
@@ -108,7 +107,7 @@ func (a *ItemIcon) Deletes(c *gin.Context) {
}
userInfo, _ := base.GetCurrentUserInfo(c)
if err := global.Db.Debug().Delete(&models.ItemIcon{}, "id in ? AND user_id=?", req.Ids, userInfo.ID).Error; err != nil {
if err := global.Db.Delete(&models.ItemIcon{}, "id in ? AND user_id=?", req.Ids, userInfo.ID).Error; err != nil {
apiReturn.ErrorDatabase(c, err.Error())
return
}

View File

@@ -121,6 +121,7 @@ func CreateDatabase(driver string, db *gorm.DB) error {
&models.ItemIcon{},
&models.UserConfig{},
&models.File{},
&models.ItemIconGroup{},
)
return err

View File

@@ -4,15 +4,15 @@ import "sun-panel/models/datatype"
type ItemIcon struct {
BaseModel
IconJson string `gorm:"type:varchar(1000)" json:"-"`
Icon datatype.ItemIconIconInfo `gorm:"-" json:"icon"`
Title string `gorm:"type:varchar(50)" json:"title"`
Url string `gorm:"type:varchar(1000)" json:"url"`
LanUrl string `gorm:"type:varchar(1000)" json:"lanUrl"`
Description string `gorm:"type:varchar(1000)" json:"description"`
OpenMethod int `gorm:"type:tinyint(1)" json:"openMethod"`
Sort int `gorm:"type:int(11)" json:"sort"`
GroupId int `json:"groupId"` // 为以后分组做准备
UserId uint `json:"userId"`
User User `json:"user"`
IconJson string `gorm:"type:varchar(1000)" json:"-"`
Icon datatype.ItemIconIconInfo `gorm:"-" json:"icon"`
Title string `gorm:"type:varchar(50)" json:"title"`
Url string `gorm:"type:varchar(1000)" json:"url"`
LanUrl string `gorm:"type:varchar(1000)" json:"lanUrl"`
Description string `gorm:"type:varchar(1000)" json:"description"`
OpenMethod int `gorm:"type:tinyint(1)" json:"openMethod"`
Sort int `gorm:"type:int(11)" json:"sort"`
ItemIconGroupId int `json:"itemIconGroupId"`
UserId uint `json:"userId"`
User User `json:"user"`
}

View File

@@ -0,0 +1,11 @@
package models
type ItemIconGroup struct {
BaseModel
Icon string `json:"icon"`
Title string `gorm:"type:varchar(50)" json:"title"`
Description string `gorm:"type:varchar(1000)" json:"description"`
Sort int `gorm:"type:int(11)" json:"sort"`
UserId uint `json:"userId"`
User User `json:"user"`
}

View File

@@ -6,4 +6,5 @@ func Init(routerGroup *gin.RouterGroup) {
InitItemIcon(routerGroup)
InitUserConfig(routerGroup)
InitUsersRouter(routerGroup)
InitItemIconGroup(routerGroup)
}

View File

@@ -0,0 +1,18 @@
package panel
import (
"sun-panel/api/api_v1"
"sun-panel/api/api_v1/middleware"
"github.com/gin-gonic/gin"
)
func InitItemIconGroup(router *gin.RouterGroup) {
itemIconGroup := api_v1.ApiGroupApp.ApiPanel.ItemIconGroup
r := router.Group("", middleware.LoginInterceptor)
{
r.POST("/panel/itemIconGroup/edit", itemIconGroup.Edit)
r.POST("/panel/itemIconGroup/getList", itemIconGroup.GetList)
r.POST("/panel/itemIconGroup/deletes", itemIconGroup.Deletes)
}
}

View File

@@ -231,6 +231,7 @@ onMounted(() => {
:animation="300"
class="mx-auto mt-4 grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 xl:12 gap-5"
@end="handleEndDrag"
filter=".not-drag"
>
<div v-for="item, index in items" :key="index" @contextmenu="(e) => handleContextMenu(e, item)">
<div
@@ -254,6 +255,28 @@ onMounted(() => {
</div>
</div>
</div>
<div class="not-drag">
<div
class="w-full rounded-2xl cursor-pointer transition-all duration-200 hover:shadow-[0_0_20px_10px_rgba(0,0,0,0.2)] bg-[#2a2a2a6b] flex"
@click="handleAddAppClick"
>
<ItemIcon :item-icon="{ itemType: 3, text: 'subway:add', bgColor: '#00000000' }" />
<div class="text-white m-[8px]" :style="{ color: panelState.panelConfig.iconTextColor }">
<div>
<NEllipsis>
添加图标
</NEllipsis>
</div>
<div class="text text-xs">
<NEllipsis>
新增一个新的图标
</NEllipsis>
</div>
</div>
</div>
</div>
</vuedraggable>
<!-- <NGrid :x-gap="15" :y-gap="15" item-responsive cols="1 200:1 400:2 600:3 800:4 1000:5 1200:6">
<NGridItem v-for="(item, index) in items" :key="index">
@@ -314,6 +337,7 @@ onMounted(() => {
item-key="id"
:animation="300"
class="mx-auto mt-4 grid grid-cols-4 sm:grid-cols-6 md:grid-cols-8 lg:grid-cols-10 xl:12 gap-5"
filter=".not-drag"
>
<div v-for="item, index in items" :key="index" @contextmenu="(e) => handleContextMenu(e, item)">
<div
@@ -326,6 +350,16 @@ onMounted(() => {
<span>{{ item.title }}</span>
</div>
</div>
<div class="not-drag">
<div class="w-[70px] h-[70px] mx-auto rounded-2xl cursor-pointer transition-all duration-200 hover:shadow-[0_0_20px_10px_rgba(0,0,0,0.2)]" @click="handleAddAppClick">
<ItemIcon :item-icon="{ itemType: 3, text: 'subway:add', bgColor: '#343434' }" />
</div>
<div class="text-center app-icon-text-shadow cursor-pointer mt-[2px]" :style="{ color: panelState.panelConfig.iconTextColor }" @click="handleAddAppClick">
添加图标
</div>
</div>
</vuedraggable>
</div>
</div>