Commit 298ab0caa620bac92e14699c2d58f621c800e358
Merge branch 'ww' into 'main'
fix: DEFECT-507 chart series useage stack attribute See merge request huang/yun-teng-iot-front!248
Showing
5 changed files
with
390 additions
and
1 deletions
1 | import { defHttp } from '/@/utils/http/axios'; | 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 | enum CameraManagerApi { | 10 | enum CameraManagerApi { |
5 | CAMERA_POST_URL = '/video', | 11 | CAMERA_POST_URL = '/video', |
6 | CAMERA_GET_URL = '/video', | 12 | CAMERA_GET_URL = '/video', |
7 | CAMERA_DELETE_URL = '/video', | 13 | CAMERA_DELETE_URL = '/video', |
8 | CAMERA_GET_DETAIL_URL = '/video', | 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 | export const cameraPage = (params: CameraQueryParam) => { | 20 | export const cameraPage = (params: CameraQueryParam) => { |
@@ -42,3 +51,39 @@ export const getCameraManageDetail = (id: string) => { | @@ -42,3 +51,39 @@ export const getCameraManageDetail = (id: string) => { | ||
42 | url: CameraManagerApi.CAMERA_GET_DETAIL_URL + `/${id}`, | 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,3 +35,34 @@ export interface CameraModel { | ||
35 | updater?: string; | 35 | updater?: string; |
36 | videoUrl: string; | 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> |
src/views/camera/streaming/config.data.ts
0 → 100644
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 | + placeholder: '请输入选择平台类型', | ||
66 | + }, | ||
67 | + }, | ||
68 | + { | ||
69 | + label: '部署环境', | ||
70 | + field: 'ssl', | ||
71 | + component: 'RadioGroup', | ||
72 | + rules: [{ required: true, message: '流媒体部署环境为必填项', type: 'number' }], | ||
73 | + componentProps: { | ||
74 | + options: [ | ||
75 | + { label: 'http', value: 0 }, | ||
76 | + { label: 'https', value: 1 }, | ||
77 | + ], | ||
78 | + }, | ||
79 | + }, | ||
80 | + { | ||
81 | + label: '平台地址', | ||
82 | + field: 'host', | ||
83 | + component: 'Input', | ||
84 | + helpMessage: ['平台IP + 端口'], | ||
85 | + rules: [{ required: true, message: '平台地址为必填项' }], | ||
86 | + componentProps: { | ||
87 | + placeholder: '请输入平台地址', | ||
88 | + }, | ||
89 | + }, | ||
90 | + { | ||
91 | + label: '用户Key', | ||
92 | + field: 'appKey', | ||
93 | + component: 'Input', | ||
94 | + rules: [{ required: true, message: '用户Key为必填项' }], | ||
95 | + componentProps: { | ||
96 | + placeholder: '请输入用户Key', | ||
97 | + }, | ||
98 | + }, | ||
99 | + { | ||
100 | + label: '用户密钥', | ||
101 | + field: 'appSecret', | ||
102 | + component: 'Input', | ||
103 | + rules: [{ required: true, message: '用户密钥为必填项' }], | ||
104 | + componentProps: { | ||
105 | + placeholder: '请输入用户密钥', | ||
106 | + }, | ||
107 | + }, | ||
108 | +]; |
src/views/camera/streaming/index.vue
0 → 100644
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> |