Files
yunzerwebsiteallinone/platform/src/views/apps/cms/domain/audit.vue
T
2026-09-15 10:44:31 +08:00

297 lines
9.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="container-box">
<div class="header-bar">
<h2>租户域名审核</h2>
<el-button @click="fetchData" :loading="loading">
<el-icon><Refresh /></el-icon>
刷新
</el-button>
</div>
<el-divider></el-divider>
<!-- 搜索区域 -->
<div class="search-box">
<el-input
v-model="searchForm.sub_domain"
placeholder="搜索二级前缀或完整域名"
clearable
style="width: 220px; margin-right: 10px;"
@keyup.enter="handleSearch"
/>
<el-select v-model="searchForm.domain_type" placeholder="类型" clearable style="width: 150px; margin-right: 10px;">
<el-option label="平台二级域名" :value="1" />
<el-option label="自有域名" :value="2" />
</el-select>
<el-select v-model="searchForm.status" placeholder="状态" clearable style="width: 120px; margin-right: 10px;">
<el-option label="待生效/审核中" :value="0" />
<el-option label="已生效" :value="1" />
<el-option label="已禁用" :value="2" />
</el-select>
<el-button type="primary" @click="handleSearch">搜索</el-button>
</div>
<!-- 表格 -->
<el-table
:data="tableData"
style="width: 100%"
border
v-loading="loading"
element-loading-text="正在加载..."
>
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="tenant_name" label="租户名称" min-width="150" />
<el-table-column label="类型" width="130" align="center">
<template #default="scope">
<el-tag v-if="isCustom(scope.row)" type="warning">自有域名</el-tag>
<el-tag v-else type="info">平台二级域名</el-tag>
</template>
</el-table-column>
<el-table-column prop="full_domain" label="完整域名" min-width="200" />
<el-table-column prop="status" label="状态" width="120" align="center">
<template #default="scope">
<el-tag v-if="scope.row.status === 1" type="success">已生效</el-tag>
<el-tag v-else-if="scope.row.status === 2" type="danger">已禁用</el-tag>
<el-tag v-else type="warning">{{ isCustom(scope.row) ? '待生效' : '审核中' }}</el-tag>
</template>
</el-table-column>
<el-table-column label="解析检测" width="120" align="center">
<template #default="scope">
<span v-if="!isCustom(scope.row)" class="text-muted">—</span>
<el-tooltip v-else-if="scope.row.verify_msg" :content="scope.row.verify_msg" placement="top">
<el-tag :type="verifyTagType(scope.row.verify_status)">{{ verifyText(scope.row.verify_status) }}</el-tag>
</el-tooltip>
<el-tag v-else :type="verifyTagType(scope.row.verify_status)">{{ verifyText(scope.row.verify_status) }}</el-tag>
</template>
</el-table-column>
<el-table-column label="HTTPS 证书" width="130" align="center">
<template #default="scope">
<span v-if="!isCustom(scope.row)" class="text-muted">平台证书</span>
<el-tooltip v-else-if="scope.row.ssl_status === 3 && scope.row.ssl_error" :content="scope.row.ssl_error" placement="top">
<el-tag type="danger">签发失败</el-tag>
</el-tooltip>
<el-tooltip v-else-if="scope.row.ssl_status === 2 && scope.row.ssl_expire_at" :content="'到期时间:' + scope.row.ssl_expire_at" placement="top">
<el-tag type="success">已签发</el-tag>
</el-tooltip>
<el-tag v-else :type="sslTagType(scope.row.ssl_status)">{{ sslText(scope.row.ssl_status) }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="create_time" label="申请时间" width="170">
<template #default="{ row }">{{ formatDateTime(row.create_time) }}</template>
</el-table-column>
<el-table-column label="操作" width="230" fixed="right" align="center">
<template #default="scope">
<!-- 自有域名无人工审核:解析与证书就绪后自动生效,这里只提供重新检测与禁用 -->
<template v-if="isCustom(scope.row)">
<el-button
size="small"
text
type="primary"
:loading="checkingId === scope.row.id"
@click="handleCheckDns(scope.row)"
>
检测解析
</el-button>
<el-button v-if="scope.row.status === 1" size="small" text type="danger" @click="handleDisable(scope.row)">
禁用
</el-button>
<el-button v-else-if="scope.row.status === 2" size="small" text type="success" @click="handleEnable(scope.row)">
启用
</el-button>
</template>
<template v-else-if="scope.row.status === 0">
<el-button size="small" type="success" @click="handleAudit(scope.row, 'approve')">
通过
</el-button>
<el-button size="small" type="danger" @click="handleAudit(scope.row, 'reject')">
拒绝
</el-button>
</template>
<template v-else-if="scope.row.status === 1">
<el-button size="small" text type="danger" @click="handleDisable(scope.row)">
禁用
</el-button>
</template>
<span v-else style="color: #999;">-</span>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<div class="pagination-wrap">
<el-pagination
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50]"
layout="total, sizes, prev, pager, next, jumper"
@size-change="fetchData"
@current-change="fetchData"
/>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, reactive, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Refresh } from '@element-plus/icons-vue'
import { formatDateTime } from '@/utils/datetime'
import {
getTenantDomainList,
auditTenantDomain,
toggleTenantDomainStatus,
checkCustomDomainDns
} from '@/api/domain'
// 域名类型:与后端 models.DomainTypeCustom 对应
const DOMAIN_TYPE_CUSTOM = 2
const loading = ref(false)
const checkingId = ref<number | null>(null)
const searchForm = reactive({
sub_domain: '',
status: '',
domain_type: ''
})
const pagination = reactive({
page: 1,
pageSize: 10,
total: 0
})
const tableData = ref<any[]>([])
const isCustom = (row: any) => row.domain_type === DOMAIN_TYPE_CUSTOM
const verifyText = (status: number) =>
status === 1 ? '已通过' : status === 2 ? '未通过' : '未检测'
const verifyTagType = (status: number) =>
status === 1 ? 'success' : status === 2 ? 'danger' : 'info'
const sslText = (status: number) =>
status === 2 ? '已签发' : status === 1 ? '签发中' : status === 3 ? '签发失败' : '待处理'
const sslTagType = (status: number) =>
status === 2 ? 'success' : status === 1 ? 'warning' : status === 3 ? 'danger' : 'info'
const fetchData = async () => {
loading.value = true
try {
const res = await getTenantDomainList({
page: pagination.page,
pageSize: pagination.pageSize,
...searchForm
})
if (res.code === 200) {
tableData.value = res.data.list || []
pagination.total = res.data.total || 0
}
} finally {
loading.value = false
}
}
const handleSearch = () => {
pagination.page = 1
fetchData()
}
const handleAudit = async (row: any, action: string) => {
const msg = action === 'approve' ? '确定要通过该域名申请吗?' : '确定要拒绝该域名申请吗?'
await ElMessageBox.confirm(msg, '提示', { type: 'warning' })
const res = await auditTenantDomain({ id: row.id, action })
if (res.code === 200) {
ElMessage.success(res.msg)
fetchData()
} else {
ElMessage.error(res.msg || '操作失败')
}
}
const handleDisable = async (row: any) => {
await ElMessageBox.confirm('确定要禁用该域名吗?禁用后该域名将无法访问官网。', '提示', { type: 'warning' })
const res = await toggleTenantDomainStatus(row.id)
if (res.code === 200) {
ElMessage.success(res.msg)
fetchData()
} else {
ElMessage.error(res.msg || '操作失败')
}
}
const handleEnable = async (row: any) => {
await ElMessageBox.confirm('确定要重新启用该域名吗?', '提示', { type: 'warning' })
const res = await toggleTenantDomainStatus(row.id)
if (res.code === 200) {
ElMessage.success(res.msg)
fetchData()
} else {
ElMessage.error(res.msg || '操作失败')
}
}
// 自有域名:重新检测解析,通过后后端自动申请证书
const handleCheckDns = async (row: any) => {
checkingId.value = row.id
try {
const res = await checkCustomDomainDns(row.id)
if (res.code === 200) {
const data = res.data || {}
if (data.verify_status === 1) {
ElMessage.success(data.ssl_message || data.verify_msg || '解析检测通过')
} else {
ElMessage.warning(data.verify_msg || '解析尚未生效')
}
fetchData()
} else {
ElMessage.error(res.msg || '检测失败')
}
} finally {
checkingId.value = null
}
}
onMounted(() => {
fetchData()
})
</script>
<style lang="less" scoped>
.container-box {
padding: 20px;
}
.header-bar {
display: flex;
justify-content: space-between;
align-items: center;
h2 {
margin: 0;
font-size: 18px;
font-weight: 600;
}
}
.search-box {
margin-bottom: 20px;
}
.text-muted {
color: #999;
}
.pagination-wrap {
margin-top: 20px;
display: flex;
justify-content: flex-end;
}
</style>