Commit a2b21f85eae544d52ec3203c13247f618423a1be

Authored by ww
1 parent c79a9d7e

feat: add streaming media config page

1 1 import { defHttp } from '/@/utils/http/axios';
2   -import { CameraModel, CameraQueryParam } from './model/cameraModel';
  2 +import {
  3 + CameraModel,
  4 + CameraQueryParam,
  5 + StreamingMediaDeleteParam,
  6 + StreamingQueryParam,
  7 + StreamingSubmitParam,
  8 +} from './model/cameraModel';
3 9
4 10 enum CameraManagerApi {
5 11 CAMERA_POST_URL = '/video',
6 12 CAMERA_GET_URL = '/video',
7 13 CAMERA_DELETE_URL = '/video',
8 14 CAMERA_GET_DETAIL_URL = '/video',
  15 + STERAMING_GET_URL = '/video/platform',
  16 + STERAMING_POST_URL = '/video/platform',
  17 + STERAMING_DELETE_URL = '/video/platform',
9 18 }
10 19
11 20 export const cameraPage = (params: CameraQueryParam) => {
... ... @@ -42,3 +51,39 @@ export const getCameraManageDetail = (id: string) => {
42 51 url: CameraManagerApi.CAMERA_GET_DETAIL_URL + `/${id}`,
43 52 });
44 53 };
  54 +
  55 +/**
  56 + * @description 获取流媒体列表
  57 + * @param params
  58 + * @returns
  59 + */
  60 +export const getStreamingMediaList = (params: StreamingQueryParam) => {
  61 + return defHttp.get({
  62 + url: CameraManagerApi.STERAMING_GET_URL,
  63 + params,
  64 + });
  65 +};
  66 +
  67 +/**
  68 + * @description 更新/新增流媒体记录
  69 + * @param params
  70 + * @returns
  71 + */
  72 +export const createOrUpdateStreamingMediaRecord = (params: StreamingSubmitParam) => {
  73 + return defHttp.post({
  74 + url: CameraManagerApi.STERAMING_POST_URL,
  75 + params,
  76 + });
  77 +};
  78 +
  79 +/**
  80 + * @description 删除流媒体记录
  81 + * @param params
  82 + * @returns
  83 + */
  84 +export const deleteStreamingMediaRecord = (params: StreamingMediaDeleteParam) => {
  85 + return defHttp.delete({
  86 + url: CameraManagerApi.STERAMING_POST_URL,
  87 + params,
  88 + });
  89 +};
... ...
... ... @@ -35,3 +35,34 @@ export interface CameraModel {
35 35 updater?: string;
36 36 videoUrl: string;
37 37 }
  38 +
  39 +export interface StreamingMediaModel {
  40 + id: string;
  41 + creator: string;
  42 + createTime: string;
  43 + enabled: boolean;
  44 + tenantId: string;
  45 + type: number;
  46 + host: string;
  47 + appKey: string;
  48 + appSecret: string;
  49 + ssl: number;
  50 +}
  51 +
  52 +export interface StreamingQueryParam {
  53 + host?: string;
  54 +}
  55 +
  56 +export interface StreamingSubmitParam {
  57 + type: number;
  58 + ssl: number;
  59 + host: string;
  60 + appKey: string;
  61 + appSecret: string;
  62 + id?: string;
  63 +}
  64 +
  65 +export interface StreamingMediaDeleteParam {
  66 + tenantId?: string;
  67 + ids: string[];
  68 +}
