@ithinkdt/app

iThinkDT 应用核心包
4,939
Install
npm install @ithinkdt/app
Latest Version:4.2.4
Vue:3
License:MIT
Last Updated:Aug 14, 2026
Links: npm
Maintainer: liuzw2579

@ithinkdt/app

许可证

MIT

安装

npm i @ithinkdt/app

需要您自行安装依赖 vue@3 与 vue-router@4。

介绍

@ithinkdt/app 提供 iThinkDT 应用层的核心能力,包括:

  • 应用状态注入与读取
  • 登录态与权限状态管理
  • 路由权限拦截
  • 多页签页面管理
  • 子应用上下文继承

初始化应用

注册插件

import { createApp } from 'vue'
import { createRouter, createWebHistory } from 'vue-router'
import appCore from '@ithinkdt/app'

import App from './App.vue'

const router = createRouter({
    history: createWebHistory(),
    routes: [
        {
            path: '/',
            component: () => import('./pages/home.vue'),
            meta: {
                requiresLogin: true,
            },
        },
        {
            path: '/users',
            component: () => import('./pages/users.vue'),
            meta: {
                requiresAuth: 'user:list',
            },
        },
    ],
})

const app = createApp(App)

app.use(appCore, {
    router,
    appCode: 'admin',
    appName: '管理后台',
    multiTab: true,
    i18n: true,
    supportLanguages: [
        { label: '简体中文', value: 'zh-CN' },
        { label: 'English', value: 'en-US' },
    ],
    language: 'zh-CN',
    mode: 'auto',
    vars: {
        colorPrimary: '#18a058',
    },
    auth: {
        async refresh(auth) {
            const me = await fetch('/api/me').then(res => res.json())

            auth.assign({
                user: me.user,
                resources: new Set(me.resources),
                accesses: me.accesses,
            })
        },
        async logout(auth) {
            await fetch('/api/logout', { method: 'POST' })
            auth.assign({
                user: undefined,
                resources: new Set(),
                accesses: {},
            })
        },
    },
})

app.use(router)
app.mount('#app')

路由权限

插件会根据路由 meta 自动判断访问权限(默认需要登录且具有路由path权限):

  • meta.requiresLogin = false:无须登录
  • meta.requiresAuth = false:登录后可访问
  • meta.requiresAuth = true:需要路由path权限
  • meta.requiresAuth = 'user:detail' 或 meta.requiresAuth = /user:需要指定的按钮或菜单权限
  • meta.requiresAuth = ['user:list', 'user:view']:满足其中任一权限即可

示例:

const routes = [
    {
        path: '/about',
        component: () => import('./pages/about.vue'),
        meta: {
            requiresLogin: false,
        },
    },
    {
        path: '/user/:id',
        component: () => import('./pages/user/[id].vue'),
        meta: {
            requiresAuth: 'user:detail',
        },
    },
]

活动路由

插件会根据路由 meta.activatedModule 自动设置活动的路由

const routes = [
    {
        path: '/user/:id/edit',
        component: () => import('./pages/user/[id].edit.vue'),
        meta: {
            requiresAuth: 'user:edit',
            activatedModule: '/users'
        },
    },
]

组合式 API

useApp 获取应用状态

declare function useApp<LoggedIn extends boolean = boolean>(
    app?: import('vue').App,
): UseAppReturn<LoggedIn>

示例:

import { computed } from 'vue'
import { useApp } from '@ithinkdt/app/use-app'

const app = useApp()

const pageTitle = computed(() => {
    return `${app.appName} - ${app.currentTab?.title ?? '首页'}`
})

app.assignVars({
    colorPrimary: '#2080f0',
})

app.openPage('/users')

useAuth 获取权限状态

declare function useAuth<LoggedIn extends boolean = boolean>(
    app?: import('vue').App,
): UseAuthReturn<LoggedIn>

示例:

import { computed, onMounted } from 'vue'
import { useAuth } from '@ithinkdt/app/use-auth'

const auth = useAuth()

