2
0
mirror of https://github.com/acepanel/panel.git synced 2026-02-04 06:47:20 +08:00

feat: 网站列表添加域名直接打开

This commit is contained in:
2026-01-26 18:14:40 +08:00
parent d87a9e3f02
commit 197781e722
4 changed files with 75 additions and 5 deletions

View File

@@ -27,8 +27,9 @@ type Website struct {
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
CertExpire string `gorm:"-:all" json:"cert_expire"` // 仅显示
PHP uint `gorm:"-:all" json:"php"` // 仅显示
CertExpire string `gorm:"-:all" json:"cert_expire"` // 仅显示
PHP uint `gorm:"-:all" json:"php"` // 仅显示
Domains []string `gorm:"-:all" json:"domains"` // 仅显示
Cert *Cert `gorm:"foreignKey:WebsiteID" json:"cert"`
}

View File

@@ -263,6 +263,12 @@ func (r *websiteRepo) List(typ string, page, limit uint) ([]*biz.Website, int64,
if website.Type == biz.WebsiteTypePHP {
website.PHP = r.getPHPVersion(website.Name)
}
// 获取域名
if vhost, err := r.getVhost(website); err == nil {
if domains, err := punycode.DecodeDomains(vhost.ServerName()); err == nil {
website.Domains = domains
}
}
}
return websites, total, nil

View File

@@ -30,6 +30,7 @@ import EditModal from '@/views/file/EditModal.vue'
import PreviewModal from '@/views/file/PreviewModal.vue'
import PropertyModal from '@/views/file/PropertyModal.vue'
import type { FileInfo, Marked } from '@/views/file/types'
import copy2clipboard from '@vavt/copy2clipboard'
const { $gettext } = useGettext()
const themeVars = useThemeVars()
@@ -818,7 +819,7 @@ const deleteFiles = (items: any[]) => {
// 复制路径到剪贴板
const copyPath = (item: any) => {
navigator.clipboard.writeText(item.full).then(() => {
copy2clipboard(item.full).then(() => {
window.$message.success($gettext('Path copied to clipboard'))
})
}

View File

@@ -1,11 +1,13 @@
<script lang="ts" setup>
import { NButton, NCheckbox, NDataTable, NFlex, NInput, NSwitch, NTag } from 'naive-ui'
import { NButton, NCheckbox, NDataTable, NFlex, NInput, NPopover, NSwitch, NTag } from 'naive-ui'
import { useGettext } from 'vue3-gettext'
import website from '@/api/panel/website'
import DeleteConfirm from '@/components/common/DeleteConfirm.vue'
import TheIcon from '@/components/custom/TheIcon.vue'
import { useFileStore } from '@/store'
import { isNullOrUndef } from '@/utils'
import copy2clipboard from '@vavt/copy2clipboard'
const type = defineModel<string>('type', { type: String, required: true }) // 网站类型
const createModal = defineModel<boolean>('createModal', { type: Boolean, required: true }) // 创建网站
@@ -23,7 +25,67 @@ const columns: any = [
key: 'name',
width: 200,
resizable: true,
ellipsis: { tooltip: true }
ellipsis: { tooltip: true },
render(row: any) {
const elements = [h('span', {}, row.name)]
// 如果有域名,添加飞机图标和弹层
if (row.domains && row.domains.length > 0) {
elements.push(
h(
NPopover,
{ trigger: 'click', placement: 'right' },
{
trigger: () =>
h('span', { class: 'cursor-pointer hover:opacity-60 ml-1 inline-flex' }, [
h(TheIcon, { icon: 'mdi:send', size: 16 })
]),
default: () =>
h(
NFlex,
{ vertical: true, size: 'small' },
{
default: () =>
row.domains.map((domain: string) => {
const protocol = row.ssl ? 'https' : 'http'
const url = `${protocol}://${domain}`
return h(
NFlex,
{ align: 'center', size: 'small' },
{
default: () => [
h(
'a',
{
href: url,
target: '_blank',
class: 'hover:underline'
},
url
),
h(
'span',
{
class: 'cursor-pointer hover:opacity-60 ml-1 inline-flex',
onClick: () => {
copy2clipboard(url).then(() => {
window.$message.success($gettext('Copied'))
})
}
},
[h(TheIcon, { icon: 'mdi:content-copy', size: 14 })]
)
]
}
)
})
}
)
}
)
)
}
return h(NFlex, { align: 'center', wrap: false }, { default: () => elements })
}
},
{
title: $gettext('Running'),