1
0
mirror of https://github.com/1Panel-dev/1Panel.git synced 2025-03-17 03:04:46 +08:00

fix: 防火墙空状态页面样式优化 (#625)

This commit is contained in:
ssongliu 2023-04-14 15:08:51 +08:00 committed by GitHub
parent 975663f0ff
commit 4c8fc1defa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 254 additions and 189 deletions

View File

@ -161,27 +161,3 @@ onMounted(() => {
onCheck(); onCheck();
}); });
</script> </script>
<style lang="scss">
.app-warn {
text-align: center;
margin-top: 100px;
span:first-child {
color: #bbbfc4;
}
span:nth-child(2) {
color: $primary-color;
cursor: pointer;
}
span:nth-child(2):hover {
color: #74a4f3;
}
img {
width: 300px;
height: 300px;
}
}
</style>

View File

@ -1227,6 +1227,8 @@ const message = {
'This certificate has been associated with the following websites, and the renewal will be applied to these websites simultaneously', 'This certificate has been associated with the following websites, and the renewal will be applied to these websites simultaneously',
}, },
firewall: { firewall: {
notSupport:
'No system firewall detected (firewalld or ufw). Please refer to the official documentation for installation.',
ccDeny: 'CC Protection', ccDeny: 'CC Protection',
ipWhiteList: 'IP Whitelist', ipWhiteList: 'IP Whitelist',
ipBlockList: 'IP Blacklist', ipBlockList: 'IP Blacklist',

View File

@ -1220,6 +1220,7 @@ const message = {
createAcme: '创建账户', createAcme: '创建账户',
}, },
firewall: { firewall: {
notSupport: '未检测到系统防火墙firewalld 或者 ufw请参考官方文档进行安装',
ccDeny: 'CC 防护', ccDeny: 'CC 防护',
ipWhiteList: 'IP 白名单', ipWhiteList: 'IP 白名单',
ipBlockList: 'IP 黑名单', ipBlockList: 'IP 黑名单',

View File

@ -302,3 +302,25 @@
.table-link:hover { .table-link:hover {
opacity: 0.6; opacity: 0.6;
} }
.app-warn {
text-align: center;
margin-top: 100px;
span:first-child {
color: #bbbfc4;
}
span:nth-child(2) {
color: $primary-color;
cursor: pointer;
}
span:nth-child(2):hover {
color: #74a4f3;
}
img {
width: 300px;
height: 300px;
}
}

View File

@ -2,83 +2,109 @@
<div v-loading="loading" style="position: relative"> <div v-loading="loading" style="position: relative">
<FireRouter /> <FireRouter />
<FireStatus <FireStatus
v-show="fireName !== '-'"
ref="fireStatuRef" ref="fireStatuRef"
@search="search" @search="search"
v-model:loading="loading" v-model:loading="loading"
v-model:name="fireName"
v-model:mask-show="maskShow" v-model:mask-show="maskShow"
v-model:status="fireStatus" v-model:status="fireStatus"
/> />
<el-card v-if="fireStatus != 'running' && maskShow" class="mask-prompt"> <div v-if="fireName !== '-'">
<span>{{ $t('firewall.firewallNotStart') }}</span> <el-card v-if="fireStatus != 'running' && maskShow" class="mask-prompt">
</el-card> <span>{{ $t('firewall.firewallNotStart') }}</span>
</el-card>
<LayoutContent :title="$t('firewall.ipRule')" :class="{ mask: fireStatus != 'running' }"> <LayoutContent :title="$t('firewall.ipRule')" :class="{ mask: fireStatus != 'running' }">
<template #toolbar> <template #toolbar>
<el-row> <el-row>
<el-col :span="16"> <el-col :span="16">
<el-button type="primary" @click="onOpenDialog('create')"> <el-button type="primary" @click="onOpenDialog('create')">
{{ $t('commons.button.create') }} {{ $t('firewall.ipRule') }} {{ $t('commons.button.create') }} {{ $t('firewall.ipRule') }}
</el-button> </el-button>
<el-button @click="onDelete(null)" plain :disabled="selects.length === 0"> <el-button @click="onDelete(null)" plain :disabled="selects.length === 0">
{{ $t('commons.button.delete') }} {{ $t('commons.button.delete') }}
</el-button> </el-button>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
<TableSetting @search="search()" /> <TableSetting @search="search()" />
<div class="search-button"> <div class="search-button">
<el-input <el-input
v-model="searchName" v-model="searchName"
clearable clearable
@clear="search()" @clear="search()"
suffix-icon="Search" suffix-icon="Search"
@keyup.enter="search()" @keyup.enter="search()"
@blur="search()" @blur="search()"
:placeholder="$t('commons.button.search')" :placeholder="$t('commons.button.search')"
></el-input> ></el-input>
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
</template> </template>
<template #main> <template #main>
<ComplexTable <ComplexTable
:pagination-config="paginationConfig" :pagination-config="paginationConfig"
v-model:selects="selects" v-model:selects="selects"
@search="search" @search="search"
:data="data" :data="data"
> >
<el-table-column type="selection" fix /> <el-table-column type="selection" fix />
<el-table-column :min-width="80" :label="$t('firewall.address')" prop="address"> <el-table-column :min-width="80" :label="$t('firewall.address')" prop="address">
<template #default="{ row }"> <template #default="{ row }">
<span v-if="row.address && row.address !== 'Anywhere'">{{ row.address }}</span> <span v-if="row.address && row.address !== 'Anywhere'">{{ row.address }}</span>
<span v-else>{{ $t('firewall.allIP') }}</span> <span v-else>{{ $t('firewall.allIP') }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column :min-width="80" :label="$t('firewall.strategy')" prop="strategy"> <el-table-column :min-width="80" :label="$t('firewall.strategy')" prop="strategy">
<template #default="{ row }"> <template #default="{ row }">
<el-button <el-button
v-if="row.strategy === 'accept'" v-if="row.strategy === 'accept'"
@click="onChangeStatus(row, 'drop')" @click="onChangeStatus(row, 'drop')"
link link
type="success" type="success"
>
{{ $t('firewall.allow') }}
</el-button>
<el-button v-else link type="danger" @click="onChangeStatus(row, 'accept')">
{{ $t('firewall.deny') }}
</el-button>
</template>
</el-table-column>
<fu-table-operations
width="200px"
:buttons="buttons"
:ellipsis="10"
:label="$t('commons.table.operate')"
fix
/>
</ComplexTable>
</template>
</LayoutContent>
</div>
<div v-else>
<LayoutContent :title="$t('firewall.firewall')" :divider="true">
<template #main>
<div class="app-warn">
<div>
<span>{{ $t('firewall.notSupport') }}</span>
<el-link
style="font-size: 12px; margin-left: 5px"
@click="toDoc"
icon="Position"
type="primary"
> >
{{ $t('firewall.allow') }} {{ $t('firewall.quickJump') }}
</el-button> </el-link>
<el-button v-else link type="danger" @click="onChangeStatus(row, 'accept')"> <div>
{{ $t('firewall.deny') }} <img src="@/assets/images/no_app.svg" />
</el-button> </div>
</template> </div>
</el-table-column> </div>
<fu-table-operations </template>
width="200px" </LayoutContent>
:buttons="buttons" </div>
:ellipsis="10"
:label="$t('commons.table.operate')"
fix
/>
</ComplexTable>
</template>
</LayoutContent>
<OperatrDialog @search="search" ref="dialogRef" /> <OperatrDialog @search="search" ref="dialogRef" />
</div> </div>
@ -102,6 +128,7 @@ const loading = ref();
const activeTag = ref('address'); const activeTag = ref('address');
const selects = ref<any>([]); const selects = ref<any>([]);
const searchName = ref(); const searchName = ref();
const fireName = ref();
const maskShow = ref(true); const maskShow = ref(true);
const fireStatus = ref('running'); const fireStatus = ref('running');
@ -153,6 +180,10 @@ const onOpenDialog = async (
dialogRef.value!.acceptParams(params); dialogRef.value!.acceptParams(params);
}; };
const toDoc = () => {
window.open('https://1panel.cn/docs/user_manual/hosts/firewall/', '_blank');
};
const onChangeStatus = async (row: Host.RuleInfo, status: string) => { const onChangeStatus = async (row: Host.RuleInfo, status: string) => {
let operation = let operation =
status === 'accept' status === 'accept'
@ -244,7 +275,9 @@ const buttons = [
]; ];
onMounted(() => { onMounted(() => {
loading.value = true; if (fireName.value !== '-') {
fireStatuRef.value.acceptParams(); loading.value = true;
fireStatuRef.value.acceptParams();
}
}); });
</script> </script>

View File

@ -3,6 +3,7 @@
<FireRouter /> <FireRouter />
<FireStatus <FireStatus
v-show="fireName !== '-'"
ref="fireStatuRef" ref="fireStatuRef"
@search="search" @search="search"
v-model:loading="loading" v-model:loading="loading"
@ -10,107 +11,132 @@
v-model:status="fireStatus" v-model:status="fireStatus"
v-model:name="fireName" v-model:name="fireName"
/> />
<div v-if="fireName !== '-'">
<el-card v-if="fireStatus != 'running' && maskShow" class="mask-prompt">
<span>{{ $t('firewall.firewallNotStart') }}</span>
</el-card>
<el-card v-if="fireStatus != 'running' && maskShow" class="mask-prompt"> <LayoutContent :title="$t('firewall.portRule')" :class="{ mask: fireStatus != 'running' }">
<span>{{ $t('firewall.firewallNotStart') }}</span> <template #prompt>
</el-card> <el-alert type="info" :closable="false">
<template #default>
<LayoutContent :title="$t('firewall.portRule')" :class="{ mask: fireStatus != 'running' }"> <span>
<template #prompt> <span>{{ $t('firewall.dockerHelper', [fireName]) }}</span>
<el-alert type="info" :closable="false"> <el-link
<template #default> style="font-size: 12px; margin-left: 5px"
<span> icon="Position"
<span>{{ $t('firewall.dockerHelper', [fireName]) }}</span> @click="quickJump()"
type="primary"
>
{{ $t('firewall.quickJump') }}
</el-link>
</span>
</template>
</el-alert>
</template>
<template #toolbar>
<el-row>
<el-col :span="16">
<el-button type="primary" @click="onOpenDialog('create')">
{{ $t('commons.button.create') }}{{ $t('firewall.portRule') }}
</el-button>
<el-button @click="onDelete(null)" plain :disabled="selects.length === 0">
{{ $t('commons.button.delete') }}
</el-button>
</el-col>
<el-col :span="8">
<TableSetting @search="search()" />
<div class="search-button">
<el-input
v-model="searchName"
clearable
@clear="search()"
suffix-icon="Search"
@keyup.enter="search()"
@blur="search()"
:placeholder="$t('commons.button.search')"
></el-input>
</div>
</el-col>
</el-row>
</template>
<template #main>
<ComplexTable
:pagination-config="paginationConfig"
v-model:selects="selects"
@search="search"
:data="data"
>
<el-table-column type="selection" :selectable="selectable" fix />
<el-table-column :label="$t('firewall.protocol')" :min-width="90" prop="protocol" />
<el-table-column :label="$t('firewall.port')" :min-width="120" prop="port" />
<el-table-column :label="$t('commons.table.status')" :min-width="120">
<template #default="{ row }">
<el-tag type="info" v-if="row.isUsed">
{{
row.appName
? $t('firewall.used') + ' ( ' + row.appName + ' )'
: $t('firewall.used')
}}
</el-tag>
<el-tag type="success" v-else>{{ $t('firewall.unUsed') }}</el-tag>
</template>
</el-table-column>
<el-table-column :min-width="80" :label="$t('firewall.strategy')" prop="strategy">
<template #default="{ row }">
<el-button
v-if="row.strategy === 'accept'"
:disabled="row.appName === '1panel'"
@click="onChangeStatus(row, 'drop')"
link
type="success"
>
{{ $t('firewall.accept') }}
</el-button>
<el-button v-else link type="danger" @click="onChangeStatus(row, 'accept')">
{{ $t('firewall.drop') }}
</el-button>
</template>
</el-table-column>
<el-table-column :min-width="80" :label="$t('firewall.address')" prop="address">
<template #default="{ row }">
<span v-if="row.address && row.address !== 'Anywhere'">{{ row.address }}</span>
<span v-else>{{ $t('firewall.allIP') }}</span>
</template>
</el-table-column>
<fu-table-operations
width="200px"
:buttons="buttons"
:ellipsis="10"
:label="$t('commons.table.operate')"
fix
/>
</ComplexTable>
</template>
</LayoutContent>
</div>
<div v-else>
<LayoutContent :title="$t('firewall.firewall')" :divider="true">
<template #main>
<div class="app-warn">
<div>
<span>{{ $t('firewall.notSupport') }}</span>
<el-link <el-link
style="font-size: 12px; margin-left: 5px" style="font-size: 12px; margin-left: 5px"
@click="toDoc"
icon="Position" icon="Position"
@click="quickJump()"
type="primary" type="primary"
> >
{{ $t('firewall.quickJump') }} {{ $t('firewall.quickJump') }}
</el-link> </el-link>
</span> <div>
</template> <img src="@/assets/images/no_app.svg" />
</el-alert> </div>
</template>
<template #toolbar>
<el-row>
<el-col :span="16">
<el-button type="primary" @click="onOpenDialog('create')">
{{ $t('commons.button.create') }}{{ $t('firewall.portRule') }}
</el-button>
<el-button @click="onDelete(null)" plain :disabled="selects.length === 0">
{{ $t('commons.button.delete') }}
</el-button>
</el-col>
<el-col :span="8">
<TableSetting @search="search()" />
<div class="search-button">
<el-input
v-model="searchName"
clearable
@clear="search()"
suffix-icon="Search"
@keyup.enter="search()"
@blur="search()"
:placeholder="$t('commons.button.search')"
></el-input>
</div> </div>
</el-col> </div>
</el-row> </template>
</template> </LayoutContent>
<template #main> </div>
<ComplexTable
:pagination-config="paginationConfig"
v-model:selects="selects"
@search="search"
:data="data"
>
<el-table-column type="selection" :selectable="selectable" fix />
<el-table-column :label="$t('firewall.protocol')" :min-width="90" prop="protocol" />
<el-table-column :label="$t('firewall.port')" :min-width="120" prop="port" />
<el-table-column :label="$t('commons.table.status')" :min-width="120">
<template #default="{ row }">
<el-tag type="info" v-if="row.isUsed">
{{
row.appName ? $t('firewall.used') + ' ( ' + row.appName + ' )' : $t('firewall.used')
}}
</el-tag>
<el-tag type="success" v-else>{{ $t('firewall.unUsed') }}</el-tag>
</template>
</el-table-column>
<el-table-column :min-width="80" :label="$t('firewall.strategy')" prop="strategy">
<template #default="{ row }">
<el-button
v-if="row.strategy === 'accept'"
:disabled="row.appName === '1panel'"
@click="onChangeStatus(row, 'drop')"
link
type="success"
>
{{ $t('firewall.accept') }}
</el-button>
<el-button v-else link type="danger" @click="onChangeStatus(row, 'accept')">
{{ $t('firewall.drop') }}
</el-button>
</template>
</el-table-column>
<el-table-column :min-width="80" :label="$t('firewall.address')" prop="address">
<template #default="{ row }">
<span v-if="row.address && row.address !== 'Anywhere'">{{ row.address }}</span>
<span v-else>{{ $t('firewall.allIP') }}</span>
</template>
</el-table-column>
<fu-table-operations
width="200px"
:buttons="buttons"
:ellipsis="10"
:label="$t('commons.table.operate')"
fix
/>
</ComplexTable>
</template>
</LayoutContent>
<OperatrDialog @search="search" ref="dialogRef" /> <OperatrDialog @search="search" ref="dialogRef" />
</div> </div>
@ -192,6 +218,9 @@ const onOpenDialog = async (
const quickJump = () => { const quickJump = () => {
router.push({ name: 'ContainerSetting' }); router.push({ name: 'ContainerSetting' });
}; };
const toDoc = () => {
window.open('https://1panel.cn/docs/user_manual/hosts/firewall/', '_blank');
};
const onChangeStatus = async (row: Host.RuleInfo, status: string) => { const onChangeStatus = async (row: Host.RuleInfo, status: string) => {
let operation = let operation =
@ -300,7 +329,9 @@ const buttons = [
]; ];
onMounted(() => { onMounted(() => {
loading.value = true; if (fireName.value !== '-') {
fireStatuRef.value.acceptParams(); loading.value = true;
fireStatuRef.value.acceptParams();
}
}); });
</script> </script>

View File

@ -91,7 +91,7 @@ const onOperate = async (operation: string) => {
loadBaseInfo(true); loadBaseInfo(true);
}) })
.catch(() => { .catch(() => {
emit('update:loading', false); loadBaseInfo(true);
}); });
}) })
.catch(() => { .catch(() => {