refactor(vimp): 重构vimp模块的API目录与导入路径
重新梳理vimp模块的API代码结构,拆分为client、model、query、request子模块并添加统一导出入口;修正所有相关文件的导入路径,新增通用响应类型与工具函数,优化树组件的类型判断逻辑,同时新增设备查询相关API与查询hook。
This commit is contained in:
@@ -0,0 +1 @@
|
||||
export * from './vimp-client';
|
||||
@@ -1,16 +1,8 @@
|
||||
import type { VimpChannel, VimpStation } from './model';
|
||||
import type { AxiosError, AxiosRequestConfig, CreateAxiosDefaults } from 'axios';
|
||||
import axios from 'axios';
|
||||
import type { VimpResponse, VimpResult } from '../../types';
|
||||
|
||||
interface VimpResult<T = unknown> {
|
||||
code: number;
|
||||
data: T;
|
||||
msg: string;
|
||||
}
|
||||
|
||||
type VimpResponse<T> = [err: AxiosError | null, data: T | null, resp: VimpResult<T> | null];
|
||||
|
||||
const createVimpClient = (config?: CreateAxiosDefaults) => {
|
||||
export const createVimpClient = (config?: CreateAxiosDefaults) => {
|
||||
const instance = axios.create(config);
|
||||
|
||||
const vimpPost = <T>(url: string, data?: AxiosRequestConfig['data'], options?: Partial<Omit<AxiosRequestConfig, 'data'>> & { retRaw?: boolean; upload?: boolean }): Promise<VimpResponse<T>> => {
|
||||
@@ -38,7 +30,7 @@ const createVimpClient = (config?: CreateAxiosDefaults) => {
|
||||
};
|
||||
};
|
||||
|
||||
const unwrapVimpResponse = <T>(resp: VimpResponse<T>) => {
|
||||
export const unwrapVimpResponse = <T>(resp: VimpResponse<T>) => {
|
||||
const [err, data, result] = resp;
|
||||
if (err) throw err;
|
||||
if (result) {
|
||||
@@ -51,21 +43,3 @@ const unwrapVimpResponse = <T>(resp: VimpResponse<T>) => {
|
||||
export const vimpClient = createVimpClient({
|
||||
baseURL: `/vimp/api/client`,
|
||||
});
|
||||
|
||||
export const catalogAllDeviceApi = async (options?: { signal?: AbortSignal }) => {
|
||||
const { signal } = options ?? {};
|
||||
const client = vimpClient;
|
||||
const endpoint = `/catalog/allDevice`;
|
||||
const resp = await client.post<VimpStation[]>(endpoint, {}, { signal });
|
||||
const data = unwrapVimpResponse(resp);
|
||||
return data;
|
||||
};
|
||||
|
||||
export const catalogChannelApi = async (code: string, options?: { signal?: AbortSignal }) => {
|
||||
const { signal } = options ?? {};
|
||||
const client = vimpClient;
|
||||
const endpoint = `/catalog/channel`;
|
||||
const resp = await client.post<VimpChannel[]>(endpoint, { code, time: '' }, { signal });
|
||||
const data = unwrapVimpResponse(resp);
|
||||
return data;
|
||||
};
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from './client';
|
||||
export * from './model';
|
||||
export * from './query';
|
||||
export * from './request';
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './vimp-channel';
|
||||
export * from './vimp-station';
|
||||
@@ -1,9 +1,3 @@
|
||||
export interface VimpStation {
|
||||
code: string;
|
||||
name: string;
|
||||
online: boolean;
|
||||
}
|
||||
|
||||
export interface VimpChannel {
|
||||
address: string;
|
||||
block: string;
|
||||
@@ -0,0 +1,5 @@
|
||||
export interface VimpStation {
|
||||
code: string;
|
||||
name: string;
|
||||
online: boolean;
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
import { useQuery } from '@tanstack/vue-query';
|
||||
import { computed } from 'vue';
|
||||
import { catalogChannelApi, catalogAllDeviceApi } from './request';
|
||||
import { catalogChannelApi, catalogAllDeviceApi } from '../request';
|
||||
import type { AxiosRequestConfig } from 'axios';
|
||||
import axios from 'axios';
|
||||
import type { CodeArea, CodeLines, CodeSites } from '../types';
|
||||
import type { VimpChannel } from '.';
|
||||
import { useCameraStore, useAlarmStore } from '../stores';
|
||||
import type { CodeArea, CodeLines, CodeSites } from '../../types';
|
||||
import { useCameraStore, useAlarmStore } from '../../stores';
|
||||
import type { VimpChannel } from '../model';
|
||||
|
||||
export const useVimpDeviceQuery = () => {
|
||||
export const useDeviceCenterQuery = () => {
|
||||
const cameraStore = useCameraStore();
|
||||
const alarmStore = useAlarmStore();
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export * from './device-center-query';
|
||||
@@ -0,0 +1,11 @@
|
||||
import { unwrapVimpResponse, vimpClient } from '../client';
|
||||
import type { VimpStation } from '../model';
|
||||
|
||||
export const catalogAllDeviceApi = async (options?: { signal?: AbortSignal }) => {
|
||||
const { signal } = options ?? {};
|
||||
const client = vimpClient;
|
||||
const endpoint = `/catalog/allDevice`;
|
||||
const resp = await client.post<VimpStation[]>(endpoint, {}, { signal });
|
||||
const data = unwrapVimpResponse(resp);
|
||||
return data;
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
import { unwrapVimpResponse, vimpClient } from '../client';
|
||||
import type { VimpChannel } from '../model';
|
||||
|
||||
export const catalogChannelApi = async (code: string, options?: { signal?: AbortSignal }) => {
|
||||
const { signal } = options ?? {};
|
||||
const client = vimpClient;
|
||||
const endpoint = `/catalog/channel`;
|
||||
const resp = await client.post<VimpChannel[]>(endpoint, { code, time: '' }, { signal });
|
||||
const data = unwrapVimpResponse(resp);
|
||||
return data;
|
||||
};
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './catalog.channel';
|
||||
export * from './catalog.all-device';
|
||||
@@ -1,13 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
import { NTabPane, NTabs, NTree, type TreeOverrideNodeClickBehavior, type TreeProps } from 'naive-ui';
|
||||
import { useVimpDeviceQuery } from '../api/query';
|
||||
import type { VimpChannel, VimpStation } from '../api/model';
|
||||
import { h, type CSSProperties } from 'vue';
|
||||
import { hasOwn } from '@vueuse/core';
|
||||
import { useAlarmStore } from '../stores';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useDeviceCenterQuery, type VimpChannel, type VimpStation } from '../apis';
|
||||
import { isAlarmNode, isAlarmSiteNode, isAlarmAreaNode } from '../types';
|
||||
|
||||
const { isLoading } = useVimpDeviceQuery();
|
||||
const { isLoading } = useDeviceCenterQuery();
|
||||
|
||||
const alarmStore = useAlarmStore();
|
||||
const { lineTabPanes } = storeToRefs(alarmStore);
|
||||
@@ -25,8 +24,8 @@ const overrideNodeClickBehavior: TreeOverrideNodeClickBehavior = ({ option }) =>
|
||||
|
||||
const renderNodeLabel: TreeProps['renderLabel'] = ({ option }) => {
|
||||
// 是车站节点
|
||||
if (hasOwn(option, 'online')) {
|
||||
const siteOnline = option['online'] as boolean;
|
||||
if (isAlarmSiteNode(option)) {
|
||||
const siteOnline = option.online;
|
||||
const siteNodeStyle: CSSProperties = {
|
||||
opacity: siteOnline ? 1 : 0.5,
|
||||
};
|
||||
@@ -34,8 +33,8 @@ const renderNodeLabel: TreeProps['renderLabel'] = ({ option }) => {
|
||||
}
|
||||
|
||||
// 是中间节点(一级/二级区域)
|
||||
if (!hasOwn(option, 'device') && hasOwn(option, 'site')) {
|
||||
const site = option['site'] as VimpStation;
|
||||
if (isAlarmAreaNode(option)) {
|
||||
const site = option.site;
|
||||
const nodeStyle: CSSProperties = {
|
||||
opacity: site.online ? 1 : 0.5,
|
||||
};
|
||||
@@ -43,9 +42,9 @@ const renderNodeLabel: TreeProps['renderLabel'] = ({ option }) => {
|
||||
}
|
||||
|
||||
// 是警报器节点
|
||||
if (hasOwn(option, 'alarm') && hasOwn(option, 'site')) {
|
||||
const alarm = option['alarm'] as VimpChannel;
|
||||
const site = option['site'] as VimpStation;
|
||||
if (isAlarmNode(option)) {
|
||||
const alarm = option.alarm;
|
||||
const site = option.site;
|
||||
|
||||
const alarmOnline = () => {
|
||||
return alarm.status === 1 && site.online;
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
import { NTabPane, NTabs, NTree, type TreeOverrideNodeClickBehavior, type TreeProps } from 'naive-ui';
|
||||
import { useVimpDeviceQuery } from '../api/query';
|
||||
import type { VimpChannel, VimpStation } from '../api/model';
|
||||
import { h, type CSSProperties } from 'vue';
|
||||
import { hasOwn } from '@vueuse/core';
|
||||
import { useCameraStore } from '../stores';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useDeviceCenterQuery } from '../apis';
|
||||
import { isCameraNode, isCameraSiteNode, isCameraAreaNode } from '../types';
|
||||
|
||||
const { isLoading } = useVimpDeviceQuery();
|
||||
const { isLoading } = useDeviceCenterQuery();
|
||||
|
||||
const cameraStore = useCameraStore();
|
||||
const { lineTabPanes } = storeToRefs(cameraStore);
|
||||
@@ -25,8 +24,8 @@ const overrideNodeClickBehavior: TreeOverrideNodeClickBehavior = ({ option }) =>
|
||||
|
||||
const renderNodeLabel: TreeProps['renderLabel'] = ({ option }) => {
|
||||
// 是车站节点
|
||||
if (hasOwn(option, 'online')) {
|
||||
const siteOnline = option['online'] as boolean;
|
||||
if (isCameraSiteNode(option)) {
|
||||
const siteOnline = option.online;
|
||||
const siteNodeStyle: CSSProperties = {
|
||||
opacity: siteOnline ? 1 : 0.5,
|
||||
};
|
||||
@@ -34,8 +33,8 @@ const renderNodeLabel: TreeProps['renderLabel'] = ({ option }) => {
|
||||
}
|
||||
|
||||
// 是中间节点(一级/二级区域)
|
||||
if (!hasOwn(option, 'device') && hasOwn(option, 'site')) {
|
||||
const site = option['site'] as VimpStation;
|
||||
if (isCameraAreaNode(option)) {
|
||||
const site = option.site;
|
||||
const nodeStyle: CSSProperties = {
|
||||
opacity: site.online ? 1 : 0.5,
|
||||
};
|
||||
@@ -43,9 +42,9 @@ const renderNodeLabel: TreeProps['renderLabel'] = ({ option }) => {
|
||||
}
|
||||
|
||||
// 是摄像机节点
|
||||
if (hasOwn(option, 'camera') && hasOwn(option, 'site')) {
|
||||
const camera = option['camera'] as VimpChannel;
|
||||
const site = option['site'] as VimpStation;
|
||||
if (isCameraNode(option)) {
|
||||
const camera = option.camera;
|
||||
const site = option.site;
|
||||
|
||||
const cameraOnline = () => {
|
||||
return camera.status === 1 && site.online;
|
||||
@@ -59,14 +58,14 @@ const renderNodeLabel: TreeProps['renderLabel'] = ({ option }) => {
|
||||
'div',
|
||||
{
|
||||
style: cameraNodeStyle,
|
||||
draggable: camera.status === 1,
|
||||
draggable: cameraOnline(),
|
||||
onDblclick() {
|
||||
if (camera.status === 0) return;
|
||||
if (!cameraOnline()) return;
|
||||
selectedDeviceGbCode.value = [camera.code];
|
||||
window.$message.info(`播放:${JSON.stringify({ code: camera.code, name: camera.name })}`);
|
||||
},
|
||||
onDragstart(event) {
|
||||
if (camera.status === 0) return;
|
||||
if (!cameraOnline()) return;
|
||||
console.log(event);
|
||||
event.dataTransfer?.setData('type', 'camera');
|
||||
event.dataTransfer?.setData('code', camera.code);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import type { VimpChannel, VimpStation } from '../api';
|
||||
import type { VimpChannel, VimpStation } from '../apis';
|
||||
import { h, ref } from 'vue';
|
||||
import type { AlarmAreaNodeOption, AlarmNodeOption, CodeArea, CodeLines, CodeSites, AlarmLineTabPane, AlarmSiteNodeOption, AlarmSubAreaNodeOption } from '../types';
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import type { VimpChannel, VimpStation } from '../api';
|
||||
import type { VimpChannel, VimpStation } from '../apis';
|
||||
import { h, ref } from 'vue';
|
||||
import type { CameraAreaNodeOption, CameraNodeOption, CodeArea, CodeLines, CodeSites, CameraLineTabPane, CameraSiteNodeOption, CameraSubAreaNodeOption } from '../types';
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import type { AxiosError } from 'axios';
|
||||
|
||||
export interface VimpResult<T = unknown> {
|
||||
code: number;
|
||||
data: T;
|
||||
msg: string;
|
||||
}
|
||||
|
||||
export type VimpResponse<T> = [err: AxiosError | null, data: T | null, resp: VimpResult<T> | null];
|
||||
@@ -1 +1,2 @@
|
||||
export * from './axios';
|
||||
export * from './tree';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { TabPaneProps, TreeOption } from 'naive-ui';
|
||||
import type { VimpChannel, VimpStation } from '../api';
|
||||
import type { VimpChannel, VimpStation } from '../apis/model';
|
||||
|
||||
export type SiteType = 'station' | 'parking' | 'occ' | 'train';
|
||||
export type CodeLines = Record<string, { name: string; color: string }>;
|
||||
@@ -39,6 +39,18 @@ export interface CameraSiteNodeOption extends TreeOption {
|
||||
online: boolean;
|
||||
}
|
||||
|
||||
export function isCameraSiteNode(option: TreeOption): option is CameraSiteNodeOption {
|
||||
return 'online' in option && !('camera' in option);
|
||||
}
|
||||
|
||||
export function isCameraAreaNode(option: TreeOption): option is CameraAreaNodeOption | CameraSubAreaNodeOption {
|
||||
return 'site' in option && !('camera' in option) && !('online' in option);
|
||||
}
|
||||
|
||||
export function isCameraNode(option: TreeOption): option is CameraNodeOption {
|
||||
return 'camera' in option && 'site' in option;
|
||||
}
|
||||
|
||||
export interface CameraLineTabPane extends TabPaneProps {
|
||||
lineCode: string;
|
||||
lineName: string;
|
||||
@@ -72,6 +84,18 @@ export interface AlarmSiteNodeOption extends TreeOption {
|
||||
online: boolean;
|
||||
}
|
||||
|
||||
export function isAlarmSiteNode(option: TreeOption): option is AlarmSiteNodeOption {
|
||||
return 'online' in option && !('alarm' in option);
|
||||
}
|
||||
|
||||
export function isAlarmAreaNode(option: TreeOption): option is AlarmAreaNodeOption | AlarmSubAreaNodeOption {
|
||||
return 'site' in option && !('alarm' in option) && !('online' in option);
|
||||
}
|
||||
|
||||
export function isAlarmNode(option: TreeOption): option is AlarmNodeOption {
|
||||
return 'alarm' in option && 'site' in option;
|
||||
}
|
||||
|
||||
export interface AlarmLineTabPane extends TabPaneProps {
|
||||
lineCode: string;
|
||||
lineName: string;
|
||||
|
||||
Reference in New Issue
Block a user