onMounted(() => {
    void auth.refresh()
})

const canCreateUser = computed(() => auth.can('user:create'))
const canEditUser = computed(() => auth('user:edit'))
const currentUser = computed(() => auth.user?.nickname)

async function handleLogout() {
    await auth.logout()
}

usePageTab 获取当前页签

declare function usePageTab(app?: import('vue').App): AppPageTab

示例:

import { onMounted } from 'vue'
import { usePageTab } from '@ithinkdt/app/use-page-tab'

const tab = usePageTab()

onMounted(() => {
    tab.title = '用户详情'
})

async function reloadCurrentPage() {
    await tab.reload()
}

onPageClose 页面关闭前处理

declare function onPageClose(
    hook: (beforeunload?: boolean) => Awaitable<unknown>,
    options?: {
        hookWindowLeave?: boolean
    },
): void

示例:

import { ref } from 'vue'
import { onPageClose } from '@ithinkdt/app/use-page-tab'

const changed = ref(false)

onPageClose((beforeunload) => {
    if (!changed.value) return

    if (beforeunload) {
        return '当前页面有未保存内容'
    }

    return confirm('当前页面有未保存内容,确定离开吗?')
}, {
    hookWindowLeave: true,
})

路由上下文

useRouterContext 多页签路由包装

useRouterContext 用于配合 RouterView 渲染多页签页面,并暴露 keep-alive 相关状态。

declare function useRouterContext(): {
    AppRouterView: ...
    keepAlives: Ref<string[]>
    onTransitionStart: () => void
    onTransitionEnd: () => void
}

示例:

import { defineComponent } from 'vue'
import { useRouterContext } from '@ithinkdt/app'

export default defineComponent({
    name: 'AppLayout',
    setup() {
        const { AppRouterView } = useRouterContext()

        return () => (
            <AppRouterView
                name="app-page"
                mode="out-in"
                appear
            >
                {({ Content, status, reloading }) => (
                    <section class="page-container">
                        {status === 'forbidden'
                            ? <div>无权限访问当前页面</div>
                            : reloading
                                ? <div>页面重载中...</div>
                                : Content}
                    </section>
                )}
            </AppRouterView>
        )
    },
})

子应用

useSubApp 继承主应用上下文

当子应用和主应用共用同一个 vue-router、权限状态和应用状态时,可以在子应用入口调用 useSubApp。

declare function useSubApp(app: import('vue').App): void

示例:

import { useSubApp } from '@ithinkdt/app/sub'
import setup from '@/setup/common'

export default function subAppSetup(vueApp: import('vue').App) {
    if (!vueApp) {
        throw new Error(`[setup] 请传入当前 Vue App!`)
    }
    useSubApp(vueApp)
    return setup(vueApp)
}

自动导入

包内提供了自动导入配置:

declare const App: {
    from: string
    imports: (string | { name: string, type: boolean })[]
}[]

示例:

// unplugin-auto-import 配置示意
import AutoImport from 'unplugin-auto-import/vite'
import AppImports from '@ithinkdt/app/auto-imports'

export default {
    plugins: [
        AutoImport({
            imports: [
                ...AppImports,
            ],
        }),
    ],
}

Related Packages

@ithinkdt/page

iThinkDT Page

8,743
@ithinkdt/lowcode

iThinkDT Lowcode

8,150
@ithinkdt/editor

iThinkDT Cloud Editor

4,526
@ithinkdt/ui

iThinkDT UI

10,505
@ithinkdt/cloud

iThinkDT Cloud API

7,219

Version History

Version Released Vue License
4.2.4 >=3.5 MIT
4.2.3 >=3.5 MIT
4.2.2 >=3.5 MIT
4.2.1 >=3.5 MIT
4.2.0 >=3.5 MIT
Pre-releases (24)
Version Released Vue License
4.2.0-2 >=3.5 MIT
4.2.0-1 >=3.5 MIT
4.2.0-0 >=3.5 MIT
4.0.0-800 >=3.5 MIT
4.0.0-700 >=3.5 MIT