diff --git a/bigtop-manager-ui/src/api/host/index.ts b/bigtop-manager-ui/src/api/host/index.ts index 57c1ecd34..869d4c91f 100644 --- a/bigtop-manager-ui/src/api/host/index.ts +++ b/bigtop-manager-ui/src/api/host/index.ts @@ -17,66 +17,50 @@ * under the License. */ -import request from '@/api/request.ts' import type { HostListParams, HostParams, HostVO, HostVOList, InstalledStatusVO } from '@/api/host/types' import type { ComponentVO } from '@/api/component/types.ts' +import { get, post, del, put } from '@/api/request-util' -export const getHosts = (params?: HostListParams): Promise => { - return request({ - method: 'get', - url: '/hosts', - params - }) +export const getHosts = (params?: HostListParams) => { + return get('/hosts', params) } -export const getHost = (pathParams: { id: number }): Promise => { - return request({ - method: 'get', - url: `/hosts/${pathParams.id}` - }) + +export const getHost = (pathParams: { id: number }) => { + return get(`/hosts/${pathParams.id}`) } export const addHost = (data: HostParams): Promise => { - return request({ - method: 'post', - url: '/hosts', - data - }) + return post('/hosts', data) } export const installDependencies = (data: HostParams) => { - return request({ - method: 'post', - url: '/hosts/install-dependencies', - data - }) + return post('/hosts/install-dependencies', data) } -export const getInstalledStatus = (): Promise => { - return request({ - method: 'get', - url: '/hosts/installed-status' - }) +export const getInstalledStatus = () => { + return get('/hosts/installed-status') } -export const updateHost = (data: HostParams): Promise => { - return request({ - method: 'put', - url: `/hosts/${data.id}`, - data - }) +export const updateHost = (data: HostParams) => { + return put(`/hosts/${data.id}`, data) } -export const removeHost = (data: { ids: number[] }): Promise => { - return request({ - method: 'delete', - url: '/hosts/batch', - data - }) +export const removeHost = (data: { ids: number[] }) => { + return del('/hosts/batch', { data }) } export const getComponentsByHost = (pathParams: { id: number }): Promise => { - return request({ - method: 'get', - url: `/hosts/${pathParams.id}/components` - }) + return get(`/hosts/${pathParams.id}/components`) +} + +export const startAgent = (pathParams: { id: number }) => { + return post(`/hosts/${pathParams.id}/start-agent`) +} + +export const restartAgent = (pathParams: { id: number }) => { + return post(`/hosts/${pathParams.id}/restart-agent`) +} + +export const stopAgent = (pathParams: { id: number }) => { + return post(`/hosts/${pathParams.id}/stop-agent`) } diff --git a/bigtop-manager-ui/src/composables/use-modal.ts b/bigtop-manager-ui/src/composables/use-modal.ts new file mode 100644 index 000000000..978e031cd --- /dev/null +++ b/bigtop-manager-ui/src/composables/use-modal.ts @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import SvgIcon from '@/components/base/svg-icon/index.vue' +import { Modal, ModalFuncProps } from 'ant-design-vue' + +interface ConfirmModalProps extends ModalFuncProps { + tipText?: string +} + +const DEFAULT_STYLE = { top: '30vh' } + +export const useModal = () => { + function confirmModal({ tipText, onOk, ...rest }: ConfirmModalProps) { + return Modal.confirm({ + title: () => + h('div', { style: { display: 'flex' } }, [ + h(SvgIcon, { name: 'unknown', style: { width: '24px', height: '24px' } }), + h('p', tipText ?? '') + ]), + style: DEFAULT_STYLE, + icon: null, + ...rest, + onOk: async () => { + try { + if (onOk) { + await onOk() + } + } catch (e) { + console.error('Modal onOk error:', e) + } + return Promise.resolve() + } + }) + } + + return { + confirmModal, + destroyAllModal: Modal.destroyAll + } +} diff --git a/bigtop-manager-ui/src/composables/use-tab-state.ts b/bigtop-manager-ui/src/composables/use-tab-state.ts new file mode 100644 index 000000000..b005cf46b --- /dev/null +++ b/bigtop-manager-ui/src/composables/use-tab-state.ts @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { useTabStore } from '@/store/tab-state' + +/** + * Combined functions that manage tab state + * @param pageKey Page unique identifier + * @param defaultIndex The default selected tab + */ +export function useTabState(pageKey: string, defaultIndex = '0') { + const route = useRoute() + const tabStore = useTabStore() + + const activeTab = ref(defaultIndex) + + // Initialize tabIndex: Preferred from URL query, followed by store + onMounted(() => { + const queryTab = route.query.tab as string + activeTab.value = queryTab ?? tabStore.getActiveTab(pageKey) ?? activeTab.value + }) + + watch(activeTab, (val) => { + tabStore.setActiveTab(pageKey, val) + }) + + return { activeTab } +} diff --git a/bigtop-manager-ui/src/features/ai-assistant/chat-history.vue b/bigtop-manager-ui/src/features/ai-assistant/chat-history.vue index 77bcffd5f..20ce4b2c2 100644 --- a/bigtop-manager-ui/src/features/ai-assistant/chat-history.vue +++ b/bigtop-manager-ui/src/features/ai-assistant/chat-history.vue @@ -20,9 +20,7 @@ import { useAiChatStore } from '@/store/ai-assistant' import { formatTime } from '@/utils/transform' import { EllipsisOutlined } from '@ant-design/icons-vue' - import { message, Modal, Empty } from 'ant-design-vue' - - import SvgIcon from '@/components/base/svg-icon/index.vue' + import { message, Empty } from 'ant-design-vue' import type { ChatThread, ThreadId } from '@/api/ai-assistant/types' @@ -39,6 +37,7 @@ type ThreadOperationHandler = Record<'delete' | 'rename', (thread: ChatThread, idx: number) => void> const { t } = useI18n() + const { confirmModal } = useModal() const aiChatStore = useAiChatStore() const { threads, currThread, threadLimit } = storeToRefs(aiChatStore) const props = defineProps() @@ -100,14 +99,8 @@ } const handleDeleteConfirm = (thread: ChatThread, idx: number) => { - Modal.confirm({ - title: () => - h('div', { style: { display: 'flex' } }, [ - h(SvgIcon, { name: 'unknown', style: { width: '24px', height: '24px' } }), - h('p', t('common.delete_msg')) - ]), - style: { top: '30vh' }, - icon: null, + confirmModal({ + tipText: t('common.delete_msg'), async onOk() { const success = await aiChatStore.deleteChatThread(thread) if (success) { diff --git a/bigtop-manager-ui/src/features/create-cluster/index.vue b/bigtop-manager-ui/src/features/create-cluster/index.vue index e90875f85..9b3e21327 100644 --- a/bigtop-manager-ui/src/features/create-cluster/index.vue +++ b/bigtop-manager-ui/src/features/create-cluster/index.vue @@ -23,8 +23,6 @@ import { getInstalledStatus, installDependencies } from '@/api/host' import { execCommand } from '@/api/command' - import SvgIcon from '@/components/base/svg-icon/index.vue' - import ClusterBase from './components/cluster-base.vue' import ComponentInfo from './components/component-info.vue' import HostManage from './components/host-manage.vue' @@ -34,6 +32,7 @@ import type { ClusterCommandReq, CommandRequest, CommandVO, HostReq } from '@/api/command/types' const { t } = useI18n() + const { confirmModal } = useModal() const menuStore = useMenuStore() const compRef = ref() @@ -201,12 +200,8 @@ onBeforeRouteLeave((_to, _from, next) => { if (current.value === stepsLimit.value && !isDone.value) { - Modal.confirm({ - title: () => - h('div', { style: { display: 'flex' } }, [ - h(SvgIcon, { name: 'unknown', style: { width: '24px', height: '24px' } }), - h('span', t('common.exit_confirm')) - ]), + confirmModal({ + tipText: t('common.exit_confirm'), content: h('div', { style: { paddingLeft: '36px' } }, t('common.installing_exit_confirm_content')), cancelText: t('common.no'), style: { top: '30vh' }, diff --git a/bigtop-manager-ui/src/features/create-service/index.vue b/bigtop-manager-ui/src/features/create-service/index.vue index 2340b7dae..3b2dd63a6 100644 --- a/bigtop-manager-ui/src/features/create-service/index.vue +++ b/bigtop-manager-ui/src/features/create-service/index.vue @@ -25,9 +25,10 @@ import ComponentAssigner from './components/component-assigner.vue' import ServiceConfigurator from './components/service-configurator.vue' import ComponentInstaller from './components/component-installer.vue' - import SvgIcon from '@/components/base/svg-icon/index.vue' const { t } = useI18n() + const { confirmModal } = useModal() + const route = useRoute() const createStore = useCreateServiceStore() const { current, stepsLimit, stepContext, selectedServices, createdPayload } = storeToRefs(createStore) @@ -136,12 +137,8 @@ onBeforeRouteLeave((_to, _from, next) => { if (current.value === stepsLimit.value && !isDone.value) { - Modal.confirm({ - title: () => - h('div', { style: { display: 'flex' } }, [ - h(SvgIcon, { name: 'unknown', style: { width: '24px', height: '24px' } }), - h('span', t('common.exit_confirm')) - ]), + confirmModal({ + tipText: t('common.exit_confirm'), content: h('div', { style: { paddingLeft: '36px' } }, t('common.installing_exit_confirm_content')), cancelText: t('common.no'), style: { top: '30vh' }, diff --git a/bigtop-manager-ui/src/features/job/index.vue b/bigtop-manager-ui/src/features/job/index.vue index 52c7ab642..9003f5ce1 100644 --- a/bigtop-manager-ui/src/features/job/index.vue +++ b/bigtop-manager-ui/src/features/job/index.vue @@ -18,10 +18,9 @@ -->