From 87c4447f31a9ce42fd95f5849d4f9f14d82b8841 Mon Sep 17 00:00:00 2001 From: JiangQiming <291854119@qq.com> Date: Fri, 17 Feb 2023 17:37:04 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=A7=86=E9=A2=91=E8=AE=BE=E5=A4=87-?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E7=BC=96=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/media/device.ts | 13 + src/components/JUpload/index.vue | 227 ++++++++------- src/views/media/Device/Save/SaveProduct.vue | 282 ++++++++++++++++++ src/views/media/Device/Save/index.vue | 301 +++++++++----------- src/views/media/Device/const.ts | 11 +- src/views/media/Device/index.vue | 6 +- src/views/media/Device/typings.d.ts | 63 +++- 7 files changed, 630 insertions(+), 273 deletions(-) create mode 100644 src/views/media/Device/Save/SaveProduct.vue diff --git a/src/api/media/device.ts b/src/api/media/device.ts index d16d117e..4634bfbd 100644 --- a/src/api/media/device.ts +++ b/src/api/media/device.ts @@ -1,4 +1,5 @@ import server from '@/utils/request' +import type { ProductType } from '@/views/media/Device/typings'; export default { // 列表 @@ -10,4 +11,16 @@ export default { // 修改 update: (data: any) => server.put(`/media/device/${data.channel}/${data.id}`, data), del: (id: string) => server.remove(`/media/device/${id}`), + // 更新通道 + updateChannels: (id: string) => server.post(`/media/device/${id}/channels/_sync`), + // 查询产品列表 + queryProductList: (data: any) => server.post(`/device/product/_query/no-paging`, data), + // 快速添加产品 + saveProduct: (data: any) => server.post(`/device/product`, data), + // 产品发布 + deployProductById: (id: string) => server.post(`/device/product/${id}/deploy`), + // 查询设备接入配置 + queryProvider: (data?: any) => server.post(`/gateway/device/detail/_query`, data), + // 查询网关配置 + getConfiguration: (id: string, transport: string) => server.get(`/protocol/${id}/${transport}/configuration`), } \ No newline at end of file diff --git a/src/components/JUpload/index.vue b/src/components/JUpload/index.vue index 93fd6562..03ee6536 100644 --- a/src/components/JUpload/index.vue +++ b/src/components/JUpload/index.vue @@ -10,7 +10,7 @@ @change="handleChange" :action="FILE_UPLOAD" :headers="{ - 'X-Access-Token': LocalStore.get(TOKEN_KEY) + 'X-Access-Token': LocalStore.get(TOKEN_KEY), }" v-bind="props" > @@ -26,8 +26,23 @@
点击修改
@@ -41,8 +56,8 @@ + + diff --git a/src/views/media/Device/Save/index.vue b/src/views/media/Device/Save/index.vue index b2e6fdb5..f5ffe44c 100644 --- a/src/views/media/Device/Save/index.vue +++ b/src/views/media/Device/Save/index.vue @@ -13,82 +13,18 @@ layout="horizontal" :options="PROVIDER_OPTIONS" :checkStyle="true" - :disabled="!!formData.id" + :disabled="!!route.query.id" v-model="formData.channel" /> - + - + -
- - - - -
+ + + + + {{ item.name }} + + + + + + + + +
+
+ + @@ -258,12 +249,11 @@ import { getImage } from '@/utils/comm'; import { Form } from 'ant-design-vue'; import { message } from 'ant-design-vue'; -import templateApi from '@/api/notice/template'; +import DeviceApi from '@/api/media/device'; -import { FILE_UPLOAD } from '@/api/comm'; -import { LocalStore } from '@/utils/comm'; -import { TOKEN_KEY } from '@/utils/variable'; import { PROVIDER_OPTIONS } from '@/views/media/Device/const'; +import type { ProductType } from '@/views/media/Device/typings'; +import SaveProduct from './SaveProduct.vue'; const router = useRouter(); const route = useRoute(); @@ -274,18 +264,26 @@ const formData = ref({ id: '', name: '', channel: 'gb28181-2016', - photoUrl: '', + photoUrl: getImage('/device-media.png'), productId: '', others: { access_pwd: '', }, description: '', + // 编辑字段 + streamMode: 'UDP', + manufacturer: '', + model: '', + firmware: '', }); // 验证规则 const formRules = ref({ id: [ - { required: true, message: '请输入ID' }, + { + required: true, + message: '请输入ID', + }, { max: 64, message: '最多输入64个字符' }, { pattern: /^[a-zA-Z0-9_\-]+$/, @@ -300,8 +298,20 @@ const formRules = ref({ channel: [{ required: true, message: '请选择接入方式' }], 'others.access_pwd': [{ required: true, message: '请输入接入密码' }], description: [{ max: 200, message: '最多可输入200个字符' }], + streamMode: [{ required: true, message: '请选择流传输模式' }], }); +watch( + () => formData.value.channel, + (val) => { + formRules.value['id'][0].required = val === 'gb28181-2016'; + formRules.value['others.access_pwd'][0].required = + val === 'gb28181-2016'; + validate(); + getProductList(); + }, +); + const { resetFields, validate, validateInfos, clearValidate } = useForm( formData.value, formRules.value, @@ -309,36 +319,64 @@ const { resetFields, validate, validateInfos, clearValidate } = useForm( const clearValid = () => { setTimeout(() => { - formData.value.variableDefinitions = []; clearValidate(); }, 200); }; +/** + * 获取所属产品 + */ +const productList = ref([]); +const getProductList = async () => { + // console.log('formData.productId: ', formData.value.productId); + const params = { + paging: false, + sorts: [{ name: 'createTime', order: 'desc' }], + terms: [ + { column: 'accessProvider', value: formData.value.channel }, + { column: 'state', value: 1 }, + ], + }; + const { result } = await DeviceApi.queryProductList(params); + productList.value = result; +}; +getProductList(); + +/** + * 新增产品 + */ +const saveProductVis = ref(false); + /** * 获取详情 */ const getDetail = async () => { - const res = await templateApi.detail(route.params.id as string); + const res = await DeviceApi.detail(route.query.id as string); // console.log('res: ', res); formData.value = res.result; - // console.log('formData.value: ', formData.value); + formData.value.channel = res.result.provider; + console.log('formData.value: ', formData.value); + // validate(); }; -// getDetail(); + +onMounted(() => { + getDetail(); +}); /** * 表单提交 */ const btnLoading = ref(false); const handleSubmit = () => { - // console.log('formData.value: ', formData.value); + console.log('formData.value: ', formData.value); validate() .then(async () => { btnLoading.value = true; let res; - if (!formData.value.id) { - res = await templateApi.save(formData.value); + if (!route.query.id) { + res = await DeviceApi.save(formData.value); } else { - res = await templateApi.update(formData.value); + res = await DeviceApi.update(formData.value); } // console.log('res: ', res); if (res?.success) { @@ -360,70 +398,5 @@ const handleSubmit = () => { .page-container { background: #f0f2f5; padding: 24px; - .upload-image-warp-logo { - display: flex; - justify-content: flex-start; - .upload-image-border-logo { - position: relative; - overflow: hidden; - border: 1px dashed #d9d9d9; - transition: all 0.3s; - width: 160px; - height: 150px; - &:hover { - border: 1px dashed #1890ff; - display: flex; - } - .upload-image-content-logo { - align-items: center; - justify-content: center; - position: relative; - display: flex; - flex-direction: column; - width: 160px; - height: 150px; - padding: 8px; - background-color: rgba(0, 0, 0, 0.06); - cursor: pointer; - .loading-logo { - position: absolute; - top: 50%; - } - .loading-icon { - position: absolute; - } - .upload-image { - width: 100%; - height: 100%; - background-repeat: no-repeat; - background-position: 50%; - background-size: cover; - } - .upload-image-icon { - width: 100%; - height: 100%; - background-repeat: no-repeat; - background-position: 50%; - background-size: inherit; - } - .upload-image-mask { - align-items: center; - justify-content: center; - position: absolute; - top: 0; - left: 0; - display: none; - width: 100%; - height: 100%; - color: #fff; - font-size: 16px; - background-color: rgba(0, 0, 0, 0.35); - } - &:hover .upload-image-mask { - display: flex; - } - } - } - } } diff --git a/src/views/media/Device/const.ts b/src/views/media/Device/const.ts index d1360534..1d2ccc69 100644 --- a/src/views/media/Device/const.ts +++ b/src/views/media/Device/const.ts @@ -1,4 +1,13 @@ export const PROVIDER_OPTIONS = [ { label: '固定地址', value: 'fixed-media' }, { label: 'GB/T28181', value: 'gb28181-2016' }, -] \ No newline at end of file +] +export const streamMode = [ + { label: 'UDP', value: 'UDP' }, + { label: 'TCP被动', value: 'TCP_PASSIVE' }, +] + +export const providerType = { + 'gb28181-2016': 'GB/T28181', + 'fixed-media': '固定地址', +}; \ No newline at end of file diff --git a/src/views/media/Device/index.vue b/src/views/media/Device/index.vue index d1eef81a..acbb3de5 100644 --- a/src/views/media/Device/index.vue +++ b/src/views/media/Device/index.vue @@ -135,11 +135,7 @@ import type { ActionsType } from '@/components/Table/index.vue'; import { message } from 'ant-design-vue'; import { getImage } from '@/utils/comm'; import { PROVIDER_OPTIONS } from '@/views/media/Device/const'; - -const providerType = { - 'gb28181-2016': 'GB/T28181', - 'fixed-media': '固定地址', -}; +import { providerType } from './const'; const router = useRouter(); diff --git a/src/views/media/Device/typings.d.ts b/src/views/media/Device/typings.d.ts index 012be458..436c9236 100644 --- a/src/views/media/Device/typings.d.ts +++ b/src/views/media/Device/typings.d.ts @@ -21,4 +21,65 @@ export type DeviceItem = { state: State; streamMode: string; transport: string; -} & BaseItem; \ No newline at end of file +} & BaseItem; + +export type ProductType = { + accessId: string; + accessName: string; + accessProvider: string; + createTime: number; + creatorId: string; + deviceType: { + text: string; + value: string; + }; + id: string; + messageProtocol: string; + metadata: string; + modifierId: string; + modifyTime: number; + name: string; + protocolName: string; + state: number; + transportProtocol: string; +} + + +type addressesType = { + address: string; + bad: boolean; + disabled: boolean; + health: number; + ok: boolean; +} +export type gatewayType = { + channel: string; + channelId: string; + channelInfo: { + id: string; + name: string; + addresses: addressesType[]; + }; + id: string; + name: string; + protocol: string; + protocolDetail: { + id: string; + name: string; + description?: string; + }; + provider: string; + state: { + text: string; + value: string; + }; + transport: string; + transportDetail: { + id: string; + name: string; + metadata: string; + features: string[]; + routes: string[]; + }; + description?: string; +} \ No newline at end of file