mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-31 14:08:06 +08:00
feat: 完成 compose 模版功能
This commit is contained in:
parent
e50c4c39c1
commit
56c3c2f4cb
100
backend/app/api/v1/compose_template.go
Normal file
100
backend/app/api/v1/compose_template.go
Normal file
@ -0,0 +1,100 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"github.com/1Panel-dev/1Panel/app/api/v1/helper"
|
||||
"github.com/1Panel-dev/1Panel/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/constant"
|
||||
"github.com/1Panel-dev/1Panel/global"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func (b *BaseApi) CreateComposeTemplate(c *gin.Context) {
|
||||
var req dto.ComposeTemplateCreate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
if err := global.VALID.Struct(req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
if err := composeTemplateService.Create(req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
||||
func (b *BaseApi) SearchComposeTemplate(c *gin.Context) {
|
||||
var req dto.PageInfo
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
|
||||
total, list, err := composeTemplateService.SearchWithPage(req)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
|
||||
helper.SuccessWithData(c, dto.PageResult{
|
||||
Items: list,
|
||||
Total: total,
|
||||
})
|
||||
}
|
||||
|
||||
func (b *BaseApi) ListComposeTemplate(c *gin.Context) {
|
||||
list, err := composeTemplateService.List()
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
|
||||
helper.SuccessWithData(c, list)
|
||||
}
|
||||
|
||||
func (b *BaseApi) DeleteComposeTemplate(c *gin.Context) {
|
||||
var req dto.BatchDeleteReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
if err := global.VALID.Struct(req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := composeTemplateService.Delete(req.Ids); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
||||
func (b *BaseApi) UpdateComposeTemplate(c *gin.Context) {
|
||||
var req dto.ComposeTemplateUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
if err := global.VALID.Struct(req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
id, err := helper.GetParamID(c)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
|
||||
upMap := make(map[string]interface{})
|
||||
upMap["from"] = req.From
|
||||
upMap["content"] = req.Content
|
||||
upMap["description"] = req.Description
|
||||
if err := composeTemplateService.Update(id, upMap); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
@ -9,17 +9,18 @@ type ApiGroup struct {
|
||||
var ApiGroupApp = new(ApiGroup)
|
||||
|
||||
var (
|
||||
authService = service.ServiceGroupApp.AuthService
|
||||
hostService = service.ServiceGroupApp.HostService
|
||||
backupService = service.ServiceGroupApp.BackupService
|
||||
groupService = service.ServiceGroupApp.GroupService
|
||||
containerService = service.ServiceGroupApp.ContainerService
|
||||
imageRepoService = service.ServiceGroupApp.ImageRepoService
|
||||
imageService = service.ServiceGroupApp.ImageService
|
||||
commandService = service.ServiceGroupApp.CommandService
|
||||
operationService = service.ServiceGroupApp.OperationService
|
||||
fileService = service.ServiceGroupApp.FileService
|
||||
cronjobService = service.ServiceGroupApp.CronjobService
|
||||
settingService = service.ServiceGroupApp.SettingService
|
||||
appService = service.ServiceGroupApp.AppService
|
||||
authService = service.ServiceGroupApp.AuthService
|
||||
hostService = service.ServiceGroupApp.HostService
|
||||
backupService = service.ServiceGroupApp.BackupService
|
||||
groupService = service.ServiceGroupApp.GroupService
|
||||
containerService = service.ServiceGroupApp.ContainerService
|
||||
composeTemplateService = service.ServiceGroupApp.ComposeTemplateService
|
||||
imageRepoService = service.ServiceGroupApp.ImageRepoService
|
||||
imageService = service.ServiceGroupApp.ImageService
|
||||
commandService = service.ServiceGroupApp.CommandService
|
||||
operationService = service.ServiceGroupApp.OperationService
|
||||
fileService = service.ServiceGroupApp.FileService
|
||||
cronjobService = service.ServiceGroupApp.CronjobService
|
||||
settingService = service.ServiceGroupApp.SettingService
|
||||
appService = service.ServiceGroupApp.AppService
|
||||
)
|
||||
|
@ -246,7 +246,7 @@ func (b *BaseApi) LoadFromFile(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
buf := make([]byte, 1024*500)
|
||||
buf := make([]byte, 1024*2)
|
||||
if _, err := file.Read(buf); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
|
25
backend/app/dto/compose_template.go
Normal file
25
backend/app/dto/compose_template.go
Normal file
@ -0,0 +1,25 @@
|
||||
package dto
|
||||
|
||||
import "time"
|
||||
|
||||
type ComposeTemplateCreate struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
From string `json:"from" validate:"required,oneof=edit path"`
|
||||
Description string `json:"description"`
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
type ComposeTemplateUpdate struct {
|
||||
From string `json:"from" validate:"required,oneof=edit path"`
|
||||
Description string `json:"description"`
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
type ComposeTemplateInfo struct {
|
||||
ID uint `json:"id"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
Name string `json:"name"`
|
||||
From string `json:"from"`
|
||||
Description string `json:"description"`
|
||||
Content string `json:"content"`
|
||||
}
|
10
backend/app/model/compose_template.go
Normal file
10
backend/app/model/compose_template.go
Normal file
@ -0,0 +1,10 @@
|
||||
package model
|
||||
|
||||
type ComposeTemplate struct {
|
||||
BaseModel
|
||||
|
||||
Name string `gorm:"type:varchar(64);not null;unique" json:"name"`
|
||||
From string `gorm:"type:varchar(64);not null" json:"from"`
|
||||
Description string `gorm:"type:varchar(256);" json:"description"`
|
||||
Content string `gorm:"type:longtext" json:"content"`
|
||||
}
|
69
backend/app/repo/compose_template.go
Normal file
69
backend/app/repo/compose_template.go
Normal file
@ -0,0 +1,69 @@
|
||||
package repo
|
||||
|
||||
import (
|
||||
"github.com/1Panel-dev/1Panel/app/model"
|
||||
"github.com/1Panel-dev/1Panel/global"
|
||||
)
|
||||
|
||||
type ComposeTemplateRepo struct{}
|
||||
|
||||
type IComposeTemplateRepo interface {
|
||||
Get(opts ...DBOption) (model.ComposeTemplate, error)
|
||||
List(opts ...DBOption) ([]model.ComposeTemplate, error)
|
||||
Page(limit, offset int, opts ...DBOption) (int64, []model.ComposeTemplate, error)
|
||||
Create(compose *model.ComposeTemplate) error
|
||||
Update(id uint, vars map[string]interface{}) error
|
||||
Delete(opts ...DBOption) error
|
||||
}
|
||||
|
||||
func NewIComposeTemplateRepo() IComposeTemplateRepo {
|
||||
return &ComposeTemplateRepo{}
|
||||
}
|
||||
|
||||
func (u *ComposeTemplateRepo) Get(opts ...DBOption) (model.ComposeTemplate, error) {
|
||||
var compose model.ComposeTemplate
|
||||
db := global.DB
|
||||
for _, opt := range opts {
|
||||
db = opt(db)
|
||||
}
|
||||
err := db.First(&compose).Error
|
||||
return compose, err
|
||||
}
|
||||
|
||||
func (u *ComposeTemplateRepo) Page(page, size int, opts ...DBOption) (int64, []model.ComposeTemplate, error) {
|
||||
var users []model.ComposeTemplate
|
||||
db := global.DB.Model(&model.ComposeTemplate{})
|
||||
for _, opt := range opts {
|
||||
db = opt(db)
|
||||
}
|
||||
count := int64(0)
|
||||
db = db.Count(&count)
|
||||
err := db.Limit(size).Offset(size * (page - 1)).Find(&users).Error
|
||||
return count, users, err
|
||||
}
|
||||
|
||||
func (u *ComposeTemplateRepo) List(opts ...DBOption) ([]model.ComposeTemplate, error) {
|
||||
var composes []model.ComposeTemplate
|
||||
db := global.DB.Model(&model.ComposeTemplate{})
|
||||
for _, opt := range opts {
|
||||
db = opt(db)
|
||||
}
|
||||
err := db.Find(&composes).Error
|
||||
return composes, err
|
||||
}
|
||||
|
||||
func (u *ComposeTemplateRepo) Create(compose *model.ComposeTemplate) error {
|
||||
return global.DB.Create(compose).Error
|
||||
}
|
||||
|
||||
func (u *ComposeTemplateRepo) Update(id uint, vars map[string]interface{}) error {
|
||||
return global.DB.Model(&model.ComposeTemplate{}).Where("id = ?", id).Updates(vars).Error
|
||||
}
|
||||
|
||||
func (u *ComposeTemplateRepo) Delete(opts ...DBOption) error {
|
||||
db := global.DB
|
||||
for _, opt := range opts {
|
||||
db = opt(db)
|
||||
}
|
||||
return db.Delete(&model.ComposeTemplate{}).Error
|
||||
}
|
@ -5,6 +5,7 @@ type RepoGroup struct {
|
||||
BackupRepo
|
||||
GroupRepo
|
||||
ImageRepoRepo
|
||||
ComposeTemplateRepo
|
||||
CommandRepo
|
||||
OperationRepo
|
||||
CommonRepo
|
||||
|
80
backend/app/service/compose_template.go
Normal file
80
backend/app/service/compose_template.go
Normal file
@ -0,0 +1,80 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"github.com/1Panel-dev/1Panel/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/constant"
|
||||
"github.com/jinzhu/copier"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type ComposeTemplateService struct{}
|
||||
|
||||
type IComposeTemplateService interface {
|
||||
List() ([]dto.ComposeTemplateInfo, error)
|
||||
SearchWithPage(search dto.PageInfo) (int64, interface{}, error)
|
||||
Create(composeDto dto.ComposeTemplateCreate) error
|
||||
Update(id uint, upMap map[string]interface{}) error
|
||||
Delete(ids []uint) error
|
||||
}
|
||||
|
||||
func NewIComposeTemplateService() IComposeTemplateService {
|
||||
return &ComposeTemplateService{}
|
||||
}
|
||||
|
||||
func (u *ComposeTemplateService) List() ([]dto.ComposeTemplateInfo, error) {
|
||||
composes, err := composeRepo.List()
|
||||
if err != nil {
|
||||
return nil, constant.ErrRecordNotFound
|
||||
}
|
||||
var dtoLists []dto.ComposeTemplateInfo
|
||||
for _, compose := range composes {
|
||||
var item dto.ComposeTemplateInfo
|
||||
if err := copier.Copy(&item, &compose); err != nil {
|
||||
return nil, errors.WithMessage(constant.ErrStructTransform, err.Error())
|
||||
}
|
||||
dtoLists = append(dtoLists, item)
|
||||
}
|
||||
return dtoLists, err
|
||||
}
|
||||
|
||||
func (u *ComposeTemplateService) SearchWithPage(search dto.PageInfo) (int64, interface{}, error) {
|
||||
total, composes, err := composeRepo.Page(search.Page, search.PageSize)
|
||||
var dtoComposeTemplates []dto.ComposeTemplateInfo
|
||||
for _, compose := range composes {
|
||||
var item dto.ComposeTemplateInfo
|
||||
if err := copier.Copy(&item, &compose); err != nil {
|
||||
return 0, nil, errors.WithMessage(constant.ErrStructTransform, err.Error())
|
||||
}
|
||||
dtoComposeTemplates = append(dtoComposeTemplates, item)
|
||||
}
|
||||
return total, dtoComposeTemplates, err
|
||||
}
|
||||
|
||||
func (u *ComposeTemplateService) Create(composeDto dto.ComposeTemplateCreate) error {
|
||||
compose, _ := composeRepo.Get(commonRepo.WithByName(composeDto.Name))
|
||||
if compose.ID != 0 {
|
||||
return constant.ErrRecordExist
|
||||
}
|
||||
if err := copier.Copy(&compose, &composeDto); err != nil {
|
||||
return errors.WithMessage(constant.ErrStructTransform, err.Error())
|
||||
}
|
||||
if err := composeRepo.Create(&compose); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *ComposeTemplateService) Delete(ids []uint) error {
|
||||
if len(ids) == 1 {
|
||||
compose, _ := composeRepo.Get(commonRepo.WithByID(ids[0]))
|
||||
if compose.ID == 0 {
|
||||
return constant.ErrRecordNotFound
|
||||
}
|
||||
return composeRepo.Delete(commonRepo.WithByID(ids[0]))
|
||||
}
|
||||
return composeRepo.Delete(commonRepo.WithIdsIn(ids))
|
||||
}
|
||||
|
||||
func (u *ComposeTemplateService) Update(id uint, upMap map[string]interface{}) error {
|
||||
return composeRepo.Update(id, upMap)
|
||||
}
|
@ -8,6 +8,7 @@ type ServiceGroup struct {
|
||||
BackupService
|
||||
GroupService
|
||||
ImageService
|
||||
ComposeTemplateService
|
||||
ImageRepoService
|
||||
ContainerService
|
||||
CommandService
|
||||
@ -28,6 +29,7 @@ var (
|
||||
operationRepo = repo.RepoGroupApp.OperationRepo
|
||||
commonRepo = repo.RepoGroupApp.CommonRepo
|
||||
imageRepoRepo = repo.RepoGroupApp.ImageRepoRepo
|
||||
composeRepo = repo.RepoGroupApp.ComposeTemplateRepo
|
||||
cronjobRepo = repo.RepoGroupApp.CronjobRepo
|
||||
settingRepo = repo.RepoGroupApp.SettingRepo
|
||||
appRepo = repo.RepoGroupApp.AppRepo
|
||||
@ -36,6 +38,7 @@ var (
|
||||
tagRepo = repo.RepoGroupApp.TagRepo
|
||||
appInstallRepo = repo.RepoGroupApp.AppInstallRepo
|
||||
appInstallResourceRepo = repo.RepoGroupApp.AppInstallResourceRpo
|
||||
appContainerRepo = repo.RepoGroupApp.AppContainerRepo
|
||||
dataBaseRepo = repo.RepoGroupApp.DatabaseRepo
|
||||
appInstallBackupRepo = repo.RepoGroupApp.AppInstallBackupRepo
|
||||
)
|
||||
|
@ -157,7 +157,7 @@ var AddTableApp = &gormigrate.Migration{
|
||||
var AddTableImageRepo = &gormigrate.Migration{
|
||||
ID: "20201009-add-table-imagerepo",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
if err := tx.AutoMigrate(&model.ImageRepo{}); err != nil {
|
||||
if err := tx.AutoMigrate(&model.ImageRepo{}, &model.ComposeTemplate{}); err != nil {
|
||||
return err
|
||||
}
|
||||
item := &model.ImageRepo{
|
||||
|
@ -33,6 +33,12 @@ func (s *ContainerRouter) InitContainerRouter(Router *gin.RouterGroup) {
|
||||
withRecordRouter.POST("/repo", baseApi.CreateRepo)
|
||||
withRecordRouter.POST("/repo/del", baseApi.DeleteRepo)
|
||||
|
||||
baRouter.POST("/compose/search", baseApi.SearchComposeTemplate)
|
||||
baRouter.PUT("/compose/:id", baseApi.UpdateComposeTemplate)
|
||||
baRouter.GET("/compose", baseApi.ListComposeTemplate)
|
||||
withRecordRouter.POST("/compose", baseApi.CreateComposeTemplate)
|
||||
withRecordRouter.POST("/compose/del", baseApi.DeleteComposeTemplate)
|
||||
|
||||
baRouter.POST("/image/search", baseApi.SearchImage)
|
||||
baRouter.GET("/image", baseApi.ListImage)
|
||||
baRouter.POST("/image/pull", baseApi.ImagePull)
|
||||
|
@ -161,6 +161,27 @@ export namespace Container {
|
||||
downloadUrl: string;
|
||||
}
|
||||
|
||||
export interface TemplateCreate {
|
||||
name: string;
|
||||
from: string;
|
||||
description: string;
|
||||
content: string;
|
||||
}
|
||||
export interface TemplateUpdate {
|
||||
id: number;
|
||||
from: string;
|
||||
description: string;
|
||||
content: string;
|
||||
}
|
||||
export interface TemplateInfo {
|
||||
id: number;
|
||||
createdAt: Date;
|
||||
name: string;
|
||||
from: string;
|
||||
description: string;
|
||||
content: string;
|
||||
}
|
||||
|
||||
export interface BatchDelete {
|
||||
ids: Array<string>;
|
||||
}
|
||||
|
@ -2,33 +2,30 @@ import http from '@/api';
|
||||
import { ResPage, ReqPage } from '../interface';
|
||||
import { Container } from '../interface/container';
|
||||
|
||||
export const getContainerPage = (params: ReqPage) => {
|
||||
export const searchContainer = (params: ReqPage) => {
|
||||
return http.post<ResPage<Container.ContainerInfo>>(`/containers/search`, params);
|
||||
};
|
||||
export const createContainer = (params: Container.ContainerCreate) => {
|
||||
return http.post(`/containers`, params);
|
||||
};
|
||||
|
||||
export const getContainerLog = (params: Container.ContainerLogSearch) => {
|
||||
export const logContainer = (params: Container.ContainerLogSearch) => {
|
||||
return http.post<string>(`/containers/log`, params);
|
||||
};
|
||||
export const ContainerStats = (id: string) => {
|
||||
return http.get<Container.ContainerStats>(`/containers/stats/${id}`);
|
||||
};
|
||||
|
||||
export const ContainerOperator = (params: Container.ContainerOperate) => {
|
||||
return http.post(`/containers/operate`, params);
|
||||
};
|
||||
|
||||
export const inspect = (params: Container.ContainerInspect) => {
|
||||
return http.post<string>(`/containers/inspect`, params);
|
||||
};
|
||||
|
||||
// image
|
||||
export const getImagePage = (params: ReqPage) => {
|
||||
export const searchImage = (params: ReqPage) => {
|
||||
return http.post<ResPage<Container.ImageInfo>>(`/containers/image/search`, params);
|
||||
};
|
||||
export const imageOptions = () => {
|
||||
export const listImage = () => {
|
||||
return http.get<Array<Container.Options>>(`/containers/image`);
|
||||
};
|
||||
export const imageBuild = (params: Container.ImageBuild) => {
|
||||
@ -54,7 +51,7 @@ export const imageRemove = (params: Container.BatchDelete) => {
|
||||
};
|
||||
|
||||
// network
|
||||
export const getNetworkPage = (params: ReqPage) => {
|
||||
export const searchNetwork = (params: ReqPage) => {
|
||||
return http.post<ResPage<Container.NetworkInfo>>(`/containers/network/search`, params);
|
||||
};
|
||||
export const deleteNetwork = (params: Container.BatchDelete) => {
|
||||
@ -65,10 +62,10 @@ export const createNetwork = (params: Container.NetworkCreate) => {
|
||||
};
|
||||
|
||||
// volume
|
||||
export const getVolumePage = (params: ReqPage) => {
|
||||
export const searchVolume = (params: ReqPage) => {
|
||||
return http.post<ResPage<Container.VolumeInfo>>(`/containers/volume/search`, params);
|
||||
};
|
||||
export const volumeOptions = () => {
|
||||
export const listVolume = () => {
|
||||
return http.get<Array<Container.Options>>(`/containers/volume`);
|
||||
};
|
||||
export const deleteVolume = (params: Container.BatchDelete) => {
|
||||
@ -79,18 +76,35 @@ export const createVolume = (params: Container.VolumeCreate) => {
|
||||
};
|
||||
|
||||
// repo
|
||||
export const getRepoPage = (params: ReqPage) => {
|
||||
export const searchImageRepo = (params: ReqPage) => {
|
||||
return http.post<ResPage<Container.RepoInfo>>(`/containers/repo/search`, params);
|
||||
};
|
||||
export const getRepoOption = () => {
|
||||
export const listImageRepo = () => {
|
||||
return http.get<Container.RepoOptions>(`/containers/repo`);
|
||||
};
|
||||
export const repoCreate = (params: Container.RepoCreate) => {
|
||||
export const createImageRepo = (params: Container.RepoCreate) => {
|
||||
return http.post(`/containers/repo`, params);
|
||||
};
|
||||
export const repoUpdate = (params: Container.RepoUpdate) => {
|
||||
export const updateImageRepo = (params: Container.RepoUpdate) => {
|
||||
return http.put(`/containers/repo/${params.id}`, params);
|
||||
};
|
||||
export const deleteRepo = (params: { ids: number[] }) => {
|
||||
export const deleteImageRepo = (params: { ids: number[] }) => {
|
||||
return http.post(`/containers/repo/del`, params);
|
||||
};
|
||||
|
||||
// composeTemplate
|
||||
export const searchComposeTemplate = (params: ReqPage) => {
|
||||
return http.post<ResPage<Container.TemplateInfo>>(`/containers/compose/search`, params);
|
||||
};
|
||||
export const listComposeTemplate = (params: ReqPage) => {
|
||||
return http.post<ResPage<Container.TemplateInfo>>(`/containers/compose/search`, params);
|
||||
};
|
||||
export const deleteComposeTemplate = (params: { ids: number[] }) => {
|
||||
return http.post(`/containers/compose/del`, params);
|
||||
};
|
||||
export const createComposeTemplate = (params: Container.TemplateCreate) => {
|
||||
return http.post(`/containers/compose`, params);
|
||||
};
|
||||
export const updateComposeTemplate = (params: Container.TemplateUpdate) => {
|
||||
return http.put(`/containers/compose/${params.id}`, params);
|
||||
};
|
||||
|
@ -93,6 +93,7 @@ export default {
|
||||
number: 'Please enter the correct number',
|
||||
ip: 'Please enter the correct IP address',
|
||||
port: 'Please enter the correct port',
|
||||
selectHelper: 'Please select the correct {0} file',
|
||||
},
|
||||
res: {
|
||||
paramError: 'The request failed, please try again later!',
|
||||
@ -161,7 +162,6 @@ export default {
|
||||
reName: 'ReName',
|
||||
remove: 'Remove',
|
||||
container: 'Container',
|
||||
schedule: 'Schedule',
|
||||
upTime: 'UpTime',
|
||||
all: 'All',
|
||||
lastDay: 'Last Day',
|
||||
@ -242,6 +242,11 @@ export default {
|
||||
imageRepo: 'Image repo',
|
||||
repoHelper: 'Does it include a mirror repository/organization/project?',
|
||||
auth: 'Auth',
|
||||
|
||||
compose: 'Compose',
|
||||
composeTemplate: 'Compose template',
|
||||
description: 'Description',
|
||||
content: 'Content',
|
||||
},
|
||||
cronjob: {
|
||||
cronTask: 'Task',
|
||||
|
@ -2,6 +2,7 @@ export default {
|
||||
commons: {
|
||||
true: '是',
|
||||
false: '否',
|
||||
example: '例如:',
|
||||
button: {
|
||||
create: '新建',
|
||||
add: '添加',
|
||||
@ -90,6 +91,7 @@ export default {
|
||||
number: '请输入正确的数字',
|
||||
ip: '请输入正确的 IP 地址',
|
||||
port: '请输入正确的端口',
|
||||
selectHelper: '请选择正确的 {0} 文件',
|
||||
},
|
||||
res: {
|
||||
paramError: '请求失败,请稍后重试!',
|
||||
@ -158,7 +160,6 @@ export default {
|
||||
reName: '重命名',
|
||||
remove: '移除',
|
||||
container: '容器',
|
||||
schedule: '编排',
|
||||
upTime: '运行时长',
|
||||
all: '全部',
|
||||
lastDay: '最近一天',
|
||||
@ -242,6 +243,11 @@ export default {
|
||||
imageRepo: '镜像仓库',
|
||||
repoHelper: '是否包含镜像仓库/组织/项目?',
|
||||
auth: '认证',
|
||||
|
||||
compose: '编排',
|
||||
composeTemplate: '编排模版',
|
||||
description: '描述',
|
||||
content: '内容',
|
||||
},
|
||||
cronjob: {
|
||||
cronTask: '计划任务',
|
||||
|
169
frontend/src/views/container/compose/template/index.vue
Normal file
169
frontend/src/views/container/compose/template/index.vue
Normal file
@ -0,0 +1,169 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-card style="margin-top: 20px">
|
||||
<ComplexTable :pagination-config="paginationConfig" v-model:selects="selects" :data="data" @search="search">
|
||||
<template #toolbar>
|
||||
<el-button type="primary" @click="onOpenDialog('create')">
|
||||
{{ $t('commons.button.create') }}
|
||||
</el-button>
|
||||
<el-button type="danger" plain :disabled="selects.length === 0" @click="onBatchDelete(null)">
|
||||
{{ $t('commons.button.delete') }}
|
||||
</el-button>
|
||||
</template>
|
||||
<el-table-column type="selection" fix></el-table-column>
|
||||
<el-table-column
|
||||
:label="$t('commons.table.name')"
|
||||
show-overflow-tooltip
|
||||
min-width="100"
|
||||
prop="name"
|
||||
fix
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-link @click="onOpenDetail(row)" type="primary">{{ row.name }}</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('container.description')" prop="description" min-width="200" fix />
|
||||
<el-table-column :label="$t('commons.table.createdAt')" min-width="80" fix>
|
||||
<template #default="{ row }">
|
||||
{{ dateFromat(0, 0, row.createdAt) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<fu-table-operations :buttons="buttons" :label="$t('commons.table.operate')" />
|
||||
</ComplexTable>
|
||||
</el-card>
|
||||
|
||||
<el-dialog v-model="detailVisiable" :destroy-on-close="true" :close-on-click-modal="false" width="70%">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>{{ $t('commons.button.view') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<codemirror
|
||||
:autofocus="true"
|
||||
placeholder="None data"
|
||||
:indent-with-tab="true"
|
||||
:tabSize="4"
|
||||
style="max-height: 500px"
|
||||
:lineWrapping="true"
|
||||
:matchBrackets="true"
|
||||
theme="cobalt"
|
||||
:styleActiveLine="true"
|
||||
:extensions="extensions"
|
||||
v-model="detailInfo"
|
||||
:readOnly="true"
|
||||
/>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="detailVisiable = false">{{ $t('commons.button.cancel') }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<OperatorDialog @search="search" ref="dialogRef" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import ComplexTable from '@/components/complex-table/index.vue';
|
||||
import { Codemirror } from 'vue-codemirror';
|
||||
import { javascript } from '@codemirror/lang-javascript';
|
||||
import { oneDark } from '@codemirror/theme-one-dark';
|
||||
import { reactive, onMounted, ref } from 'vue';
|
||||
import { dateFromat } from '@/utils/util';
|
||||
import { Container } from '@/api/interface/container';
|
||||
import OperatorDialog from '@/views/container/compose/template/operator/index.vue';
|
||||
import { deleteComposeTemplate, searchComposeTemplate } from '@/api/modules/container';
|
||||
import { useDeleteData } from '@/hooks/use-delete-data';
|
||||
import i18n from '@/lang';
|
||||
import { LoadFile } from '@/api/modules/files';
|
||||
|
||||
const data = ref();
|
||||
const selects = ref<any>([]);
|
||||
const detailVisiable = ref(false);
|
||||
const detailInfo = ref();
|
||||
const extensions = [javascript(), oneDark];
|
||||
|
||||
const paginationConfig = reactive({
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
});
|
||||
|
||||
const search = async () => {
|
||||
let params = {
|
||||
page: paginationConfig.page,
|
||||
pageSize: paginationConfig.pageSize,
|
||||
};
|
||||
await searchComposeTemplate(params).then((res) => {
|
||||
if (res.data) {
|
||||
data.value = res.data.items;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const onOpenDetail = async (row: Container.TemplateInfo) => {
|
||||
if (row.from === 'edit') {
|
||||
detailInfo.value = row.content;
|
||||
detailVisiable.value = true;
|
||||
} else {
|
||||
const res = await LoadFile({ path: row.content });
|
||||
detailInfo.value = res.data;
|
||||
detailVisiable.value = true;
|
||||
}
|
||||
};
|
||||
|
||||
const dialogRef = ref();
|
||||
const onOpenDialog = async (
|
||||
title: string,
|
||||
rowData: Partial<Container.TemplateInfo> = {
|
||||
name: '',
|
||||
from: 'edit',
|
||||
description: '',
|
||||
content: '',
|
||||
},
|
||||
) => {
|
||||
let params = {
|
||||
title,
|
||||
rowData: { ...rowData },
|
||||
};
|
||||
dialogRef.value!.acceptParams(params);
|
||||
};
|
||||
|
||||
const onBatchDelete = async (row: Container.RepoInfo | null) => {
|
||||
let ids: Array<number> = [];
|
||||
if (row) {
|
||||
ids.push(row.id);
|
||||
} else {
|
||||
selects.value.forEach((item: Container.RepoInfo) => {
|
||||
ids.push(item.id);
|
||||
});
|
||||
}
|
||||
await useDeleteData(deleteComposeTemplate, { ids: ids }, 'commons.msg.delete', true);
|
||||
search();
|
||||
};
|
||||
|
||||
const buttons = [
|
||||
{
|
||||
label: i18n.global.t('commons.button.edit'),
|
||||
disabled: (row: Container.RepoInfo) => {
|
||||
return row.downloadUrl === 'docker.io';
|
||||
},
|
||||
click: (row: Container.RepoInfo) => {
|
||||
onOpenDialog('edit', row);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: i18n.global.t('commons.button.delete'),
|
||||
disabled: (row: Container.RepoInfo) => {
|
||||
return row.downloadUrl === 'docker.io';
|
||||
},
|
||||
click: (row: Container.RepoInfo) => {
|
||||
onBatchDelete(row);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
onMounted(() => {
|
||||
search();
|
||||
});
|
||||
</script>
|
133
frontend/src/views/container/compose/template/operator/index.vue
Normal file
133
frontend/src/views/container/compose/template/operator/index.vue
Normal file
@ -0,0 +1,133 @@
|
||||
<template>
|
||||
<el-dialog v-model="templateVisiable" :destroy-on-close="true" :close-on-click-modal="false" width="50%">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>{{ title }}{{ $t('container.composeTemplate') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-form ref="formRef" :model="dialogData.rowData" :rules="rules" label-width="80px">
|
||||
<el-form-item :label="$t('container.name')" prop="name">
|
||||
<el-input :disabled="dialogData.title === 'edit'" v-model="dialogData.rowData!.name"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('container.description')">
|
||||
<el-input v-model="dialogData.rowData!.description"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('container.from')">
|
||||
<el-radio-group v-model="dialogData.rowData!.from">
|
||||
<el-radio label="edit">{{ $t('container.edit') }}</el-radio>
|
||||
<el-radio label="path">{{ $t('container.pathSelect') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="dialogData.rowData!.from === 'path'" :rules="Rules.requiredSelect" prop="content">
|
||||
<el-input
|
||||
clearable
|
||||
:placeholder="$t('commons.example') + '/tmp/docker-compose.yml'"
|
||||
v-model="dialogData.rowData!.content"
|
||||
>
|
||||
<template #append>
|
||||
<FileList @choose="loadDir" :dir="false"></FileList>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="dialogData.rowData!.from === 'edit'">
|
||||
<codemirror
|
||||
:autofocus="true"
|
||||
placeholder="None data"
|
||||
:indent-with-tab="true"
|
||||
:tabSize="4"
|
||||
style="max-height: 500px; width: 100%"
|
||||
:lineWrapping="true"
|
||||
:matchBrackets="true"
|
||||
theme="cobalt"
|
||||
:styleActiveLine="true"
|
||||
:extensions="extensions"
|
||||
v-model="dialogData.rowData!.content"
|
||||
:readOnly="true"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="templateVisiable = false">{{ $t('commons.button.cancel') }}</el-button>
|
||||
<el-button type="primary" @click="onSubmit(formRef)">
|
||||
{{ $t('commons.button.confirm') }}
|
||||
</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref } from 'vue';
|
||||
import FileList from '@/components/file-list/index.vue';
|
||||
import { Codemirror } from 'vue-codemirror';
|
||||
import { javascript } from '@codemirror/lang-javascript';
|
||||
import { oneDark } from '@codemirror/theme-one-dark';
|
||||
import { Rules } from '@/global/form-rules';
|
||||
import i18n from '@/lang';
|
||||
import { ElForm, ElMessage } from 'element-plus';
|
||||
import { Container } from '@/api/interface/container';
|
||||
import { createComposeTemplate, updateComposeTemplate } from '@/api/modules/container';
|
||||
|
||||
interface DialogProps {
|
||||
title: string;
|
||||
rowData?: Container.TemplateInfo;
|
||||
getTableList?: () => Promise<any>;
|
||||
}
|
||||
const extensions = [javascript(), oneDark];
|
||||
const title = ref<string>('');
|
||||
const templateVisiable = ref(false);
|
||||
const dialogData = ref<DialogProps>({
|
||||
title: '',
|
||||
});
|
||||
const acceptParams = (params: DialogProps): void => {
|
||||
dialogData.value = params;
|
||||
title.value = i18n.global.t('commons.button.' + dialogData.value.title);
|
||||
templateVisiable.value = true;
|
||||
};
|
||||
const emit = defineEmits<{ (e: 'search'): void }>();
|
||||
|
||||
const varifyPath = (rule: any, value: any, callback: any) => {
|
||||
if (value.indexOf('docker-compose.yml') === -1) {
|
||||
callback(new Error(i18n.global.t('commons.rule.selectHelper', ['.docker-compose.yml'])));
|
||||
}
|
||||
callback();
|
||||
};
|
||||
const rules = reactive({
|
||||
name: [Rules.requiredInput, Rules.name],
|
||||
content: [Rules.requiredInput, { validator: varifyPath, trigger: 'change', required: true }],
|
||||
});
|
||||
|
||||
type FormInstance = InstanceType<typeof ElForm>;
|
||||
const formRef = ref<FormInstance>();
|
||||
|
||||
function restForm() {
|
||||
if (formRef.value) {
|
||||
formRef.value.resetFields();
|
||||
}
|
||||
}
|
||||
const onSubmit = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return;
|
||||
formEl.validate(async (valid) => {
|
||||
if (!valid) return;
|
||||
if (dialogData.value.title === 'create') {
|
||||
await createComposeTemplate(dialogData.value.rowData!);
|
||||
}
|
||||
if (dialogData.value.title === 'edit') {
|
||||
await updateComposeTemplate(dialogData.value.rowData!);
|
||||
}
|
||||
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
|
||||
restForm();
|
||||
emit('search');
|
||||
templateVisiable.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
const loadDir = async (path: string) => {
|
||||
dialogData.value.rowData!.content = path;
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
acceptParams,
|
||||
});
|
||||
</script>
|
@ -189,7 +189,7 @@ import { reactive, ref } from 'vue';
|
||||
import { Rules } from '@/global/form-rules';
|
||||
import i18n from '@/lang';
|
||||
import { ElForm, ElMessage } from 'element-plus';
|
||||
import { imageOptions, volumeOptions, createContainer } from '@/api/modules/container';
|
||||
import { listImage, listVolume, createContainer } from '@/api/modules/container';
|
||||
import { Container } from '@/api/interface/container';
|
||||
|
||||
const createVisiable = ref(false);
|
||||
@ -259,11 +259,11 @@ const handleVolumesDelete = (index: number) => {
|
||||
};
|
||||
|
||||
const loadImageOptions = async () => {
|
||||
const res = await imageOptions();
|
||||
const res = await listImage();
|
||||
images.value = res.data;
|
||||
};
|
||||
const loadVolumeOptions = async () => {
|
||||
const res = await volumeOptions();
|
||||
const res = await listVolume();
|
||||
volumes.value = res.data;
|
||||
};
|
||||
const onSubmit = async (formEl: FormInstance | undefined) => {
|
||||
|
@ -171,7 +171,7 @@ import { oneDark } from '@codemirror/theme-one-dark';
|
||||
import { reactive, onMounted, ref } from 'vue';
|
||||
import { dateFromat, dateFromatForName } from '@/utils/util';
|
||||
import { Rules } from '@/global/form-rules';
|
||||
import { ContainerOperator, inspect, getContainerLog, getContainerPage } from '@/api/modules/container';
|
||||
import { ContainerOperator, inspect, logContainer, searchContainer } from '@/api/modules/container';
|
||||
import { Container } from '@/api/interface/container';
|
||||
import { ElForm, ElMessage, ElMessageBox, FormInstance } from 'element-plus';
|
||||
import i18n from '@/lang';
|
||||
@ -234,7 +234,7 @@ const timeOptions = ref([
|
||||
const search = async () => {
|
||||
containerSearch.page = paginationConfig.page;
|
||||
containerSearch.pageSize = paginationConfig.pageSize;
|
||||
await getContainerPage(containerSearch).then((res) => {
|
||||
await searchContainer(containerSearch).then((res) => {
|
||||
if (res.data) {
|
||||
data.value = res.data.items;
|
||||
}
|
||||
@ -272,7 +272,7 @@ const onCloseLog = async () => {
|
||||
clearInterval(Number(timer));
|
||||
};
|
||||
const searchLogs = async () => {
|
||||
const res = await getContainerLog(logSearch);
|
||||
const res = await logContainer(logSearch);
|
||||
logInfo.value = res.data;
|
||||
};
|
||||
const onDownload = async () => {
|
||||
|
@ -93,6 +93,16 @@ const form = reactive({
|
||||
tagStr: '',
|
||||
tags: [] as Array<string>,
|
||||
});
|
||||
const varifyPath = (rule: any, value: any, callback: any) => {
|
||||
if (value.indexOf('docker-compose.yml') === -1) {
|
||||
callback(new Error(i18n.global.t('commons.rule.selectHelper', ['Dockerfile'])));
|
||||
}
|
||||
callback();
|
||||
};
|
||||
const rules = reactive({
|
||||
name: [Rules.requiredInput, Rules.name],
|
||||
content: [Rules.requiredInput, { validator: varifyPath, trigger: 'change', required: true }],
|
||||
});
|
||||
const acceptParams = async () => {
|
||||
buildVisiable.value = true;
|
||||
form.from = 'path';
|
||||
|
@ -78,7 +78,7 @@ import Push from '@/views/container/image/push/index.vue';
|
||||
import Save from '@/views/container/image/save/index.vue';
|
||||
import Load from '@/views/container/image/load/index.vue';
|
||||
import Build from '@/views/container/image/build/index.vue';
|
||||
import { getImagePage, getRepoOption, imageRemove } from '@/api/modules/container';
|
||||
import { searchImage, listImageRepo, imageRemove } from '@/api/modules/container';
|
||||
import i18n from '@/lang';
|
||||
import { ElForm } from 'element-plus';
|
||||
import { useDeleteData } from '@/hooks/use-delete-data';
|
||||
@ -112,7 +112,7 @@ const search = async () => {
|
||||
page: paginationConfig.page,
|
||||
pageSize: paginationConfig.pageSize,
|
||||
};
|
||||
await getImagePage(repoSearch).then((res) => {
|
||||
await searchImage(repoSearch).then((res) => {
|
||||
if (res.data) {
|
||||
data.value = res.data.items;
|
||||
}
|
||||
@ -120,7 +120,7 @@ const search = async () => {
|
||||
});
|
||||
};
|
||||
const loadRepos = async () => {
|
||||
const res = await getRepoOption();
|
||||
const res = await listImageRepo();
|
||||
repos.value = res.data;
|
||||
};
|
||||
|
||||
|
@ -17,8 +17,11 @@
|
||||
<el-radio-button class="topButton" size="large" label="repo">
|
||||
{{ $t('container.repo') }}
|
||||
</el-radio-button>
|
||||
<el-radio-button class="topButton" size="large" label="schedule">
|
||||
{{ $t('container.schedule') }}
|
||||
<el-radio-button class="topButton" size="large" label="compose">
|
||||
{{ $t('container.compose') }}
|
||||
</el-radio-button>
|
||||
<el-radio-button class="topButton" size="large" label="composeTemplate">
|
||||
{{ $t('container.composeTemplate') }}
|
||||
</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-card>
|
||||
@ -27,7 +30,7 @@
|
||||
<Image v-if="activeNames === 'image'" />
|
||||
<Network v-if="activeNames === 'network'" />
|
||||
<Volume v-if="activeNames === 'volume'" />
|
||||
<About v-if="activeNames === 'schedule'" />
|
||||
<ComposeTemplate v-if="activeNames === 'composeTemplate'" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -38,7 +41,7 @@ import Repo from '@/views/container/repo/index.vue';
|
||||
import Image from '@/views/container/image/index.vue';
|
||||
import Network from '@/views/container/network/index.vue';
|
||||
import Volume from '@/views/container/volume/index.vue';
|
||||
import About from '@/views/setting/tabs/about.vue';
|
||||
import ComposeTemplate from '@/views/container/compose/template/index.vue';
|
||||
|
||||
const activeNames = ref('container');
|
||||
</script>
|
||||
|
@ -83,7 +83,7 @@ import { javascript } from '@codemirror/lang-javascript';
|
||||
import { oneDark } from '@codemirror/theme-one-dark';
|
||||
import { reactive, onMounted, ref } from 'vue';
|
||||
import { dateFromat } from '@/utils/util';
|
||||
import { deleteNetwork, getNetworkPage, inspect } from '@/api/modules/container';
|
||||
import { deleteNetwork, searchNetwork, inspect } from '@/api/modules/container';
|
||||
import { Container } from '@/api/interface/container';
|
||||
import i18n from '@/lang';
|
||||
import { useDeleteData } from '@/hooks/use-delete-data';
|
||||
@ -114,7 +114,7 @@ const search = async () => {
|
||||
page: paginationConfig.page,
|
||||
pageSize: paginationConfig.pageSize,
|
||||
};
|
||||
await getNetworkPage(params).then((res) => {
|
||||
await searchNetwork(params).then((res) => {
|
||||
if (res.data) {
|
||||
data.value = res.data.items;
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ import OperatorDialog from '@/views/container/repo/operator/index.vue';
|
||||
import { reactive, onMounted, ref } from 'vue';
|
||||
import { dateFromat } from '@/utils/util';
|
||||
import { Container } from '@/api/interface/container';
|
||||
import { deleteRepo, getRepoPage } from '@/api/modules/container';
|
||||
import { deleteImageRepo, searchImageRepo } from '@/api/modules/container';
|
||||
import { useDeleteData } from '@/hooks/use-delete-data';
|
||||
import i18n from '@/lang';
|
||||
|
||||
@ -49,25 +49,20 @@ const paginationConfig = reactive({
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
});
|
||||
const repoSearch = reactive({
|
||||
page: 1,
|
||||
pageSize: 5,
|
||||
});
|
||||
|
||||
const search = async () => {
|
||||
repoSearch.page = paginationConfig.page;
|
||||
repoSearch.pageSize = paginationConfig.pageSize;
|
||||
await getRepoPage(repoSearch).then((res) => {
|
||||
let params = {
|
||||
page: paginationConfig.page,
|
||||
pageSize: paginationConfig.pageSize,
|
||||
};
|
||||
await searchImageRepo(params).then((res) => {
|
||||
if (res.data) {
|
||||
data.value = res.data.items;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
interface DialogExpose {
|
||||
acceptParams: (params: any) => void;
|
||||
}
|
||||
const dialogRef = ref<DialogExpose>();
|
||||
const dialogRef = ref();
|
||||
const onOpenDialog = async (
|
||||
title: string,
|
||||
rowData: Partial<Container.RepoInfo> = {
|
||||
@ -91,7 +86,7 @@ const onBatchDelete = async (row: Container.RepoInfo | null) => {
|
||||
ids.push(item.id);
|
||||
});
|
||||
}
|
||||
await useDeleteData(deleteRepo, { ids: ids }, 'commons.msg.delete', true);
|
||||
await useDeleteData(deleteImageRepo, { ids: ids }, 'commons.msg.delete', true);
|
||||
search();
|
||||
};
|
||||
|
||||
|
@ -48,7 +48,7 @@ import { Rules } from '@/global/form-rules';
|
||||
import i18n from '@/lang';
|
||||
import { ElForm, ElMessage } from 'element-plus';
|
||||
import { Container } from '@/api/interface/container';
|
||||
import { repoCreate, repoUpdate } from '@/api/modules/container';
|
||||
import { createImageRepo, updateImageRepo } from '@/api/modules/container';
|
||||
|
||||
interface DialogProps {
|
||||
title: string;
|
||||
@ -89,10 +89,10 @@ const onSubmit = async (formEl: FormInstance | undefined) => {
|
||||
formEl.validate(async (valid) => {
|
||||
if (!valid) return;
|
||||
if (dialogData.value.title === 'create') {
|
||||
await repoCreate(dialogData.value.rowData!);
|
||||
await createImageRepo(dialogData.value.rowData!);
|
||||
}
|
||||
if (dialogData.value.title === 'edit') {
|
||||
await repoUpdate(dialogData.value.rowData!);
|
||||
await updateImageRepo(dialogData.value.rowData!);
|
||||
}
|
||||
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
|
||||
restForm();
|
||||
|
@ -72,7 +72,7 @@ import { javascript } from '@codemirror/lang-javascript';
|
||||
import { oneDark } from '@codemirror/theme-one-dark';
|
||||
import { reactive, onMounted, ref } from 'vue';
|
||||
import { dateFromat } from '@/utils/util';
|
||||
import { deleteVolume, getVolumePage, inspect } from '@/api/modules/container';
|
||||
import { deleteVolume, searchVolume, inspect } from '@/api/modules/container';
|
||||
import { Container } from '@/api/interface/container';
|
||||
import i18n from '@/lang';
|
||||
import { useDeleteData } from '@/hooks/use-delete-data';
|
||||
@ -103,7 +103,7 @@ const search = async () => {
|
||||
page: paginationConfig.page,
|
||||
pageSize: paginationConfig.pageSize,
|
||||
};
|
||||
await getVolumePage(params).then((res) => {
|
||||
await searchVolume(params).then((res) => {
|
||||
if (res.data) {
|
||||
data.value = res.data.items;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user