feat: 容器、数据库、网站、计划任务增加名称排序 (#1490)

pull/1498/head
ssongliu 2023-06-29 18:40:12 +08:00 committed by GitHub
parent a1c76600e2
commit 38bf54ec3b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 115 additions and 38 deletions

View File

@ -2,7 +2,9 @@ package dto
type SearchWithPage struct {
PageInfo
Info string `json:"info"`
Info string `json:"info"`
OrderBy string `json:"orderBy"`
Order string `json:"order"`
}
type PageInfo struct {

View File

@ -5,6 +5,8 @@ import "time"
type PageContainer struct {
PageInfo
Name string `json:"name"`
OrderBy string `json:"orderBy"`
Order string `json:"order"`
Filters string `json:"filters"`
}

View File

@ -7,6 +7,8 @@ import (
type WebsiteSearch struct {
dto.PageInfo
Name string `json:"name"`
OrderBy string `json:"orderBy"`
Order string `json:"order"`
WebsiteGroupID uint `json:"websiteGroupId"`
}

View File

@ -2,6 +2,7 @@ package repo
import (
"context"
"fmt"
"time"
"github.com/1Panel-dev/1Panel/backend/constant"
@ -16,6 +17,7 @@ type ICommonRepo interface {
WithByName(name string) DBOption
WithByType(tp string) DBOption
WithOrderBy(orderStr string) DBOption
WithOrderRuleBy(orderBy, order string) DBOption
WithByGroupID(groupID uint) DBOption
WithLikeName(name string) DBOption
WithIdsIn(ids []uint) DBOption
@ -93,6 +95,21 @@ func (c *CommonRepo) WithOrderBy(orderStr string) DBOption {
}
}
func (c *CommonRepo) WithOrderRuleBy(orderBy, order string) DBOption {
switch order {
case constant.OrderDesc:
order = "desc"
case constant.OrderAsc:
order = "asc"
default:
orderBy = "created_at"
order = "desc"
}
return func(g *gorm.DB) *gorm.DB {
return g.Order(fmt.Sprintf("%s %s", orderBy, order))
}
}
func (c *CommonRepo) WithIdsIn(ids []uint) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("id in (?)", ids)

View File

@ -83,7 +83,7 @@ func (u *CronjobRepo) Page(page, size int, opts ...DBOption) (int64, []model.Cro
}
count := int64(0)
db = db.Count(&count)
err := db.Order("created_at desc").Limit(size).Offset(size * (page - 1)).Find(&cronjobs).Error
err := db.Limit(size).Offset(size * (page - 1)).Find(&cronjobs).Error
return count, cronjobs, err
}

View File

@ -67,9 +67,8 @@ func NewIContainerService() IContainerService {
func (u *ContainerService) Page(req dto.PageContainer) (int64, interface{}, error) {
var (
records []types.Container
list []types.Container
backDatas []dto.ContainerInfo
records []types.Container
list []types.Container
)
client, err := docker.NewDockerClient()
if err != nil {
@ -95,9 +94,30 @@ func (u *ContainerService) Page(req dto.PageContainer) (int64, interface{}, erro
}
}
}
sort.Slice(list, func(i, j int) bool {
return list[i].Created > list[j].Created
})
switch req.OrderBy {
case "name":
sort.Slice(list, func(i, j int) bool {
if req.Order == constant.OrderAsc {
return list[i].Names[0][1:] < list[j].Names[0][1:]
}
return list[i].Names[0][1:] > list[j].Names[0][1:]
})
case "state":
sort.Slice(list, func(i, j int) bool {
if req.Order == constant.OrderAsc {
return list[i].State < list[j].State
}
return list[i].State > list[j].State
})
default:
sort.Slice(list, func(i, j int) bool {
if req.Order == constant.OrderAsc {
return list[i].Created < list[j].Created
}
return list[i].Created > list[j].Created
})
}
total, start, end := len(list), (req.Page-1)*req.PageSize, req.Page*req.PageSize
if start > total {
records = make([]types.Container, 0)
@ -108,10 +128,11 @@ func (u *ContainerService) Page(req dto.PageContainer) (int64, interface{}, erro
records = list[start:end]
}
backDatas := make([]dto.ContainerInfo, len(records))
var wg sync.WaitGroup
wg.Add(len(records))
for _, container := range records {
go func(item types.Container) {
for i := 0; i < len(records); i++ {
go func(item types.Container, i int) {
IsFromCompose := false
if _, ok := item.Labels[composeProjectLabel]; ok {
IsFromCompose = true
@ -129,7 +150,7 @@ func (u *ContainerService) Page(req dto.PageContainer) (int64, interface{}, erro
ports = append(ports, fmt.Sprintf("%v:%v/%s", port.PublicPort, port.PrivatePort, port.Type))
}
cpu, mem := loadCpuAndMem(client, item.ID)
backDatas = append(backDatas, dto.ContainerInfo{
backDatas[i] = dto.ContainerInfo{
ContainerID: item.ID,
CreateTime: time.Unix(item.Created, 0).Format("2006-01-02 15:04:05"),
Name: item.Names[0][1:],
@ -142,9 +163,9 @@ func (u *ContainerService) Page(req dto.PageContainer) (int64, interface{}, erro
Ports: ports,
IsFromApp: IsFromApp,
IsFromCompose: IsFromCompose,
})
}
wg.Done()
}(container)
}(records[i], i)
}
wg.Wait()

View File

@ -36,7 +36,7 @@ func NewICronjobService() ICronjobService {
}
func (u *CronjobService) SearchWithPage(search dto.SearchWithPage) (int64, interface{}, error) {
total, cronjobs, err := cronjobRepo.Page(search.Page, search.PageSize, commonRepo.WithLikeName(search.Info))
total, cronjobs, err := cronjobRepo.Page(search.Page, search.PageSize, commonRepo.WithLikeName(search.Info), commonRepo.WithOrderRuleBy(search.OrderBy, search.Order))
var dtoCronjobs []dto.CronjobInfo
for _, cronjob := range cronjobs {
var item dto.CronjobInfo

View File

@ -48,7 +48,7 @@ func NewIMysqlService() IMysqlService {
}
func (u *MysqlService) SearchWithPage(search dto.SearchWithPage) (int64, interface{}, error) {
total, mysqls, err := mysqlRepo.Page(search.Page, search.PageSize, commonRepo.WithLikeName(search.Info))
total, mysqls, err := mysqlRepo.Page(search.Page, search.PageSize, commonRepo.WithLikeName(search.Info), commonRepo.WithOrderRuleBy(search.OrderBy, search.Order))
var dtoMysqls []dto.MysqlDBInfo
for _, mysql := range mysqls {
var item dto.MysqlDBInfo

View File

@ -8,6 +8,14 @@ import (
"encoding/pem"
"errors"
"fmt"
"os"
"path"
"reflect"
"regexp"
"strconv"
"strings"
"time"
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
"github.com/1Panel-dev/1Panel/backend/utils/common"
@ -18,13 +26,6 @@ import (
"golang.org/x/crypto/bcrypt"
"gopkg.in/ini.v1"
"gorm.io/gorm"
"os"
"path"
"reflect"
"regexp"
"strconv"
"strings"
"time"
"github.com/1Panel-dev/1Panel/backend/app/dto/request"
"github.com/1Panel-dev/1Panel/backend/app/dto/response"
@ -96,7 +97,7 @@ func (w WebsiteService) PageWebsite(req request.WebsiteSearch) (int64, []respons
}
return 0, nil, err
}
opts = append(opts, commonRepo.WithOrderBy("created_at desc"))
opts = append(opts, commonRepo.WithOrderRuleBy(req.OrderBy, req.Order))
if req.Name != "" {
opts = append(opts, websiteRepo.WithDomainLike(req.Name))
}

View File

@ -10,4 +10,7 @@ const (
StatusEnable = "Enable"
StatusDisable = "Disable"
StatusNone = "None"
OrderDesc = "descending"
OrderAsc = "ascending"
)

View File

@ -9,6 +9,8 @@ export namespace Container {
export interface ContainerSearch extends ReqPage {
name: string;
filters: string;
orderBy: string;
order: string;
}
export interface ResourceLimit {
cpu: number;

View File

@ -22,6 +22,8 @@ export interface SearchWithPage {
info: string;
page: number;
pageSize: number;
orderBy?: string;
order?: string;
}
export interface CommonModel {
id: number;

View File

@ -39,6 +39,8 @@ export namespace Website {
export interface WebSiteSearch extends ReqPage {
name: string;
orderBy: string;
order: string;
websiteGroupId: number;
}

View File

@ -60,10 +60,11 @@
:pagination-config="paginationConfig"
v-model:selects="selects"
:data="data"
@sort-change="search"
@search="search"
>
<el-table-column type="selection" fix />
<el-table-column :label="$t('commons.table.name')" min-width="80" prop="name" fix>
<el-table-column :label="$t('commons.table.name')" min-width="80" prop="name" sortable fix>
<template #default="{ row }">
<Tooltip @click="onInspect(row.containerID)" :text="row.name" />
</template>
@ -74,7 +75,7 @@
min-width="80"
prop="imageName"
/>
<el-table-column :label="$t('commons.table.status')" min-width="60" prop="state" fix>
<el-table-column :label="$t('commons.table.status')" min-width="60" prop="state" sortable fix>
<template #default="{ row }">
<Status :key="row.state" :status="row.state"></Status>
</template>
@ -225,13 +226,15 @@ const mydetail = ref();
const dialogContainerLogRef = ref();
const dialogReNameRef = ref();
const search = async () => {
const search = async (column?: any) => {
let filterItem = props.filters ? props.filters : '';
let params = {
name: searchName.value,
page: paginationConfig.currentPage,
pageSize: paginationConfig.pageSize,
filters: filterItem,
orderBy: column?.order ? column.prop : 'created_at',
order: column?.order ? column.order : 'null',
};
loading.value = true;
await searchContainer(params)

View File

@ -45,16 +45,17 @@
<ComplexTable
:pagination-config="paginationConfig"
v-model:selects="selects"
@sort-change="search"
@search="search"
:data="data"
>
<el-table-column type="selection" fix />
<el-table-column :label="$t('cronjob.taskName')" :min-width="120" prop="name">
<el-table-column :label="$t('cronjob.taskName')" :min-width="120" prop="name" sortable>
<template #default="{ row }">
<Tooltip @click="loadDetail(row)" :text="row.name" />
</template>
</el-table-column>
<el-table-column :label="$t('commons.table.status')" :min-width="80" prop="status">
<el-table-column :label="$t('commons.table.status')" :min-width="80" prop="status" sortable>
<template #default="{ row }">
<el-button
v-if="row.status === 'Enable'"
@ -155,7 +156,7 @@
</el-dialog>
<OperatrDialog @search="search" ref="dialogRef" />
<Records @search="search()" ref="dialogRecordRef" />
<Records @search="search" ref="dialogRecordRef" />
</div>
</template>
@ -199,11 +200,13 @@ const weekOptions = [
{ label: i18n.global.t('cronjob.sunday'), value: 7 },
];
const search = async () => {
const search = async (column?: any) => {
let params = {
info: searchName.value,
page: paginationConfig.currentPage,
pageSize: paginationConfig.pageSize,
orderBy: column?.order ? column.prop : 'created_at',
order: column?.order ? column.order : 'null',
};
loading.value = true;
await getCronjobPage(params)

View File

@ -43,11 +43,12 @@
<template #main v-if="mysqlIsExist && !isOnSetting">
<ComplexTable
:pagination-config="paginationConfig"
@sort-change="search"
@search="search"
:data="data"
:class="{ mask: mysqlStatus != 'Running' }"
>
<el-table-column :label="$t('commons.table.name')" prop="name" />
<el-table-column :label="$t('commons.table.name')" prop="name" sortable />
<el-table-column :label="$t('commons.login.username')" prop="username" />
<el-table-column :label="$t('commons.login.password')" prop="password">
<template #default="{ row }">
@ -239,11 +240,13 @@ const onSetting = async () => {
settingRef.value!.acceptParams(params);
};
const search = async () => {
const search = async (column?: any) => {
let params = {
page: paginationConfig.currentPage,
pageSize: paginationConfig.pageSize,
info: searchName.value,
orderBy: column?.order ? column.prop : 'created_at',
order: column?.order ? column.order : 'null',
};
const res = await searchMysqlDBs(params);
data.value = res.data.items || [];

View File

@ -64,19 +64,28 @@
<ComplexTable
:pagination-config="paginationConfig"
:data="data"
@sort-change="search"
@search="search()"
:class="{ mask: nginxStatus != 'Running' }"
>
<el-table-column :label="$t('commons.table.name')" fix prop="primaryDomain" min-width="120px">
<el-table-column
:label="$t('commons.table.name')"
fix
prop="primaryDomain"
min-width="120px"
sortable
>
<template #default="{ row }">
<Tooltip @click="openConfig(row.id)" :text="row.primaryDomain" />
</template>
</el-table-column>
<el-table-column :label="$t('commons.table.type')" fix show-overflow-tooltip prop="type">
<el-table-column :label="$t('commons.table.type')" fix show-overflow-tooltip prop="type" sortable>
<template #default="{ row }">
{{ $t('website.' + row.type) }}
<span v-if="row.type === 'deployment'">[{{ row.appName }}]</span>
<span v-if="row.type === 'runtime'">[{{ row.runtimeName }}]</span>
<div v-if="row.type">
{{ $t('website.' + row.type) }}
<span v-if="row.type === 'deployment'">[{{ row.appName }}]</span>
<span v-if="row.type === 'runtime'">[{{ row.runtimeName }}]</span>
</div>
</template>
</el-table-column>
<el-table-column :label="$t('website.sitePath')" prop="sitePath">
@ -233,14 +242,19 @@ let req = reactive({
name: '',
page: 1,
pageSize: 10,
orderBy: 'created_at',
order: 'null',
websiteGroupId: 0,
});
const mobile = computed(() => {
return globalStore.isMobile();
});
const search = async () => {
const search = async (column?: any) => {
req.page = paginationConfig.currentPage;
req.pageSize = paginationConfig.pageSize;
req.orderBy = column?.order ? column.prop : 'created_at';
req.orderBy = req.orderBy === 'primaryDomain' ? 'primary_domain' : req.orderBy;
req.order = column?.order ? column.order : 'null';
loading.value = true;
await SearchWebsites(req)
.then((res) => {