... ...
  1 +<script lang="ts" setup>
  2 + import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
  3 + import { BasicForm, useForm } from '/@/components/Form';
  4 + import { formDetailSchema } from './config.data';
  5 + import type { DrawerParams } from './config.data';
  6 + import { ref, computed, unref } from 'vue';
  7 + import { createOrUpdateStreamingMediaRecord } from '/@/api/camera/cameraManager';
  8 + import { StreamingMediaModel } from '/@/api/camera/model/cameraModel';
  9 + import { useMessage } from '/@/hooks/web/useMessage';
  10 +
  11 + const emit = defineEmits({
  12 + success: null,
  13 + });
  14 +
  15 + const createFlag = ref(false);
  16 +
  17 + const getDrawerTitle = computed(() => `${unref(createFlag) ? '新增' : '编辑'}流媒体配置`);
  18 +
  19 + let id: Nullable<string> = null;
  20 +
  21 + const [register, { getFieldsValue, setFieldsValue, resetFields, validate }] = useForm({
  22 + schemas: formDetailSchema,
  23 + labelWidth: 90,
  24 + showActionButtonGroup: false,
  25 + });
  26 +
  27 + const [registerDrawer, { setDrawerProps }] = useDrawerInner((data: DrawerParams) => {
  28 + createFlag.value = data.createFlag;
  29 + if (!unref(createFlag)) {
  30 + id = data.record!.id;
  31 + setFieldsValue(data.record);
  32 + } else {
  33 + resetFields();
  34 + }
  35 + });
  36 +
  37 + const handleSubmit = async () => {
  38 + await validate();
  39 + let value = getFieldsValue() as StreamingMediaModel;
  40 + let message = '修改成功';
  41 + if (unref(createFlag)) message = '添加成功';
  42 + else value = { ...value, id: id! };
  43 + try {
  44 + setDrawerProps({
  45 + confirmLoading: true,
  46 + });
  47 + await createOrUpdateStreamingMediaRecord(value);
  48 + const { createMessage } = useMessage();
  49 + createMessage.success(message);
  50 + emit('success');
  51 + } catch (e) {
  52 + } finally {
  53 + setDrawerProps({
  54 + confirmLoading: false,
  55 + });
  56 + }
  57 + };
  58 +</script>
  59 +
  60 +<template>
  61 + <BasicDrawer
  62 + @register="registerDrawer"
  63 + v-bind="$attrs"
  64 + showFooter
  65 + :title="getDrawerTitle"
  66 + width="30%"
  67 + @ok="handleSubmit"
  68 + >
  69 + <BasicForm @register="register" />
  70 + </BasicDrawer>
  71 +</template>
... ...
  1 +import type { StreamingMediaModel } from '/@/api/camera/model/cameraModel';
  2 +import { BasicColumn, FormSchema } from '/@/components/Table';
  3 +
  4 +export interface DrawerParams {
  5 + createFlag: boolean;
  6 + record?: StreamingMediaModel;
  7 +}
  8 +
  9 +export const streamingMediaTypeMapping = {
  10 + 0: '海康ISC平台',
  11 +};
  12 +
  13 +export const streamingMediaSSLMapping = {
  14 + 0: 'http',
  15 + 1: 'https',
  16 +};
  17 +
  18 +export const columnSchema: BasicColumn[] = [
  19 + {
  20 + title: '平台类型',
  21 + dataIndex: 'type',
  22 + width: 80,
  23 + slots: { customRender: 'type' },
  24 + },
  25 + {
  26 + title: '部署环境',
  27 + dataIndex: 'ssl',
  28 + width: 80,
  29 + slots: { customRender: 'ssl' },
  30 + },
  31 + {
  32 + title: '平台地址',
  33 + dataIndex: 'host',
  34 + width: 80,
  35 + },
  36 + {
  37 + title: '用户Key',
  38 + dataIndex: 'appKey',
  39 + width: 80,
  40 + },
  41 + {
  42 + title: '用户密钥',
  43 + dataIndex: 'appSecret',
  44 + width: 80,
  45 + },
  46 +];
  47 +
  48 +export const formSchema: FormSchema[] = [
  49 + {
  50 + field: 'host',
  51 + label: '平台地址',
  52 + component: 'Input',
  53 + colProps: { span: 8 },
  54 + },
  55 +];
  56 +
  57 +export const formDetailSchema: FormSchema[] = [
  58 + {
  59 + label: '平台类型',
  60 + field: 'type',
  61 + component: 'Select',
  62 + rules: [{ required: true, message: '平台类型为必填项', type: 'number' }],
  63 + componentProps: {
  64 + options: [{ label: '海康ISC平台', value: 0 }],
  65 + },
  66 + },
  67 + {
  68 + label: '部署环境',
  69 + field: 'ssl',
  70 + component: 'RadioGroup',
  71 + rules: [{ required: true, message: '流媒体部署环境为必填项', type: 'number' }],
  72 + componentProps: {
  73 + options: [
  74 + { label: 'http', value: 0 },
  75 + { label: 'https', value: 1 },
  76 + ],
  77 + },
  78 + },
  79 + {
  80 + label: '平台地址',
  81 + field: 'host',
  82 + component: 'Input',
  83 + helpMessage: ['平台IP + 端口'],
  84 + rules: [{ required: true, message: '平台地址为必填项' }],
  85 + },
  86 + {
  87 + label: '用户Key',
  88 + field: 'appKey',
  89 + component: 'Input',
  90 + rules: [{ required: true, message: '用户Key为必填项' }],
  91 + },
  92 + {
  93 + label: '用户密钥',
  94 + field: 'appSecret',
  95 + component: 'Input',
  96 + rules: [{ required: true, message: '用户密钥为必填项' }],
  97 + },
  98 +];
