From cb39b45b62d9ef636ddceb30ed8b33e2620d9714 Mon Sep 17 00:00:00 2001 From: jingrow Date: Sun, 25 Jan 2026 03:20:53 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=94=A8=E6=88=B7=E6=9D=83?= =?UTF-8?q?=E9=99=90=E6=A3=80=E6=9F=A5=EF=BC=8C=E5=AE=9E=E7=8E=B0=E6=A0=B9?= =?UTF-8?q?=E6=8D=AE=E7=94=A8=E6=88=B7=E8=A7=92=E8=89=B2=E6=89=80=E6=9C=89?= =?UTF-8?q?pagetype=E6=9D=83=E9=99=90=E6=8E=A7=E5=88=B6=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E8=AE=BF=E9=97=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/jingrow/frontend/src/app/main.ts | 32 +++--- .../frontend/src/core/pagetype/default.vue | 10 +- .../src/core/pagetype/default_list.vue | 7 +- .../core/pagetype/default_list_toolbar.vue | 7 +- .../frontend/src/shared/stores/auth.ts | 12 +++ .../frontend/src/shared/stores/menu.ts | 29 +++-- .../frontend/src/shared/stores/permissions.ts | 100 ++++++++++++++++++ .../src/views/workspace/WorkspacePage.vue | 9 +- apps/jingrow/jingrow/api/auth_api.py | 28 +++++ apps/jingrow/jingrow/utils/jingrow_api.py | 28 +++++ 10 files changed, 230 insertions(+), 32 deletions(-) create mode 100644 apps/jingrow/frontend/src/shared/stores/permissions.ts diff --git a/apps/jingrow/frontend/src/app/main.ts b/apps/jingrow/frontend/src/app/main.ts index 631fd35..8a11251 100644 --- a/apps/jingrow/frontend/src/app/main.ts +++ b/apps/jingrow/frontend/src/app/main.ts @@ -15,23 +15,29 @@ import '../assets/styles/main.css' // Font Awesome: 全局引入图标字体样式 import '@fortawesome/fontawesome-free/css/all.min.css' -const app = createApp(App) - -app.use(createPinia()) -// 初始化认证状态(需要在pinia初始化之后) import { useAuthStore } from '../shared/stores/auth' -const authStore = useAuthStore() -authStore.initAuth() - -// 在路由使用前注册工具路由,避免路由匹配时的警告 import { useToolsStore } from '../shared/stores/tools' -const toolsStore = useToolsStore() -toolsStore.initToolRoutes(router) +import { usePermissionStore } from '../shared/stores/permissions' +import '../shared/utils/fetchInterceptor' +const app = createApp(App) +const pinia = createPinia() + +app.use(pinia) app.use(router) app.use(naive) -// 初始化fetch拦截器(需要在pinia初始化之后) -import '../shared/utils/fetchInterceptor' +async function bootstrap() { + const authStore = useAuthStore() + await authStore.initAuth() -app.mount('#app') + const toolsStore = useToolsStore() + toolsStore.initToolRoutes(router) + + const permissionStore = usePermissionStore() + await permissionStore.loadPermissions().catch(() => {}) + + app.mount('#app') +} + +bootstrap() diff --git a/apps/jingrow/frontend/src/core/pagetype/default.vue b/apps/jingrow/frontend/src/core/pagetype/default.vue index 3084386..8e9c8c3 100644 --- a/apps/jingrow/frontend/src/core/pagetype/default.vue +++ b/apps/jingrow/frontend/src/core/pagetype/default.vue @@ -288,11 +288,13 @@ import { downloadImageToLocal } from '@/shared/api/common' import { usePageTypeSlug } from '@/shared/utils/slug' import { resolvePagetypeToolbarOverride } from '@/core/registry/pagetypeOverride' import DefaultToolbar from '@/core/pagetype/default_toolbar.vue' +import { usePermissionStore } from '@/shared/stores/permissions' const route = useRoute() const router = useRouter() const message = useMessage() const dialog = useDialog() +const permissionStore = usePermissionStore() // 使用组合式函数处理URL slug const { pagetypeSlug, entity } = usePageTypeSlug(route) @@ -304,6 +306,7 @@ const isNew = computed(() => { return idValue === 'new' || idValue.startsWith('new-') }) const canEdit = ref(false) +const canRead = computed(() => permissionStore.canRead(entity.value)) const record = ref({}) const originalRecord = ref({}) @@ -826,9 +829,10 @@ async function loadMeta() { metaFields.value = data?.fields || [] pageMeta.value = data || {} - - - canEdit.value = true // 默认支持编辑 + + // 权限:默认读取后端权限,决定是否可编辑 + const pagetypeName = entity.value + canEdit.value = permissionStore.canWrite(pagetypeName) // 设置默认活动标签:显示第一个标签页 if (tabs.value.length > 0) { diff --git a/apps/jingrow/frontend/src/core/pagetype/default_list.vue b/apps/jingrow/frontend/src/core/pagetype/default_list.vue index a8707e9..d7eeffc 100644 --- a/apps/jingrow/frontend/src/core/pagetype/default_list.vue +++ b/apps/jingrow/frontend/src/core/pagetype/default_list.vue @@ -24,7 +24,8 @@ createRecordHandler, handleDeleteSelected, router, - t + t, + canEdit: canEditList, }" :entity="entity" :search-query="searchQuery" @@ -44,6 +45,7 @@ :view-mode="viewMode" :selected-keys="selectedKeys" :loading="loading" + :can-edit="canEditList" @update:search-query="searchQuery = $event" @update:view-mode="viewMode = $event" @reload="reload" @@ -424,15 +426,18 @@ import { resolvePagetypeListActionsOverride } from '@/core/registry/pagetypeOverride' import { downloadImageToLocal } from '@/shared/api/common' +import { usePermissionStore } from '@/shared/stores/permissions' const route = useRoute() const router = useRouter() const message = useMessage() const dialog = useDialog() +const permissionStore = usePermissionStore() // 使用组合式函数处理URL slug const { pagetypeSlug, entity } = usePageTypeSlug(route) const title = computed(() => entity.value) +const canEditList = computed(() => permissionStore.canWrite(entity.value)) // 覆盖组件引用(子组件覆盖,整体覆盖由 ListPage.vue 处理) const toolbarComponent = shallowRef(null) diff --git a/apps/jingrow/frontend/src/core/pagetype/default_list_toolbar.vue b/apps/jingrow/frontend/src/core/pagetype/default_list_toolbar.vue index 66203ea..064029e 100644 --- a/apps/jingrow/frontend/src/core/pagetype/default_list_toolbar.vue +++ b/apps/jingrow/frontend/src/core/pagetype/default_list_toolbar.vue @@ -30,7 +30,7 @@