@ithinkdt/app
@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
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 | |
| 4.1.4 | >=3.5 | MIT | |
| 4.1.3 | >=3.5 | MIT | |
| 4.1.2 | >=3.5 | MIT | |
| 4.1.1 | >=3.5 | MIT | |
| 4.1.0 | >=3.5 | MIT | |
| 4.0.5 | >=3.5 | MIT | |
| 4.0.4 | >=3.5 | MIT | |
| 4.0.3 | >=3.5 | MIT | |
| 4.0.2 | >=3.5 | MIT | |
| 4.0.1 | >=3.5 | MIT | |
| 4.0.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 | |
| 4.0.0-600 | >=3.5 | MIT | |
| 4.0.0-500 | >=3.5 | MIT | |
| 4.0.0-400 | >=3.5 | MIT | |
| 4.0.0-300 | >=3.5 | MIT | |
| 4.0.0-202 | >=3.5 | MIT | |
| 4.0.0-201 | >=3.5 | MIT | |
| 4.0.0-200 | >=3.5 | MIT | |
| 4.0.0-100 | >=3.5 | MIT | |
| 4.0.0-50 | >=3.5 | MIT | |
| 4.0.0-41 | >=3.5 | MIT | |
| 4.0.0-40 | >=3.5 | MIT | |
| 4.0.0-33 | >=3.5 | MIT | |
| 4.0.0-30 | >=3.5 | MIT | |
| 4.0.0-14 | >=3.5 | MIT | |
| 4.0.0-13 | >=3.5 | MIT | |
| 4.0.0-12 | >=3.5 | MIT | |
| 4.0.0-11 | >=3.5 | MIT | |
| 4.0.0-10 | >=3.5 | MIT | |
| 4.0.0-9 | >=3.5 | MIT |