feat: add useGlobalApp composable and integrate it into various components for improved message handling

This commit is contained in:
0xJacky
2025-09-06 03:46:32 +00:00
parent 66ba546710
commit 0c83303953
37 changed files with 46 additions and 36 deletions

View File

@@ -87,6 +87,7 @@ export default {
"useAttrs": true,
"useCssModule": true,
"useCssVars": true,
"useGlobalApp": true,
"useId": true,
"useLink": true,
"useModel": true,

View File

@@ -82,6 +82,7 @@ declare global {
const useAttrs: typeof import('vue')['useAttrs']
const useCssModule: typeof import('vue')['useCssModule']
const useCssVars: typeof import('vue')['useCssVars']
const useGlobalApp: typeof import('@/composables/useGlobalApp')['useGlobalApp']
const useId: typeof import('vue')['useId']
const useLink: typeof import('vue-router')['useLink']
const useModel: typeof import('vue')['useModel']
@@ -176,6 +177,7 @@ declare module 'vue' {
readonly useAttrs: UnwrapRef<typeof import('vue')['useAttrs']>
readonly useCssModule: UnwrapRef<typeof import('vue')['useCssModule']>
readonly useCssVars: UnwrapRef<typeof import('vue')['useCssVars']>
readonly useGlobalApp: UnwrapRef<typeof import('@/composables/useGlobalApp')['useGlobalApp']>
readonly useId: UnwrapRef<typeof import('vue')['useId']>
readonly useLink: UnwrapRef<typeof import('vue-router')['useLink']>
readonly useModel: UnwrapRef<typeof import('vue')['useModel']>

View File

@@ -3,7 +3,6 @@ import type { Key } from 'ant-design-vue/es/_util/type'
import type { ConfigBackup } from '@/api/config'
import type { GetListResponse } from '@/api/curd'
import { datetimeRender, StdPagination } from '@uozi-admin/curd'
import { message } from 'ant-design-vue'
import config from '@/api/config'
// Define props for the component
@@ -14,6 +13,7 @@ const props = defineProps<{
// Define modal props using defineModel with boolean type
const visible = defineModel<boolean>('visible')
const currentContent = defineModel<string>('currentContent')
const { message } = useGlobalApp()
// Import DiffViewer asynchronously with loading options
const DiffViewer = defineAsyncComponent({

View File

@@ -1,6 +1,5 @@
<script setup lang="ts">
import type { Namespace } from '@/api/namespace'
import { message } from 'ant-design-vue'
import namespaceApi from '@/api/namespace'
import nodeApi from '@/api/node'
import { useNodeAvailabilityStore } from '@/pinia/moudule/nodeAvailability'
@@ -12,6 +11,7 @@ defineProps<{
const modelValue = defineModel<string | number>('activeKey')
const nodeStore = useNodeAvailabilityStore()
const namespaces = ref<Namespace[]>([])
const { message } = useGlobalApp()
// Load all namespaces on mount (handle pagination)
async function loadAllNamespaces() {

View File

@@ -1,7 +1,6 @@
<script setup lang="ts">
import type { NgxDirective } from '@/api/ngx'
import { DeleteOutlined, HolderOutlined, InfoCircleOutlined } from '@ant-design/icons-vue'
import { message } from 'ant-design-vue'
import config from '@/api/config'
import CodeEditor from '@/components/CodeEditor'
import { Include } from '..'
@@ -15,6 +14,7 @@ const props = defineProps<{
}>()
const emit = defineEmits(['remove'])
const { message } = useGlobalApp()
const directiveStore = useDirectiveStore()
const { curIdx } = storeToRefs(directiveStore)

View File

@@ -1,6 +1,6 @@
<script setup lang="ts">
import type { PortInfo, PortScanRequest } from '@/api/port_scan'
import { Badge, message } from 'ant-design-vue'
import { Badge } from 'ant-design-vue'
import portScan from '@/api/port_scan'
interface FormData {
@@ -13,6 +13,7 @@ const formData = reactive<FormData>({
startPort: 80,
endPort: 8080,
})
const { message } = useGlobalApp()
const tableData = ref<PortInfo[]>([])
const pagination = reactive({

View File

@@ -2,7 +2,6 @@
import type { UploadFile } from 'ant-design-vue'
import type { RestoreOptions, RestoreResponse } from '@/api/backup'
import { InboxOutlined } from '@ant-design/icons-vue'
import { message } from 'ant-design-vue'
import backup from '@/api/backup'
// Define props using TypeScript interface
@@ -23,6 +22,7 @@ withDefaults(defineProps<SystemRestoreProps>(), {
})
const emit = defineEmits<SystemRestoreEmits>()
const { message } = useGlobalApp()
// Use UploadFile from ant-design-vue
const uploadFiles = ref<UploadFile[]>([])

View File

@@ -1,7 +1,6 @@
import { Modal } from 'ant-design-vue'
import twoFA from '@/api/2fa'
import Authorization from '@/components/TwoFA/Authorization.vue'
import { useGlobalApp } from '@/composables/useGlobalApp'
import { useUserStore } from '@/pinia'
function use2FAModal() {

View File

@@ -1,7 +1,6 @@
<script setup lang="ts">
import { DesktopOutlined, HomeOutlined, LogoutOutlined, MenuUnfoldOutlined } from '@ant-design/icons-vue'
import { useElementSize } from '@vueuse/core'
import { message } from 'ant-design-vue'
import auth from '@/api/auth'
import NginxControl from '@/components/NginxControl'
import Notification from '@/components/Notification'
@@ -15,6 +14,7 @@ const emit = defineEmits<{
}>()
const router = useRouter()
const { message } = useGlobalApp()
function logout() {
auth.logout().then(() => {

View File

@@ -1,5 +1,4 @@
import type { CosyError, CosyErrorRecord } from './types'
import { useGlobalApp } from '@/composables/useGlobalApp'
const errors: Record<string, CosyErrorRecord> = {}

View File

@@ -2,12 +2,12 @@
import type { AutoBackup } from '@/api/backup'
import { CheckCircleOutlined, LoadingOutlined } from '@ant-design/icons-vue'
import { message } from 'ant-design-vue'
import { testS3Connection } from '@/api/backup'
const modelValue = defineModel<AutoBackup>({ default: reactive({
storage_type: 'local',
}) as AutoBackup })
const { message } = useGlobalApp()
const isLocalStorage = computed(() => modelValue.value.storage_type === 'local')
const isS3Storage = computed(() => modelValue.value.storage_type === 's3')

View File

@@ -2,7 +2,6 @@
import { CheckOutlined, CopyOutlined, InfoCircleFilled, WarningOutlined } from '@ant-design/icons-vue'
import { UseClipboard } from '@vueuse/components'
import backup from '@/api/backup'
import { useGlobalApp } from '@/composables/useGlobalApp'
const { message } = useGlobalApp()

View File

@@ -1,7 +1,8 @@
<script setup lang="ts">
import { message } from 'ant-design-vue'
import SystemRestoreContent from '@/components/SystemRestore/SystemRestoreContent.vue'
const { message } = useGlobalApp()
function handleRestoreSuccess(options: { restoreNginx: boolean, restoreNginxUI: boolean }): void {
// Only redirect to login page if Nginx UI was restored
if (options.restoreNginxUI) {

View File

@@ -1,7 +1,6 @@
<script setup lang="ts">
import type { Config } from '@/api/config'
import { HistoryOutlined } from '@ant-design/icons-vue'
import { message } from 'ant-design-vue'
import { trim, trimEnd } from 'lodash'
import config from '@/api/config'
import ngx from '@/api/ngx'
@@ -13,6 +12,7 @@ import InspectConfig from '@/views/config/InspectConfig.vue'
const route = useRoute()
const router = useRouter()
const { message } = useGlobalApp()
const origName = ref('')
const addMode = computed(() => !route.params.name)

View File

@@ -1,5 +1,4 @@
<script setup lang="ts">
import { message } from 'ant-design-vue'
import config from '@/api/config'
import use2FAModal from '@/components/TwoFA/use2FAModal'
@@ -10,6 +9,7 @@ const props = defineProps<{
const name = defineModel<string>('name', { default: '' })
const router = useRouter()
const { message } = useGlobalApp()
const modify = ref(false)
const buffer = ref('')

View File

@@ -1,5 +1,4 @@
<script setup lang="ts">
import { message } from 'ant-design-vue'
import config from '@/api/config'
import NodeSelector from '@/components/NodeSelector'
import use2FAModal from '@/components/TwoFA/use2FAModal'
@@ -7,6 +6,7 @@ import { urlJoin } from '@/lib/helper'
import { isProtectedPath } from '@/views/config/configUtils'
const emit = defineEmits(['deleted'])
const { message } = useGlobalApp()
const visible = ref(false)
const confirmText = ref('')

View File

@@ -1,9 +1,9 @@
<script setup lang="ts">
import { message } from 'ant-design-vue'
import config from '@/api/config'
import use2FAModal from '@/components/TwoFA/use2FAModal'
const emit = defineEmits(['created'])
const { message } = useGlobalApp()
const visible = ref(false)
const data = ref({

View File

@@ -1,10 +1,10 @@
<script setup lang="ts">
import { message } from 'ant-design-vue'
import config from '@/api/config'
import NodeSelector from '@/components/NodeSelector'
import use2FAModal from '@/components/TwoFA/use2FAModal'
const emit = defineEmits(['renamed'])
const { message } = useGlobalApp()
const visible = ref(false)
const isDirFlag = ref(false)

View File

@@ -2,7 +2,6 @@
import type ReconnectingWebSocket from 'reconnecting-websocket'
import type { SiteInfo } from '@/api/site_navigation'
import { GlobalOutlined } from '@ant-design/icons-vue'
import { message } from 'ant-design-vue'
import Sortable from 'sortablejs'
import { siteNavigationApi } from '@/api/site_navigation'
import SiteCard from './components/SiteCard.vue'
@@ -10,6 +9,7 @@ import SiteHealthCheckModal from './components/SiteHealthCheckModal.vue'
import SiteNavigationToolbar from './components/SiteNavigationToolbar.vue'
const sites = ref<SiteInfo[]>([])
const { message } = useGlobalApp()
const loading = ref(true)
const refreshing = ref(false)
const isConnected = ref(false)

View File

@@ -3,13 +3,13 @@ import type { NginxConfigInfo, NginxPerfOpt } from '@/api/ngx'
import {
SettingOutlined,
} from '@ant-design/icons-vue'
import { message } from 'ant-design-vue'
import ngx from '@/api/ngx'
import PerformanceConfig from './ParamsOpt/PerformanceConfig.vue'
import ProxyCacheConfig from './ParamsOpt/ProxyCacheConfig.vue'
// Performance settings modal
const visible = ref(false)
const { message } = useGlobalApp()
const loading = ref(false)
const data = ref<NginxConfigInfo>({
worker_processes: '4',

View File

@@ -1,7 +1,6 @@
<script setup lang="ts">
import type { EnhancedHealthCheckConfig, HeaderItem, SiteInfo } from '@/api/site_navigation'
import { CloseOutlined, PlusOutlined } from '@ant-design/icons-vue'
import { message } from 'ant-design-vue'
import { siteNavigationApi } from '@/api/site_navigation'
interface Props {
@@ -17,6 +16,7 @@ interface Emits {
const props = defineProps<Props>()
const emit = defineEmits<Emits>()
const { message } = useGlobalApp()
const testing = ref(false)

View File

@@ -1,11 +1,12 @@
<script setup lang="ts">
import { LockOutlined, MailOutlined, UserOutlined } from '@ant-design/icons-vue'
import { Form, message } from 'ant-design-vue'
import { Form } from 'ant-design-vue'
import install from '@/api/install'
const emit = defineEmits<{
(e: 'installSuccess'): void
}>()
const { message } = useGlobalApp()
const router = useRouter()
const loading = ref(false)

View File

@@ -1,5 +1,4 @@
<script setup lang="ts">
import { message } from 'ant-design-vue'
import install from '@/api/install'
import SelfCheck, { useSelfCheckStore } from '@/components/SelfCheck'
import SystemRestoreContent from '@/components/SystemRestore'
@@ -11,6 +10,7 @@ import TimeoutAlert from './TimeoutAlert.vue'
const installTimeout = ref(false)
const activeTab = ref('1')
const step = ref(1)
const { message } = useGlobalApp()
const selfCheckStore = useSelfCheckStore()
const { hasError, loading } = storeToRefs(selfCheckStore)

View File

@@ -1,12 +1,12 @@
<script setup lang="tsx">
import { StdCurd } from '@uozi-admin/curd'
import { message } from 'ant-design-vue'
import nodeApi from '@/api/node'
import FooterToolBar from '@/components/FooterToolbar'
import BatchUpgrader from './BatchUpgrader.vue'
import envColumns from './nodeColumns'
const route = useRoute()
const { message } = useGlobalApp()
const curd = ref()
const loadingFromSettings = ref(false)
const loadingReload = ref(false)

View File

@@ -1,11 +1,11 @@
<script setup lang="ts">
import { StdCurd } from '@uozi-admin/curd'
import { message } from 'ant-design-vue'
import notification from '@/api/notification'
import { useUserStore } from '@/pinia'
import notificationColumns from './notificationColumns'
const { unreadCount } = storeToRefs(useUserStore())
const { message } = useGlobalApp()
const curd = useTemplateRef('curd')
function clear() {

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import { KeyOutlined, LockOutlined, UserOutlined } from '@ant-design/icons-vue'
import { startAuthentication } from '@simplewebauthn/browser'
import { Form, message } from 'ant-design-vue'
import { Form } from 'ant-design-vue'
import auth from '@/api/auth'
import install from '@/api/install'
import passkey from '@/api/passkey'
@@ -23,6 +23,7 @@ install.get_lock().then(async (r: { lock: boolean }) => {
})
const loading = ref(false)
const { message } = useGlobalApp()
const enabled2FA = ref(false)
const refOTP = useTemplateRef('refOTP')
const passcode = ref('')

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import type { SelectValue } from 'ant-design-vue/es/select'
import type { SiteStatus } from '@/api/site'
import { message, Modal } from 'ant-design-vue'
import { Modal } from 'ant-design-vue'
import site from '@/api/site'
import { ConfigStatus } from '@/constants'
@@ -20,6 +20,7 @@ const status = defineModel<string>({
default: ConfigStatus.Disabled,
})
const { message } = useGlobalApp()
const [modal, ContextHolder] = Modal.useModal()
// Computed property for select style based on current status

View File

@@ -1,5 +1,4 @@
<script setup lang="ts">
import { message } from 'ant-design-vue'
import ngx from '@/api/ngx'
import site from '@/api/site'
import NgxConfigEditor, { DirectiveEditor, LocationEditor, useNgxConfigStore } from '@/components/NgxConfigEditor'
@@ -9,6 +8,7 @@ import EnableTLS from '../site_edit/components/EnableTLS'
import { useSiteEditorStore } from '../site_edit/components/SiteEditor/store'
const currentStep = ref(0)
const { message } = useGlobalApp()
onMounted(() => {
init()

View File

@@ -2,7 +2,7 @@
import type { AutoCertOptions } from '@/api/auto_cert'
import type { CertificateResult } from '@/api/cert'
import type { PrivateKeyType } from '@/constants'
import { message, Modal } from 'ant-design-vue'
import { Modal } from 'ant-design-vue'
import { AutoCertChallengeMethod } from '@/api/auto_cert'
import site from '@/api/site'
import AutoCertStepOne from '@/components/AutoCertForm'
@@ -16,6 +16,7 @@ const props = defineProps<{
}>()
const editorStore = useSiteEditorStore()
const { message } = useGlobalApp()
const { ngxConfig, issuingCert, curServerDirectives, curDirectivesMap, isDefaultServer, hasWildcardServerName, hasExplicitIpAddress, isIpCertificate, needsManualIpInput } = storeToRefs(editorStore)
const autoCert = defineModel<boolean>('autoCert')

View File

@@ -1,5 +1,4 @@
<script setup lang="ts">
import { message } from 'ant-design-vue'
import site from '@/api/site'
const props = defineProps<{
@@ -7,6 +6,7 @@ const props = defineProps<{
}>()
const router = useRouter()
const { message } = useGlobalApp()
const modify = ref(false)
const buffer = ref('')

View File

@@ -1,6 +1,5 @@
<script setup lang="ts">
import { Form, message } from 'ant-design-vue'
import { Form } from 'ant-design-vue'
import site from '@/api/site'
import gettext from '@/gettext'
@@ -10,6 +9,7 @@ const props = defineProps<{
}>()
const emit = defineEmits(['update:visible', 'duplicated'])
const { message } = useGlobalApp()
const show = computed({
get() {

View File

@@ -1,6 +1,5 @@
<script setup lang="tsx">
import { StdCurd } from '@uozi-admin/curd'
import { message } from 'ant-design-vue'
import stream from '@/api/stream'
import NamespaceTabs from '@/components/NamespaceTabs'
import InspectConfig from '@/views/config/InspectConfig.vue'
@@ -9,6 +8,7 @@ import StreamDuplicate from '@/views/stream/components/StreamDuplicate.vue'
const route = useRoute()
const router = useRouter()
const { message } = useGlobalApp()
const curd = ref()
const inspect_config = ref()

View File

@@ -1,5 +1,4 @@
<script setup lang="ts">
import { message } from 'ant-design-vue'
import stream from '@/api/stream'
const props = defineProps<{
@@ -7,6 +6,7 @@ const props = defineProps<{
}>()
const router = useRouter()
const { message } = useGlobalApp()
const modify = ref(false)
const buffer = ref('')

View File

@@ -1,6 +1,5 @@
<script setup lang="ts">
import { Form, message } from 'ant-design-vue'
import { Form } from 'ant-design-vue'
import stream from '@/api/stream'
import gettext from '@/gettext'
@@ -9,6 +8,7 @@ const props = defineProps<{
}>()
const emit = defineEmits(['duplicated'])
const { message } = useGlobalApp()
const visible = defineModel<boolean>('visible')

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import type { SiteStatus } from '@/api/site'
import type { CheckedType } from '@/types'
import { message, Modal } from 'ant-design-vue'
import { Modal } from 'ant-design-vue'
import stream from '@/api/stream'
import { ConfigStatus } from '@/constants'
@@ -17,6 +17,7 @@ const emit = defineEmits<{
// Use defineModel for v-model binding
const status = defineModel<SiteStatus>('status')
const { message } = useGlobalApp()
const [modal, ContextHolder] = Modal.useModal()

View File

@@ -1,7 +1,6 @@
<script setup lang="tsx">
import type { TwoFAStatus } from '@/api/2fa'
import type { RecoveryCode } from '@/api/recovery'
import { message } from 'ant-design-vue'
import twoFA from '@/api/2fa'
import { use2FAModal } from '@/components/TwoFA'
import { useUserStore } from '@/pinia'
@@ -9,6 +8,7 @@ import { Passkey, RecoveryCodes, TOTP } from '@/views/preference/components/Auth
const twoFAStatus = ref<TwoFAStatus>({} as TwoFAStatus)
const recoveryCodes = ref<RecoveryCode[]>()
const { message } = useGlobalApp()
const userStore = useUserStore()
const { info } = storeToRefs(userStore)

View File

@@ -58,6 +58,9 @@ export default defineConfig(({ mode }) => {
{
'@/language': ['T'],
},
{
'@/composables/useGlobalApp': ['useGlobalApp'],
},
{
'ant-design-vue': [
'App',