style: Optimize volume list display (#10231)

Refs #6601
This commit is contained in:
ssongliu 2025-09-02 17:48:10 +08:00 committed by GitHub
parent 66465beb39
commit 5a0c50b9a2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 93 additions and 30 deletions

View file

@ -209,11 +209,12 @@ type NetworkCreate struct {
}
type Volume struct {
Name string `json:"name"`
Labels []string `json:"labels"`
Driver string `json:"driver"`
Mountpoint string `json:"mountpoint"`
CreatedAt time.Time `json:"createdAt"`
Name string `json:"name"`
Labels []VolumeOption `json:"labels"`
Driver string `json:"driver"`
Mountpoint string `json:"mountpoint"`
CreatedAt time.Time `json:"createdAt"`
Options []VolumeOption `json:"options"`
}
type VolumeCreate struct {
Name string `json:"name" validate:"required"`
@ -221,7 +222,10 @@ type VolumeCreate struct {
Options []string `json:"options"`
Labels []string `json:"labels"`
}
type VolumeOption struct {
Key string `json:"key"`
Value string `json:"value"`
}
type BatchDelete struct {
TaskID string `json:"taskID"`
Force bool `json:"force"`

View file

@ -5,6 +5,7 @@ import (
"sort"
"strings"
"time"
"unicode"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/buserr"
@ -53,25 +54,27 @@ func (u *ContainerService) PageVolume(req dto.SearchWithPage) (int64, interface{
nyc, _ := time.LoadLocation(common.LoadTimeZoneByCmd())
for _, item := range records {
tag := make([]string, 0)
for _, val := range item.Labels {
tag = append(tag, val)
var volume dto.Volume
volume.Driver = item.Driver
volume.Mountpoint = item.Mountpoint
volume.Name = simplifyVolumeName(item.Name)
for key, val := range item.Labels {
volume.Labels = append(volume.Labels, dto.VolumeOption{Key: key, Value: val})
}
var createTime time.Time
if strings.Contains(item.CreatedAt, "Z") {
createTime, _ = time.ParseInLocation("2006-01-02T15:04:05Z", item.CreatedAt, nyc)
} else if strings.Contains(item.CreatedAt, "+") {
createTime, _ = time.ParseInLocation("2006-01-02T15:04:05+08:00", item.CreatedAt, nyc)
} else {
createTime, _ = time.ParseInLocation("2006-01-02T15:04:05", item.CreatedAt, nyc)
for key, val := range item.Options {
volume.Options = append(volume.Options, dto.VolumeOption{Key: key, Value: val})
}
data = append(data, dto.Volume{
CreatedAt: createTime,
Name: item.Name,
Driver: item.Driver,
Mountpoint: item.Mountpoint,
Labels: tag,
sort.Slice(volume.Options, func(i, j int) bool {
return volume.Options[i].Key < volume.Options[j].Key
})
if strings.Contains(item.CreatedAt, "Z") {
volume.CreatedAt, _ = time.ParseInLocation("2006-01-02T15:04:05Z", item.CreatedAt, nyc)
} else if strings.Contains(item.CreatedAt, "+") {
volume.CreatedAt, _ = time.ParseInLocation("2006-01-02T15:04:05+08:00", item.CreatedAt, nyc)
} else {
volume.CreatedAt, _ = time.ParseInLocation("2006-01-02T15:04:05", item.CreatedAt, nyc)
}
data = append(data, volume)
}
return int64(total), data, nil
@ -140,3 +143,16 @@ func (u *ContainerService) CreateVolume(req dto.VolumeCreate) error {
}
return nil
}
func simplifyVolumeName(name string) string {
if len(name) != 64 {
return name
}
for _, char := range name {
if !unicode.Is(unicode.ASCII_Hex_Digit, char) {
return name
}
}
return name[:12]
}

View file

@ -47,15 +47,35 @@
</el-text>
</template>
</el-table-column>
<el-table-column :label="$t('container.volumeDir')" min-width="100">
<el-table-column label="Options" min-width="160">
<template #default="{ row }">
<el-tooltip :content="row.mountpoint">
<el-button type="primary" link @click="routerToFileWithPath(row.mountpoint)">
<el-icon>
<FolderOpened />
</el-icon>
<div v-for="(item, index) in row.options" :key="index">
<div v-if="row.expand || (!row.expand && index < 3)">
<el-button
v-if="item.key === 'device'"
@click="jumpTo(item.value)"
class="mt-0.5"
icon="Position"
plain
size="small"
>
{{ item.key + ': ' + item.value }}
</el-button>
<el-button v-else class="mt-0.5" plain size="small">
{{ item.key + ': ' + item.value }}
</el-button>
</div>
</div>
<div v-if="!row.expand && row.options.length > 3">
<el-button type="primary" link @click="row.expand = true">
{{ $t('commons.button.expand') }}...
</el-button>
</el-tooltip>
</div>
<div v-if="row.expand && row.options.length > 3">
<el-button type="primary" link @click="row.expand = false">
{{ $t('commons.button.collapse') }}
</el-button>
</div>
</template>
</el-table-column>
<el-table-column
@ -63,7 +83,18 @@
show-overflow-tooltip
min-width="120"
prop="mountpoint"
/>
>
<template #default="{ row }">
<el-tooltip :content="row.mountpoint">
<el-button
type="primary"
icon="FolderOpened"
link
@click="routerToFileWithPath(row.mountpoint)"
/>
</el-tooltip>
</template>
</el-table-column>
<el-table-column
:label="$t('container.driver')"
show-overflow-tooltip
@ -102,6 +133,8 @@ import i18n from '@/lang';
import { ElMessageBox } from 'element-plus';
import { GlobalStore } from '@/store';
import { routerToFileWithPath } from '@/utils/router';
import { checkFile } from '@/api/modules/files';
import { MsgError } from '@/utils/message';
const globalStore = GlobalStore();
const taskLogRef = ref();
@ -193,6 +226,16 @@ const openTaskLog = (taskID: string) => {
taskLogRef.value.openWithTaskID(taskID);
};
const jumpTo = async (path: any) => {
await checkFile(path, false).then((res) => {
if (res.data) {
routerToFileWithPath(path);
} else {
MsgError(i18n.global.t('file.noSuchFile'));
}
});
};
const batchDelete = async (row: Container.VolumeInfo | null) => {
let names = [];
if (row) {