... ...
  1 +<script lang="ts" setup>
  2 + import { PageWrapper } from '/@/components/Page';
  3 + import { useDrawer } from '/@/components/Drawer';
  4 + import type { DrawerParams } from './config.data';
  5 + import { BasicTable, useTable, TableAction } from '/@/components/Table';
  6 + import {
  7 + columnSchema,
  8 + formSchema,
  9 + streamingMediaTypeMapping,
  10 + streamingMediaSSLMapping,
  11 + } from './config.data';
  12 + import SteramingDrawer from './SteramingDrawer.vue';
  13 + import { getStreamingMediaList, deleteStreamingMediaRecord } from '/@/api/camera/cameraManager';
  14 + import { StreamingMediaModel } from '/@/api/camera/model/cameraModel';
  15 + import { ref } from 'vue';
  16 + import { useMessage } from '/@/hooks/web/useMessage';
  17 +
  18 + const enabledBatchDelete = ref(true);
  19 + const [register, { reload, getSelectRowKeys }] = useTable({
  20 + title: '流媒体列表',
  21 + api: getStreamingMediaList,
  22 + columns: columnSchema,
  23 + showIndexColumn: false,
  24 + clickToRowSelect: false,
  25 + formConfig: {
  26 + labelWidth: 120,
  27 + schemas: formSchema,
  28 + },
  29 + useSearchForm: true,
  30 + showTableSetting: true,
  31 + bordered: true,
  32 + rowKey: 'id',
  33 + actionColumn: {
  34 + width: 100,
  35 + title: '操作',
  36 + dataIndex: 'action',
  37 + slots: { customRender: 'action' },
  38 + fixed: 'right',
  39 + },
  40 +
  41 + rowSelection: {
  42 + type: 'checkbox',
  43 + onChange(rowKeys: string[]) {
  44 + enabledBatchDelete.value = rowKeys.length <= 0;
  45 + },
  46 + },
  47 + });
  48 +
  49 + const [registerDrawer, { openDrawer }] = useDrawer();
  50 +
  51 + const handleCreateStreamingMedia = () => {
  52 + openDrawer<DrawerParams>(true, {
  53 + createFlag: true,
  54 + });
  55 + };
  56 +
  57 + const handleUpdateStreamingMedia = (record: StreamingMediaModel) => {
  58 + openDrawer<DrawerParams>(true, {
  59 + createFlag: false,
  60 + record,
  61 + });
  62 + };
  63 +
  64 + const handleDeleteRecord = async (record?: StreamingMediaModel) => {
  65 + let ids = record ? [record.id] : getSelectRowKeys();
  66 + try {
  67 + await deleteStreamingMediaRecord({ ids });
  68 + enabledBatchDelete.value = true;
  69 + const { createMessage } = useMessage();
  70 + createMessage.success('删除成功');
  71 + } catch (e) {
  72 + } finally {
  73 + reload();
  74 + }
  75 + };
  76 +
  77 + const handleDrawerSubmitSuccess = () => {
  78 + openDrawer(false);
  79 + reload();
  80 + };
  81 +</script>
  82 +
  83 +<template>
  84 + <PageWrapper dense contentFullHeight>
  85 + <BasicTable @register="register">
  86 + <template #type="{ record }">
  87 + <span>{{ streamingMediaTypeMapping[record.type] }}</span>
  88 + </template>
  89 + <template #ssl="{ record }">
  90 + <span>{{ streamingMediaSSLMapping[record.ssl] }}</span>
  91 + </template>
  92 + <template #action="{ record }">
  93 + <TableAction
  94 + :actions="[
  95 + {
  96 + label: '编辑',
  97 + auth: 'api:yt:streaming:update',
  98 + icon: 'clarity:note-edit-line',
  99 + onClick: handleUpdateStreamingMedia.bind(null, record),
  100 + },
  101 + {
  102 + label: '删除',
  103 + auth: 'api:yt:streaming:delete',
  104 + icon: 'ant-design:delete-outlined',
  105 + color: 'error',
  106 + popConfirm: {
  107 + title: '是否确认删除',
  108 + confirm: handleDeleteRecord.bind(null, record),
  109 + },
  110 + },
  111 + ]"
  112 + />
  113 + </template>
  114 + <template #toolbar>
  115 + <Authority value="api:yt:streaming:post">
  116 + <a-button type="primary" @click="handleCreateStreamingMedia">新增流媒体</a-button>
  117 + </Authority>
  118 + <Authority value="api:yt:streaming:delete">
  119 + <a-button
  120 + color="error"
  121 + type="primary"
  122 + :disabled="enabledBatchDelete"
  123 + @click="handleDeleteRecord()"
  124 + >
  125 + 批量删除
  126 + </a-button>
  127 + </Authority>
  128 + </template>
  129 + </BasicTable>
  130 + <SteramingDrawer @register="registerDrawer" @success="handleDrawerSubmitSuccess" />
  131 + </PageWrapper>
  132 +</template>
  133 +
  134 +<style></style>
... ...