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 type { AxiosError, AxiosRequestConfig, CreateAxiosDefaults } from 'axios';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
import type { VimpResponse, VimpResult } from '../../types';
|
||||||
|
|
||||||
interface VimpResult<T = unknown> {
|
export const createVimpClient = (config?: CreateAxiosDefaults) => {
|
||||||
code: number;
|
|
||||||
data: T;
|
|
||||||
msg: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
type VimpResponse<T> = [err: AxiosError | null, data: T | null, resp: VimpResult<T> | null];
|
|
||||||
|
|
||||||
const createVimpClient = (config?: CreateAxiosDefaults) => {
|
|
||||||
const instance = axios.create(config);
|
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>> => {
|
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;
|
const [err, data, result] = resp;
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
if (result) {
|
if (result) {
|
||||||
@@ -51,21 +43,3 @@ const unwrapVimpResponse = <T>(resp: VimpResponse<T>) => {
|
|||||||
export const vimpClient = createVimpClient({
|
export const vimpClient = createVimpClient({
|
||||||
baseURL: `/vimp/api/client`,
|
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 './model';
|
||||||
export * from './query';
|
export * from './query';
|
||||||
export * from './request';
|
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 {
|
export interface VimpChannel {
|
||||||
address: string;
|
address: string;
|
||||||
block: 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 { useQuery } from '@tanstack/vue-query';
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { catalogChannelApi, catalogAllDeviceApi } from './request';
|
import { catalogChannelApi, catalogAllDeviceApi } from '../request';
|
||||||
import type { AxiosRequestConfig } from 'axios';
|
import type { AxiosRequestConfig } from 'axios';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import type { CodeArea, CodeLines, CodeSites } from '../types';
|
import type { CodeArea, CodeLines, CodeSites } from '../../types';
|
||||||
import type { VimpChannel } from '.';
|
import { useCameraStore, useAlarmStore } from '../../stores';
|
||||||
import { useCameraStore, useAlarmStore } from '../stores';
|
import type { VimpChannel } from '../model';
|
||||||
|
|
||||||
export const useVimpDeviceQuery = () => {
|
export const useDeviceCenterQuery = () => {
|
||||||
const cameraStore = useCameraStore();
|
const cameraStore = useCameraStore();
|
||||||
const alarmStore = useAlarmStore();
|
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">
|
<script setup lang="ts">
|
||||||
import { NTabPane, NTabs, NTree, type TreeOverrideNodeClickBehavior, type TreeProps } from 'naive-ui';
|
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 { h, type CSSProperties } from 'vue';
|
||||||
import { hasOwn } from '@vueuse/core';
|
|
||||||
import { useAlarmStore } from '../stores';
|
import { useAlarmStore } from '../stores';
|
||||||
import { storeToRefs } from 'pinia';
|
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 alarmStore = useAlarmStore();
|
||||||
const { lineTabPanes } = storeToRefs(alarmStore);
|
const { lineTabPanes } = storeToRefs(alarmStore);
|
||||||
@@ -25,8 +24,8 @@ const overrideNodeClickBehavior: TreeOverrideNodeClickBehavior = ({ option }) =>
|
|||||||
|
|
||||||
const renderNodeLabel: TreeProps['renderLabel'] = ({ option }) => {
|
const renderNodeLabel: TreeProps['renderLabel'] = ({ option }) => {
|
||||||
// 是车站节点
|
// 是车站节点
|
||||||
if (hasOwn(option, 'online')) {
|
if (isAlarmSiteNode(option)) {
|
||||||
const siteOnline = option['online'] as boolean;
|
const siteOnline = option.online;
|
||||||
const siteNodeStyle: CSSProperties = {
|
const siteNodeStyle: CSSProperties = {
|
||||||
opacity: siteOnline ? 1 : 0.5,
|
opacity: siteOnline ? 1 : 0.5,
|
||||||
};
|
};
|
||||||
@@ -34,8 +33,8 @@ const renderNodeLabel: TreeProps['renderLabel'] = ({ option }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 是中间节点(一级/二级区域)
|
// 是中间节点(一级/二级区域)
|
||||||
if (!hasOwn(option, 'device') && hasOwn(option, 'site')) {
|
if (isAlarmAreaNode(option)) {
|
||||||
const site = option['site'] as VimpStation;
|
const site = option.site;
|
||||||
const nodeStyle: CSSProperties = {
|
const nodeStyle: CSSProperties = {
|
||||||
opacity: site.online ? 1 : 0.5,
|
opacity: site.online ? 1 : 0.5,
|
||||||
};
|
};
|
||||||
@@ -43,9 +42,9 @@ const renderNodeLabel: TreeProps['renderLabel'] = ({ option }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 是警报器节点
|
// 是警报器节点
|
||||||
if (hasOwn(option, 'alarm') && hasOwn(option, 'site')) {
|
if (isAlarmNode(option)) {
|
||||||
const alarm = option['alarm'] as VimpChannel;
|
const alarm = option.alarm;
|
||||||
const site = option['site'] as VimpStation;
|
const site = option.site;
|
||||||
|
|
||||||
const alarmOnline = () => {
|
const alarmOnline = () => {
|
||||||
return alarm.status === 1 && site.online;
|
return alarm.status === 1 && site.online;
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { NTabPane, NTabs, NTree, type TreeOverrideNodeClickBehavior, type TreeProps } from 'naive-ui';
|
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 { h, type CSSProperties } from 'vue';
|
||||||
import { hasOwn } from '@vueuse/core';
|
|
||||||
import { useCameraStore } from '../stores';
|
import { useCameraStore } from '../stores';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
|
import { useDeviceCenterQuery } from '../apis';
|
||||||
|
import { isCameraNode, isCameraSiteNode, isCameraAreaNode } from '../types';
|
||||||
|
|
||||||
const { isLoading } = useVimpDeviceQuery();
|
const { isLoading } = useDeviceCenterQuery();
|
||||||
|
|
||||||
const cameraStore = useCameraStore();
|
const cameraStore = useCameraStore();
|
||||||
const { lineTabPanes } = storeToRefs(cameraStore);
|
const { lineTabPanes } = storeToRefs(cameraStore);
|
||||||
@@ -25,8 +24,8 @@ const overrideNodeClickBehavior: TreeOverrideNodeClickBehavior = ({ option }) =>
|
|||||||
|
|
||||||
const renderNodeLabel: TreeProps['renderLabel'] = ({ option }) => {
|
const renderNodeLabel: TreeProps['renderLabel'] = ({ option }) => {
|
||||||
// 是车站节点
|
// 是车站节点
|
||||||
if (hasOwn(option, 'online')) {
|
if (isCameraSiteNode(option)) {
|
||||||
const siteOnline = option['online'] as boolean;
|
const siteOnline = option.online;
|
||||||
const siteNodeStyle: CSSProperties = {
|
const siteNodeStyle: CSSProperties = {
|
||||||
opacity: siteOnline ? 1 : 0.5,
|
opacity: siteOnline ? 1 : 0.5,
|
||||||
};
|
};
|
||||||
@@ -34,8 +33,8 @@ const renderNodeLabel: TreeProps['renderLabel'] = ({ option }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 是中间节点(一级/二级区域)
|
// 是中间节点(一级/二级区域)
|
||||||
if (!hasOwn(option, 'device') && hasOwn(option, 'site')) {
|
if (isCameraAreaNode(option)) {
|
||||||
const site = option['site'] as VimpStation;
|
const site = option.site;
|
||||||
const nodeStyle: CSSProperties = {
|
const nodeStyle: CSSProperties = {
|
||||||
opacity: site.online ? 1 : 0.5,
|
opacity: site.online ? 1 : 0.5,
|
||||||
};
|
};
|
||||||
@@ -43,9 +42,9 @@ const renderNodeLabel: TreeProps['renderLabel'] = ({ option }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 是摄像机节点
|
// 是摄像机节点
|
||||||
if (hasOwn(option, 'camera') && hasOwn(option, 'site')) {
|
if (isCameraNode(option)) {
|
||||||
const camera = option['camera'] as VimpChannel;
|
const camera = option.camera;
|
||||||
const site = option['site'] as VimpStation;
|
const site = option.site;
|
||||||
|
|
||||||
const cameraOnline = () => {
|
const cameraOnline = () => {
|
||||||
return camera.status === 1 && site.online;
|
return camera.status === 1 && site.online;
|
||||||
@@ -59,14 +58,14 @@ const renderNodeLabel: TreeProps['renderLabel'] = ({ option }) => {
|
|||||||
'div',
|
'div',
|
||||||
{
|
{
|
||||||
style: cameraNodeStyle,
|
style: cameraNodeStyle,
|
||||||
draggable: camera.status === 1,
|
draggable: cameraOnline(),
|
||||||
onDblclick() {
|
onDblclick() {
|
||||||
if (camera.status === 0) return;
|
if (!cameraOnline()) return;
|
||||||
selectedDeviceGbCode.value = [camera.code];
|
selectedDeviceGbCode.value = [camera.code];
|
||||||
window.$message.info(`播放:${JSON.stringify({ code: camera.code, name: camera.name })}`);
|
window.$message.info(`播放:${JSON.stringify({ code: camera.code, name: camera.name })}`);
|
||||||
},
|
},
|
||||||
onDragstart(event) {
|
onDragstart(event) {
|
||||||
if (camera.status === 0) return;
|
if (!cameraOnline()) return;
|
||||||
console.log(event);
|
console.log(event);
|
||||||
event.dataTransfer?.setData('type', 'camera');
|
event.dataTransfer?.setData('type', 'camera');
|
||||||
event.dataTransfer?.setData('code', camera.code);
|
event.dataTransfer?.setData('code', camera.code);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import type { VimpChannel, VimpStation } from '../api';
|
import type { VimpChannel, VimpStation } from '../apis';
|
||||||
import { h, ref } from 'vue';
|
import { h, ref } from 'vue';
|
||||||
import type { AlarmAreaNodeOption, AlarmNodeOption, CodeArea, CodeLines, CodeSites, AlarmLineTabPane, AlarmSiteNodeOption, AlarmSubAreaNodeOption } from '../types';
|
import type { AlarmAreaNodeOption, AlarmNodeOption, CodeArea, CodeLines, CodeSites, AlarmLineTabPane, AlarmSiteNodeOption, AlarmSubAreaNodeOption } from '../types';
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import type { VimpChannel, VimpStation } from '../api';
|
import type { VimpChannel, VimpStation } from '../apis';
|
||||||
import { h, ref } from 'vue';
|
import { h, ref } from 'vue';
|
||||||
import type { CameraAreaNodeOption, CameraNodeOption, CodeArea, CodeLines, CodeSites, CameraLineTabPane, CameraSiteNodeOption, CameraSubAreaNodeOption } from '../types';
|
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';
|
export * from './tree';
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { TabPaneProps, TreeOption } from 'naive-ui';
|
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 SiteType = 'station' | 'parking' | 'occ' | 'train';
|
||||||
export type CodeLines = Record<string, { name: string; color: string }>;
|
export type CodeLines = Record<string, { name: string; color: string }>;
|
||||||
@@ -39,6 +39,18 @@ export interface CameraSiteNodeOption extends TreeOption {
|
|||||||
online: boolean;
|
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 {
|
export interface CameraLineTabPane extends TabPaneProps {
|
||||||
lineCode: string;
|
lineCode: string;
|
||||||
lineName: string;
|
lineName: string;
|
||||||
@@ -72,6 +84,18 @@ export interface AlarmSiteNodeOption extends TreeOption {
|
|||||||
online: boolean;
|
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 {
|
export interface AlarmLineTabPane extends TabPaneProps {
|
||||||
lineCode: string;
|
lineCode: string;
|
||||||
lineName: string;
|
lineName: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user