feat: 添加权限查询和管理机制

- 新增权限管理页面
- 改进轮询链,引入权限查询
- 支持订阅权限变更或轮询权限检测变更
- 应用权限到页面和组件
This commit is contained in:
yangsy
2026-01-22 10:34:37 +08:00
parent 82789c78a9
commit 0af52c62ce
53 changed files with 1129 additions and 131 deletions

View File

@@ -1,6 +1,8 @@
<script setup lang="ts">
import type { NdmAlarmHostResultVO, Station } from '@/apis';
import { AlarmHostCurrentDiag, AlarmHostHistoryDiag, AlarmHostUpdate, DeviceRawCard } from '@/components';
import { usePermission } from '@/composables';
import { PERMISSION_TYPE_LITERALS } from '@/enums';
import { useSettingStore } from '@/stores';
import { NCard, NPageHeader, NScrollbar, NTab, NTabs } from 'naive-ui';
import { storeToRefs } from 'pinia';
@@ -18,6 +20,8 @@ const router = useRouter();
const settingStore = useSettingStore();
const { showDeviceRawData } = storeToRefs(settingStore);
const { hasPermission } = usePermission();
const { ndmDevice, station } = toRefs(props);
const showPageHeader = computed(() => {
@@ -45,7 +49,7 @@ watch([ndmDevice, showDeviceRawData], ([newDevice, enabled], [oldDevice]) => {
<NTabs :value="activeTabName" @update:value="onTabChange">
<NTab name="当前诊断">当前诊断</NTab>
<NTab name="历史诊断">历史诊断</NTab>
<NTab name="修改设备">修改设备</NTab>
<NTab v-if="hasPermission(station.code, PERMISSION_TYPE_LITERALS.OPERATION)" name="修改设备">修改设备</NTab>
<NTab v-if="showDeviceRawData" name="原始数据">原始数据</NTab>
</NTabs>
</template>

View File

@@ -1,6 +1,8 @@
<script setup lang="ts">
import type { NdmCameraResultVO, Station } from '@/apis';
import { CameraCurrentDiag, CameraHistoryDiag, CameraUpdate, DeviceRawCard } from '@/components';
import { usePermission } from '@/composables';
import { PERMISSION_TYPE_LITERALS } from '@/enums';
import { useSettingStore } from '@/stores';
import { NCard, NPageHeader, NScrollbar, NTab, NTabs } from 'naive-ui';
import { storeToRefs } from 'pinia';
@@ -18,6 +20,8 @@ const router = useRouter();
const settingStore = useSettingStore();
const { showDeviceRawData } = storeToRefs(settingStore);
const { hasPermission } = usePermission();
const { ndmDevice, station } = toRefs(props);
const showPageHeader = computed(() => {
@@ -45,7 +49,7 @@ watch([ndmDevice, showDeviceRawData], ([newDevice, enabled], [oldDevice]) => {
<NTabs :value="activeTabName" @update:value="onTabChange">
<NTab name="当前诊断">当前诊断</NTab>
<NTab name="历史诊断">历史诊断</NTab>
<NTab name="修改设备">修改设备</NTab>
<NTab v-if="hasPermission(station.code, PERMISSION_TYPE_LITERALS.OPERATION)" name="修改设备">修改设备</NTab>
<NTab v-if="showDeviceRawData" name="原始数据">原始数据</NTab>
</NTabs>
</template>

View File

@@ -1,6 +1,8 @@
<script setup lang="ts">
import type { NdmDecoderResultVO, Station } from '@/apis';
import { DecoderCurrentDiag, DecoderHistoryDiag, DecoderUpdate, DeviceRawCard } from '@/components';
import { usePermission } from '@/composables';
import { PERMISSION_TYPE_LITERALS } from '@/enums';
import { useSettingStore } from '@/stores';
import { NCard, NPageHeader, NScrollbar, NTab, NTabs } from 'naive-ui';
import { storeToRefs } from 'pinia';
@@ -18,6 +20,8 @@ const router = useRouter();
const settingStore = useSettingStore();
const { showDeviceRawData } = storeToRefs(settingStore);
const { hasPermission } = usePermission();
const { ndmDevice, station } = toRefs(props);
const showPageHeader = computed(() => {
@@ -45,7 +49,7 @@ watch([ndmDevice, showDeviceRawData], ([newDevice, enabled], [oldDevice]) => {
<NTabs :value="activeTabName" @update:value="onTabChange">
<NTab name="当前诊断">当前诊断</NTab>
<NTab name="历史诊断">历史诊断</NTab>
<NTab name="修改设备">修改设备</NTab>
<NTab v-if="hasPermission(station.code, PERMISSION_TYPE_LITERALS.OPERATION)" name="修改设备">修改设备</NTab>
<NTab v-if="showDeviceRawData" name="原始数据">原始数据</NTab>
</NTabs>
</template>

View File

@@ -1,6 +1,8 @@
<script setup lang="ts">
import type { NdmKeyboardResultVO, Station } from '@/apis';
import { DeviceRawCard, KeyboardCurrentDiag, KeyboardHistoryDiag, KeyboardUpdate } from '@/components';
import { usePermission } from '@/composables';
import { PERMISSION_TYPE_LITERALS } from '@/enums';
import { useSettingStore } from '@/stores';
import { NCard, NPageHeader, NScrollbar, NTab, NTabs } from 'naive-ui';
import { storeToRefs } from 'pinia';
@@ -18,6 +20,8 @@ const router = useRouter();
const settingStore = useSettingStore();
const { showDeviceRawData } = storeToRefs(settingStore);
const { hasPermission } = usePermission();
const { ndmDevice, station } = toRefs(props);
const showPageHeader = computed(() => {
@@ -45,7 +49,7 @@ watch([ndmDevice, showDeviceRawData], ([newDevice, enabled], [oldDevice]) => {
<NTabs :value="activeTabName" @update:value="onTabChange">
<NTab name="当前诊断">当前诊断</NTab>
<NTab name="历史诊断">历史诊断</NTab>
<NTab name="修改设备">修改设备</NTab>
<NTab v-if="hasPermission(station.code, PERMISSION_TYPE_LITERALS.OPERATION)" name="修改设备">修改设备</NTab>
<NTab v-if="showDeviceRawData" name="原始数据">原始数据</NTab>
</NTabs>
</template>

View File

@@ -1,6 +1,8 @@
<script setup lang="ts">
import type { NdmNvrResultVO, Station } from '@/apis';
import { DeviceRawCard, NvrCurrentDiag, NvrHistoryDiag, NvrUpdate } from '@/components';
import { usePermission } from '@/composables';
import { PERMISSION_TYPE_LITERALS } from '@/enums';
import { useSettingStore } from '@/stores';
import { NCard, NPageHeader, NScrollbar, NTab, NTabs } from 'naive-ui';
import { storeToRefs } from 'pinia';
@@ -18,6 +20,8 @@ const router = useRouter();
const settingStore = useSettingStore();
const { showDeviceRawData } = storeToRefs(settingStore);
const { hasPermission } = usePermission();
const { ndmDevice, station } = toRefs(props);
const showPageHeader = computed(() => {
@@ -45,7 +49,7 @@ watch([ndmDevice, showDeviceRawData], ([newDevice, enabled], [oldDevice]) => {
<NTabs :value="activeTabName" @update:value="onTabChange">
<NTab name="当前诊断">当前诊断</NTab>
<NTab name="历史诊断">历史诊断</NTab>
<NTab name="修改设备">修改设备</NTab>
<NTab v-if="hasPermission(station.code, PERMISSION_TYPE_LITERALS.OPERATION)" name="修改设备">修改设备</NTab>
<NTab v-if="showDeviceRawData" name="原始数据">原始数据</NTab>
</NTabs>
</template>

View File

@@ -1,6 +1,8 @@
<script setup lang="ts">
import type { NdmSecurityBoxResultVO, Station } from '@/apis';
import { DeviceRawCard, SecurityBoxCurrentDiag, SecurityBoxHistoryDiag, SecurityBoxUpdate } from '@/components';
import { usePermission } from '@/composables';
import { PERMISSION_TYPE_LITERALS } from '@/enums';
import { useSettingStore } from '@/stores';
import { NCard, NPageHeader, NScrollbar, NTab, NTabs } from 'naive-ui';
import { storeToRefs } from 'pinia';
@@ -18,6 +20,8 @@ const router = useRouter();
const settingStore = useSettingStore();
const { showDeviceRawData } = storeToRefs(settingStore);
const { hasPermission } = usePermission();
const { ndmDevice, station } = toRefs(props);
const showPageHeader = computed(() => {
@@ -45,7 +49,7 @@ watch([ndmDevice, showDeviceRawData], ([newDevice, enabled], [oldDevice]) => {
<NTabs :value="activeTabName" @update:value="onTabChange">
<NTab name="当前诊断">当前诊断</NTab>
<NTab name="历史诊断">历史诊断</NTab>
<NTab name="修改设备">修改设备</NTab>
<NTab v-if="hasPermission(station.code, PERMISSION_TYPE_LITERALS.OPERATION)" name="修改设备">修改设备</NTab>
<NTab v-if="showDeviceRawData" name="原始数据">原始数据</NTab>
</NTabs>
</template>

View File

@@ -1,6 +1,8 @@
<script setup lang="ts">
import type { NdmServerResultVO, Station } from '@/apis';
import { DeviceRawCard, ServerCurrentDiag, ServerHistoryDiag, ServerUpdate } from '@/components';
import { usePermission } from '@/composables';
import { PERMISSION_TYPE_LITERALS } from '@/enums';
import { useSettingStore } from '@/stores';
import { NCard, NPageHeader, NScrollbar, NTab, NTabs } from 'naive-ui';
import { storeToRefs } from 'pinia';
@@ -18,6 +20,8 @@ const router = useRouter();
const settingStore = useSettingStore();
const { showDeviceRawData } = storeToRefs(settingStore);
const { hasPermission } = usePermission();
const { ndmDevice, station } = toRefs(props);
const showPageHeader = computed(() => {
@@ -45,7 +49,7 @@ watch([ndmDevice, showDeviceRawData], ([newDevice, enabled], [oldDevice]) => {
<NTabs :value="activeTabName" @update:value="onTabChange">
<NTab name="当前诊断">当前诊断</NTab>
<NTab name="历史诊断">历史诊断</NTab>
<NTab name="修改设备">修改设备</NTab>
<NTab v-if="hasPermission(station.code, PERMISSION_TYPE_LITERALS.OPERATION)" name="修改设备">修改设备</NTab>
<NTab v-if="showDeviceRawData" name="原始数据">原始数据</NTab>
</NTabs>
</template>

View File

@@ -1,6 +1,8 @@
<script setup lang="ts">
import type { NdmSwitchResultVO, Station } from '@/apis';
import { DeviceRawCard, SwitchCurrentDiag, SwitchHistoryDiag, SwitchUpdate } from '@/components';
import { usePermission } from '@/composables';
import { PERMISSION_TYPE_LITERALS } from '@/enums';
import { useSettingStore } from '@/stores';
import { NCard, NPageHeader, NScrollbar, NTab, NTabs } from 'naive-ui';
import { storeToRefs } from 'pinia';
@@ -18,6 +20,8 @@ const router = useRouter();
const settingStore = useSettingStore();
const { showDeviceRawData } = storeToRefs(settingStore);
const { hasPermission } = usePermission();
const { ndmDevice, station } = toRefs(props);
const showPageHeader = computed(() => {
@@ -45,7 +49,7 @@ watch([ndmDevice, showDeviceRawData], ([newDevice, enabled], [oldDevice]) => {
<NTabs :value="activeTabName" @update:value="onTabChange">
<NTab name="当前诊断">当前诊断</NTab>
<NTab name="历史诊断">历史诊断</NTab>
<NTab name="修改设备">修改设备</NTab>
<NTab v-if="hasPermission(station.code, PERMISSION_TYPE_LITERALS.OPERATION)" name="修改设备">修改设备</NTab>
<NTab v-if="showDeviceRawData" name="原始数据">原始数据</NTab>
</NTabs>
</template>

View File

@@ -1,9 +1,9 @@
<script setup lang="ts">
import { initStationDevices, type NdmDeviceResultVO, type NdmNvrResultVO, type Station } from '@/apis';
import { useDeviceTree, type UseDeviceTreeReturn } from '@/composables';
import { DEVICE_TYPE_NAMES, DEVICE_TYPE_LITERALS, tryGetDeviceType, type DeviceType } from '@/enums';
import { useDeviceTree, usePermission, type UseDeviceTreeReturn } from '@/composables';
import { DEVICE_TYPE_NAMES, DEVICE_TYPE_LITERALS, tryGetDeviceType, type DeviceType, PERMISSION_TYPE_LITERALS } from '@/enums';
import { isNvrCluster } from '@/helpers';
import { useDeviceStore, useStationStore } from '@/stores';
import { useDeviceStore, usePermissionStore } from '@/stores';
import { watchImmediate } from '@vueuse/core';
import destr from 'destr';
import { isFunction } from 'es-toolkit';
@@ -60,6 +60,8 @@ const { station, events, syncRoute, devicePrefixLabel } = toRefs(props);
const themeVars = useThemeVars();
const { hasPermission } = usePermission();
const {
// 设备选择
selectedStationCode,
@@ -87,8 +89,9 @@ const onSelectDevice = (device: NdmDeviceResultVO, stationCode: Station['code'])
emit('afterSelectDevice', device, stationCode);
};
const stationStore = useStationStore();
const { stations } = storeToRefs(stationStore);
const permissionStore = usePermissionStore();
const stations = computed(() => permissionStore.stations.VIEW ?? []);
const deviceStore = useDeviceStore();
const { lineDevices } = storeToRefs(deviceStore);
@@ -220,13 +223,17 @@ const nodeProps: TreeProps['nodeProps'] = ({ option }) => {
payload.stopPropagation();
payload.preventDefault();
// 仅当事件列表包含 `manage` 时才显示右键菜单
// 如果事件列表包含 `manage`,则直接结束逻辑
if (!events.value?.includes('manage')) return;
const { clientX, clientY } = payload;
const stationCode = option['stationCode'] as Station['code'];
// 仅当用户在该车站拥有操作权限时才显示右键菜单
if (!hasPermission(stationCode, PERMISSION_TYPE_LITERALS.OPERATION)) return;
const deviceType = option['deviceType'] as DeviceType | undefined;
const device = option['device'] as NdmDeviceResultVO | undefined;
const { clientX, clientY } = payload;
contextmenu.value = { x: clientX, y: clientY, stationCode, deviceType, device };
showContextmenu.value = true;
},