fix: Fix the firewall startup failure (#8141)

This commit is contained in:
ssongliu
2025-03-13 07:09:06 +00:00
committed by GitHub
parent fc649ded94
commit 2ed3aaa99b
16 changed files with 210 additions and 229 deletions
+7 -5
View File
@@ -555,13 +555,15 @@ func (u *ContainerService) ContainerInfo(req dto.OperationWithName) (*dto.Contai
networkSettings := oldContainer.NetworkSettings
bridgeNetworkSettings := networkSettings.Networks[data.Network]
if bridgeNetworkSettings.IPAMConfig != nil {
ipv4Address := bridgeNetworkSettings.IPAMConfig.IPv4Address
data.MacAddr = bridgeNetworkSettings.MacAddress
data.Ipv4 = ipv4Address
ipv6Address := bridgeNetworkSettings.IPAMConfig.IPv6Address
data.Ipv6 = ipv6Address
if data.Network != "bridge" {
data.Ipv4 = bridgeNetworkSettings.IPAMConfig.IPv4Address
data.Ipv6 = bridgeNetworkSettings.IPAMConfig.IPv6Address
}
} else {
data.Ipv4 = bridgeNetworkSettings.IPAddress
if data.Network != "bridge" {
data.Ipv4 = bridgeNetworkSettings.IPAddress
}
}
data.Hostname = oldContainer.Config.Hostname
data.DNS = oldContainer.HostConfig.DNS
+4 -2
View File
@@ -611,8 +611,10 @@ func (u *FirewallService) updatePingStatus(enable string) error {
}
func (u *FirewallService) addPortsBeforeStart(client firewall.FirewallClient) error {
if err := client.Port(fireClient.FireInfo{Port: global.CONF.Base.Port, Protocol: "tcp", Strategy: "accept"}, "add"); err != nil {
return err
if !global.IsMaster {
if err := client.Port(fireClient.FireInfo{Port: global.CONF.Base.Port, Protocol: "tcp", Strategy: "accept"}, "add"); err != nil {
return err
}
}
if err := client.Port(fireClient.FireInfo{Port: "22", Protocol: "tcp", Strategy: "accept"}, "add"); err != nil {
return err
+4 -3
View File
@@ -1860,8 +1860,9 @@ const message = {
subscription: 'Subscription',
perpetual: 'Perpetual',
versionConstraint: '{0} Version Buyout',
forceDelete: 'Force delete, will ignore errors during the deletion process and eventually remove metadata',
deleteHelper: 'Deleting the license may cause child nodes to be unable to switch, please proceed with caution!',
forceUnbind: 'Force Unbind',
forceUnbindHelper:
'Forcing unbind will ignore any errors that occur during the unbinding process and ultimately release the license binding.',
trialInfo: 'Version',
authorizationId: 'Authorization ID',
authorizedUser: 'Authorized User',
@@ -3212,7 +3213,7 @@ const message = {
fixSSHConn: 'Manually edit the node to confirm connection information',
checkConnInfo: 'Check Agent Connection Information',
checkStatus: 'Check Node Service Availability',
fixStatus: 'Investigate Node Logs',
fixStatus: 'Run "systemctl status 1panel-agent.service" to check if the service is running.',
checkAPI: 'Check Node API Availability',
fixAPI: 'Check the node logs and verify if the firewall ports are properly opened.',
forceDelete: 'Force Delete',
+4 -1
View File
@@ -1723,6 +1723,9 @@ const message = {
subscription: 'サブスクリプション',
perpetual: '永久ライセンス',
versionConstraint: '{0} バージョン買い取り',
forceUnbind: '強制バインド解除',
forceUnbindHelper:
'強制的にバインド解除を行うと解除プロセス中に発生するエラーを無視し最終的にライセンスのバインドを解除します',
trialInfo: 'バージョン',
authorizationId: 'サブスクリプション承認ID',
authorizedUser: '認定ユーザー',
@@ -3024,7 +3027,7 @@ const message = {
fixSSHConn: 'ノードを手動で編集し接続情報を確認',
checkConnInfo: 'エージェント接続情報を確認',
checkStatus: 'ノードサービスの可用性を確認',
fixStatus: 'ノードログを調査',
fixStatus: 'systemctl status 1panel-agent.serviceを実行してサービスが起動しているか確認します',
checkAPI: 'ノードAPIの可用性を確認',
fixAPI: 'ノードのログを確認しファイアウォールのポートが正常に開放されているか確認します',
forceDelete: '強制削除',
+4 -1
View File
@@ -1697,6 +1697,9 @@ const message = {
subscription: '구독',
perpetual: '영구 라이선스',
versionConstraint: '{0} 버전 일시불 구매',
forceUnbind: '강제 바인딩 해제',
forceUnbindHelper:
'강제 바인딩 해제를 수행하면 해제 과정에서 발생하는 오류를 무시하고 궁극적으로 라이센스 바인딩을 해제합니다.',
trialInfo: '버전',
authorizationId: '구독 인증 ID',
authorizedUser: '인증된 사용자',
@@ -2973,7 +2976,7 @@ const message = {
fixSSHConn: '노드를 수동으로 편집하여 연결 정보를 확인합니다',
checkConnInfo: '에이전트 연결 정보 확인',
checkStatus: '노드 서비스 가용성 확인',
fixStatus: '노드 로그 조사',
fixStatus: '"systemctl status 1panel-agent.service" 실행하여 서비스가 실행 중인지 확인합니다.',
checkAPI: '노드 API 가용성 확인',
fixAPI: '노드 로그를 확인하고 방화벽 포트가 정상적으로 열려 있는지 확인합니다.',
forceDelete: '강제 삭제',
+5 -1
View File
@@ -1782,6 +1782,9 @@ const message = {
subscription: 'Langganan',
perpetual: 'Lesen Perpetual',
versionConstraint: '{0} Pembelian versi',
forceUnbind: 'Paksakan Nyahikat',
forceUnbindHelper:
'Memaksa nyahikat akan mengabaikan sebarang ralat yang berlaku semasa proses nyahikat dan akhirnya melepaskan ikatan lesen.',
trialInfo: 'Versi',
authorizationId: 'ID Kebenaran Langganan',
authorizedUser: 'Pengguna yang Dibenarkan',
@@ -3094,7 +3097,8 @@ const message = {
fixSSHConn: 'Edit nod secara manual untuk mengesahkan maklumat sambungan',
checkConnInfo: 'Periksa Maklumat Sambungan Ejen',
checkStatus: 'Periksa Ketersediaan Perkhidmatan Nod',
fixStatus: 'Siasat Log Nod',
fixStatus:
'Jalankan "systemctl status 1panel-agent.service" untuk memeriksa sama ada perkhidmatan sedang berjalan.',
checkAPI: 'Periksa Ketersediaan API Nod',
fixAPI: 'Semak log nod dan periksa sama ada port firewall dibuka dengan betul.',
forceDelete: 'Hapus Secara Paksa',
+4 -1
View File
@@ -1767,6 +1767,9 @@ const message = {
subscription: 'Assinatura',
perpetual: 'Licença Perpétua',
versionConstraint: '{0} Compra do versão',
forceUnbind: 'Forçar Desvinculação',
forceUnbindHelper:
'Forçar a desvinculação ignorará quaisquer erros que ocorram durante o processo de desvinculação e, em última análise, liberará a vinculação da licença.',
trialInfo: 'Versão',
authorizationId: 'ID de autorização',
authorizedUser: 'Usuário autorizado',
@@ -3097,7 +3100,7 @@ const message = {
fixSSHConn: 'Edite o manualmente para confirmar as informações de conexão',
checkConnInfo: 'Verificar Informações de Conexão do Agente',
checkStatus: 'Verificar Disponibilidade do Serviço do ',
fixStatus: 'Investigar Logs do ',
fixStatus: 'Execute "systemctl status 1panel-agent.service" para verificar se o serviço está em execução.',
checkAPI: 'Verificar Disponibilidade da API do ',
fixAPI: 'Verifique os logs do e confirme se as portas do firewall estão devidamente abertas.',
forceDelete: 'Excluir Forçadamente',
+4 -1
View File
@@ -1767,6 +1767,9 @@ const message = {
subscription: 'Подписка',
perpetual: 'Пожизненная лицензия',
versionConstraint: '{0} Выкуп версии',
forceUnbind: 'Принудительное отвязывание',
forceUnbindHelper:
'Принудительное отвязывание будет игнорировать любые ошибки, возникающие в процессе отвязывания, и в конечном итоге освободит привязку лицензии.',
trialInfo: 'Версия',
authorizationId: 'ID авторизации подписки',
authorizedUser: 'Авторизованный пользователь',
@@ -3087,7 +3090,7 @@ const message = {
fixSSHConn: 'Вручную отредактируйте узел, чтобы подтвердить информацию о подключении',
checkConnInfo: 'Проверка информации о подключении агента',
checkStatus: 'Проверка доступности службы узла',
fixStatus: 'Проверка журналов узла',
fixStatus: 'Запустите "systemctl status 1panel-agent.service", чтобы проверить, запущена ли служба.',
checkAPI: 'Проверка доступности API узла',
fixAPI: 'Проверьте журналы узла и убедитесь, что порты брандмауэра правильно открыты.',
forceDelete: 'Принудительное удаление',
+3 -3
View File
@@ -1727,8 +1727,8 @@ const message = {
subscription: '訂閱',
perpetual: '永久授權',
versionConstraint: '{0} 版本買斷',
forceDelete: '強制刪除會忽略刪除過程中產生的錯誤並最終刪除元數據',
deleteHelper: '刪除許可證可能導致子節點無法切換請謹慎操作',
forceUnbind: '強制解除綁定',
forceUnbindHelper: '強制解除綁定將忽略解除過程中產生的錯誤最終解除許可證綁定',
trialInfo: '版本',
authorizationId: '訂閱授權 ID',
authorizedUser: '被授權方',
@@ -2976,7 +2976,7 @@ const message = {
fixSSHConn: '手動編輯節點確認連接資訊',
checkConnInfo: '檢查 Agent 連接資訊',
checkStatus: '檢查節點服務可用性',
fixStatus: '排查節點日誌',
fixStatus: '執行 "systemctl status 1panel-agent.service" 以檢查服務是否已啟動',
checkAPI: '檢查節點 API 可用性',
fixAPI: '檢查節點日誌確認防火牆端口是否正常放行',
forceDelete: '強制刪除',
+3 -3
View File
@@ -1719,8 +1719,8 @@ const message = {
subscription: '订阅',
perpetual: '永久授权',
versionConstraint: '{0} 版本买断',
forceDelete: '强制删除会忽略删除过程中产生的错误并最终删除元数据',
deleteHelper: '删除许可证可能导致子节点无法切换请谨慎操作',
forceUnbind: '强制解绑',
forceUnbindHelper: '强制解绑会忽略解绑过程中产生的错误并最终解除许可证绑定',
trialInfo: '版本',
authorizationId: '订阅授权 ID',
authorizedUser: '被授权方',
@@ -2957,7 +2957,7 @@ const message = {
fixSSHConn: '手动编辑节点确认连接信息',
checkConnInfo: '检查 Agent 连接信息',
checkStatus: '检查节点服务可用性',
fixStatus: '排查节点日志',
fixStatus: 'systemctl status 1panel-agent.service 检查服务是否已启动',
checkAPI: '检查节点 API 可用性',
fixAPI: '排查节点日志检查防火墙端口是否正常放行',
forceDelete: '强制删除',
@@ -425,7 +425,7 @@
</LayoutContent>
<Command ref="commandRef" />
<Confirm ref="confirmRef" @submit="submit" />
<TaskLog ref="taskLogRef" width="70%" />
<TaskLog ref="taskLogRef" width="70%" @close="goBack" />
</div>
</template>
@@ -462,7 +462,7 @@ const form = reactive<Container.ContainerHelper>({
image: '',
imageInput: false,
forcePull: false,
network: '',
network: 'bridge',
hostname: '',
domainName: '',
macAddr: '',
+118 -105
View File
@@ -1,120 +1,126 @@
<template>
<div v-loading="loading">
<CardWithHeader :header="$t('menu.container')" class="mt-5">
<template #body>
<span class="count" @click="goRouter('Container')">{{ countItem.containerCount }}</span>
</template>
<template #header-l>
<el-tag size="small" class="ml-5" v-if="countItem.all" effect="plain">
{{ $t('commons.table.all') }} * {{ countItem.all }}
</el-tag>
<el-tag size="small" v-if="countItem.running" effect="plain" class="ml-2">
{{ $t('commons.status.running') }} * {{ countItem.running }}
</el-tag>
<el-tag size="small" v-if="countItem.created" effect="plain" class="ml-2">
{{ $t('commons.status.created') }} * {{ countItem.created }}
</el-tag>
<el-tag size="small" v-if="countItem.paused" effect="plain" class="ml-2">
{{ $t('commons.status.paused') }} * {{ countItem.paused }}
</el-tag>
<el-tag size="small" v-if="countItem.restarting" effect="plain" class="ml-2">
{{ $t('commons.status.restarting') }} * {{ countItem.restarting }}
</el-tag>
<el-tag size="small" v-if="countItem.removing" effect="plain" class="ml-2">
{{ $t('commons.status.removing') }} * {{ countItem.removing }}
</el-tag>
<el-tag size="small" v-if="countItem.exited" effect="plain" class="ml-2">
{{ $t('commons.status.exited') }} * {{ countItem.exited }}
</el-tag>
<el-tag size="small" v-if="countItem.dead" effect="plain" class="ml-2">
{{ $t('commons.status.dead') }} * {{ countItem.dead }}
</el-tag>
</template>
</CardWithHeader>
<el-row :gutter="20" class="mt-5">
<el-col :span="8">
<CardWithHeader :header="$t('container.compose')">
<template #body>
<span class="count" @click="goRouter('Compose')">{{ countItem.composeCount }}</span>
</template>
</CardWithHeader>
</el-col>
<el-col :span="8">
<CardWithHeader :header="$t('container.composeTemplate')">
<template #body>
<span class="count" @click="goRouter('ComposeTemplate')">
{{ countItem.composeTemplateCount }}
</span>
</template>
</CardWithHeader>
</el-col>
<el-col :span="8">
<CardWithHeader :header="$t('container.image')">
<template #body>
<span class="count" @click="goRouter('Image')">{{ countItem.imageCount }}</span>
</template>
<template #header-l>
<span v-if="countItem.imageSize" effect="plain" class="ml-2 text-xs">
{{ $t('commons.status.used') }}: {{ computeSize(countItem.imageSize) }}
</span>
</template>
</CardWithHeader>
</el-col>
</el-row>
<el-row :gutter="20" class="mt-5">
<el-col :span="8">
<CardWithHeader :header="$t('container.imageRepo')">
<template #body>
<span class="count" @click="goRouter('Repo')">{{ countItem.repoCount }}</span>
</template>
</CardWithHeader>
</el-col>
<el-col :span="8">
<CardWithHeader :header="$t('container.network')">
<template #body>
<span class="count" @click="goRouter('Network')">{{ countItem.networkCount }}</span>
</template>
</CardWithHeader>
</el-col>
<el-col :span="8">
<CardWithHeader :header="$t('container.volume')">
<template #body>
<span class="count" @click="goRouter('Volume')">{{ countItem.volumeCount }}</span>
</template>
</CardWithHeader>
</el-col>
</el-row>
<CardWithHeader :header="$t('container.setting')" class="mt-5">
<template #body>
<el-descriptions :column="1" border>
<el-descriptions-item :label="$t('container.sockPath')">
{{ countItem.sockPath }}
</el-descriptions-item>
<el-descriptions-item :label="$t('container.mirrors')">
<div v-for="item in countItem.mirrors" :key="item" :value="item" :label="item">
<div class="mt-1">
<el-tag>{{ item }}</el-tag>
<docker-status v-model:isActive="isActive" v-model:loading="loading" @search="search" />
<div :class="{ mask: !isActive }">
<CardWithHeader :header="$t('menu.container')" class="mt-5">
<template #body>
<span class="count" @click="goRouter('Container')">{{ countItem.containerCount }}</span>
</template>
<template #header-l>
<el-tag size="small" class="ml-5" v-if="countItem.all" effect="plain">
{{ $t('commons.table.all') }} * {{ countItem.all }}
</el-tag>
<el-tag size="small" v-if="countItem.running" effect="plain" class="ml-2">
{{ $t('commons.status.running') }} * {{ countItem.running }}
</el-tag>
<el-tag size="small" v-if="countItem.created" effect="plain" class="ml-2">
{{ $t('commons.status.created') }} * {{ countItem.created }}
</el-tag>
<el-tag size="small" v-if="countItem.paused" effect="plain" class="ml-2">
{{ $t('commons.status.paused') }} * {{ countItem.paused }}
</el-tag>
<el-tag size="small" v-if="countItem.restarting" effect="plain" class="ml-2">
{{ $t('commons.status.restarting') }} * {{ countItem.restarting }}
</el-tag>
<el-tag size="small" v-if="countItem.removing" effect="plain" class="ml-2">
{{ $t('commons.status.removing') }} * {{ countItem.removing }}
</el-tag>
<el-tag size="small" v-if="countItem.exited" effect="plain" class="ml-2">
{{ $t('commons.status.exited') }} * {{ countItem.exited }}
</el-tag>
<el-tag size="small" v-if="countItem.dead" effect="plain" class="ml-2">
{{ $t('commons.status.dead') }} * {{ countItem.dead }}
</el-tag>
</template>
</CardWithHeader>
<el-row :gutter="20" class="mt-5">
<el-col :span="8">
<CardWithHeader :header="$t('container.compose')">
<template #body>
<span class="count" @click="goRouter('Compose')">{{ countItem.composeCount }}</span>
</template>
</CardWithHeader>
</el-col>
<el-col :span="8">
<CardWithHeader :header="$t('container.composeTemplate')">
<template #body>
<span class="count" @click="goRouter('ComposeTemplate')">
{{ countItem.composeTemplateCount }}
</span>
</template>
</CardWithHeader>
</el-col>
<el-col :span="8">
<CardWithHeader :header="$t('container.image')">
<template #body>
<span class="count" @click="goRouter('Image')">{{ countItem.imageCount }}</span>
</template>
<template #header-l>
<span v-if="countItem.imageSize" effect="plain" class="ml-2 text-xs">
{{ $t('commons.status.used') }}: {{ computeSize(countItem.imageSize) }}
</span>
</template>
</CardWithHeader>
</el-col>
</el-row>
<el-row :gutter="20" class="mt-5">
<el-col :span="8">
<CardWithHeader :header="$t('container.imageRepo')">
<template #body>
<span class="count" @click="goRouter('Repo')">{{ countItem.repoCount }}</span>
</template>
</CardWithHeader>
</el-col>
<el-col :span="8">
<CardWithHeader :header="$t('container.network')">
<template #body>
<span class="count" @click="goRouter('Network')">{{ countItem.networkCount }}</span>
</template>
</CardWithHeader>
</el-col>
<el-col :span="8">
<CardWithHeader :header="$t('container.volume')">
<template #body>
<span class="count" @click="goRouter('Volume')">{{ countItem.volumeCount }}</span>
</template>
</CardWithHeader>
</el-col>
</el-row>
<CardWithHeader :header="$t('container.setting')" class="mt-5">
<template #body>
<el-descriptions :column="1" border>
<el-descriptions-item :label="$t('container.sockPath')">
{{ countItem.sockPath }}
</el-descriptions-item>
<el-descriptions-item :label="$t('container.mirrors')">
<div v-for="item in countItem.mirrors" :key="item" :value="item" :label="item">
<div class="mt-1">
<el-tag>{{ item }}</el-tag>
</div>
</div>
</div>
</el-descriptions-item>
</el-descriptions>
<el-button class="mt-2" type="primary" link @click="goRouter('ContainerSetting')">
<el-icon class="mr-1"><Position /></el-icon>
{{ $t('container.goSetting') }}
</el-button>
</template>
</CardWithHeader>
</el-descriptions-item>
</el-descriptions>
<el-button class="mt-2" type="primary" link @click="goRouter('ContainerSetting')">
<el-icon class="mr-1"><Position /></el-icon>
{{ $t('container.goSetting') }}
</el-button>
</template>
</CardWithHeader>
</div>
</div>
</template>
<script lang="ts" setup>
import { loadContainerStatus, loadDaemonJson } from '@/api/modules/container';
import DockerStatus from '@/views/container/docker-status/index.vue';
import { getSettingInfo } from '@/api/modules/setting';
import router from '@/routers';
import { computeSize } from '@/utils/util';
import { onMounted, reactive, ref } from 'vue';
const loading = ref();
const isActive = ref(false);
const countItem = reactive({
all: 0,
created: 0,
@@ -138,6 +144,14 @@ const countItem = reactive({
sockPath: '',
});
const search = () => {
if (!isActive.value) {
return;
}
loadContainerCount();
loadContainerSetting();
};
const loadContainerCount = async () => {
await loadContainerStatus().then((res) => {
countItem.all = res.data.all;
@@ -173,8 +187,7 @@ const goRouter = async (val: string) => {
};
onMounted(() => {
loadContainerCount();
loadContainerSetting();
search();
});
</script>
@@ -20,6 +20,7 @@ const loadStatus = async () => {
await loadDockerStatus()
.then((res) => {
isActive.value = res.data === 'Running';
em('update:loading', false);
em('update:is-active', isActive.value);
em('search');
em('mounted');
@@ -90,9 +90,13 @@
<el-table-column :label="$t('commons.table.name')" show-overflow-tooltip prop="fileName" />
<el-table-column :label="$t('app.source')" prop="backupType">
<template #default="{ row }">
<span v-if="row.source">
{{ $t('setting.' + row.source) }}
<span v-if="row.accountType === 'LOCAL'">
{{ $t('setting.LOCAL') }}
</span>
<span v-if="row.accountType && row.accountType !== 'LOCAL'">
{{ $t('setting.' + row.accountType) + ' - ' + row.accountName }}
</span>
<span v-if="!row.accountType">-</span>
</template>
</el-table-column>
<el-table-column :label="$t('file.dir')" show-overflow-tooltip prop="fileDir" />
@@ -205,7 +209,7 @@ const onBackup = async () => {
};
const onRecover = async () => {
let param = {
downloadAccountID: currentRow.value.source,
downloadAccountID: currentRow.value.downloadAccountID,
type: 'redis',
name: database.value,
detailName: '',
@@ -1,74 +0,0 @@
<template>
<DialogPro v-model="open" :title="$t('commons.button.delete')" size="small">
<el-form ref="deleteRef" v-loading="loading" @submit.prevent>
<el-form-item>
<el-alert :title="$t('license.deleteHelper')" :closable="false" type="warning" />
</el-form-item>
<el-form-item>
<el-checkbox v-model="form.forceDelete" :label="$t('database.unBindForce')" />
<span class="input-help">
{{ $t('license.forceDelete') }}
</span>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="open = false" :disabled="loading">
{{ $t('commons.button.cancel') }}
</el-button>
<el-button type="primary" @click="submit" :disabled="loading">
{{ $t('commons.button.confirm') }}
</el-button>
</span>
</template>
</DialogPro>
</template>
<script lang="ts" setup>
import { FormInstance } from 'element-plus';
import { ref } from 'vue';
import i18n from '@/lang';
import { MsgSuccess } from '@/utils/message';
import { deleteLicense } from '@/api/modules/setting';
let form = reactive({
id: 0,
licenseName: '',
forceDelete: false,
});
let open = ref(false);
let loading = ref(false);
const deleteRef = ref<FormInstance>();
interface DialogProps {
id: number;
name: string;
database: string;
}
const emit = defineEmits<{ (e: 'search'): void }>();
const acceptParams = async (prop: DialogProps) => {
form.id = prop.id;
form.licenseName = prop.name;
form.forceDelete = false;
open.value = true;
};
const submit = async () => {
loading.value = true;
deleteLicense(form.id, form.forceDelete)
.then(() => {
loading.value = false;
emit('search');
MsgSuccess(i18n.global.t('commons.msg.deleteSuccess'));
open.value = false;
})
.catch(() => {
loading.value = false;
});
};
defineExpose({
acceptParams,
});
</script>
+40 -24
View File
@@ -83,8 +83,19 @@
<LicenseImport ref="licenseRef" />
<LicenseBind ref="bindRef" />
<LicenseDelete ref="delRef" @search="search" />
<OpDialog ref="opRef" @search="search" />
<OpDialog ref="opRef2" @search="search" @submit="submitUnbind">
<template #content>
<el-form class="mt-4 mb-1" ref="deleteForm" label-position="left">
<el-form-item>
<el-checkbox v-model="forceUnbind" :label="$t('license.forceUnbind')" />
<span class="input-help">
{{ $t('license.forceUnbindHelper') }}
</span>
</el-form-item>
</el-form>
</template>
</OpDialog>
</div>
</template>
@@ -92,7 +103,6 @@
import { ref, reactive, onMounted } from 'vue';
import { deleteLicense, searchLicense, syncLicense, unbindLicense } from '@/api/modules/setting';
import LicenseImport from '@/components/license-import/index.vue';
import LicenseDelete from '@/views/setting/license/delete/index.vue';
import LicenseBind from '@/views/setting/license/bind/index.vue';
import { dateFormat } from '@/utils/util';
import i18n from '@/lang';
@@ -103,9 +113,11 @@ import { initFavicon } from '@/utils/xpack';
const globalStore = GlobalStore();
const loading = ref();
const licenseRef = ref();
const delRef = ref();
const bindRef = ref();
const opRef = ref();
const opRef2 = ref();
const forceUnbind = ref();
const unbindRow = ref();
const data = ref();
const paginationConfig = reactive({
@@ -141,29 +153,33 @@ const onSync = async (row: any) => {
};
const onUnbind = async (row: any) => {
ElMessageBox.confirm(i18n.global.t('license.unbindHelper'), i18n.global.t('commons.button.unbind'), {
confirmButtonText: i18n.global.t('commons.button.confirm'),
cancelButtonText: i18n.global.t('commons.button.cancel'),
type: 'info',
}).then(async () => {
loading.value = true;
await unbindLicense(row.id)
.then(() => {
loading.value = false;
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
if (row.freeCount !== 0) {
globalStore.isProductPro = false;
initFavicon();
window.location.reload();
return;
}
search();
})
.catch(() => {
loading.value = false;
});
unbindRow.value = row;
opRef2.value.acceptParams({
title: i18n.global.t('commons.button.unbind'),
names: [row.licenseName],
msg: i18n.global.t('license.unbindHelper'),
api: null,
params: null,
});
};
const submitUnbind = async () => {
loading.value = true;
await unbindLicense(unbindRow.value.id)
.then(() => {
loading.value = false;
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
if (unbindRow.value.freeCount !== 0) {
globalStore.isMasterProductPro = false;
initFavicon();
window.location.reload();
return;
}
search();
})
.catch(() => {
loading.value = false;
});
};
const search = async () => {
loading.value = true;