feat(iot):【网关设备:80%】动态注册的初步实现(已测试)
This commit is contained in:
@@ -0,0 +1 @@
|
||||
export { default as ProductSelect } from './select.vue';
|
||||
@@ -0,0 +1,57 @@
|
||||
<script lang="ts" setup>
|
||||
import type { IotProductApi } from '#/api/iot/product/product';
|
||||
|
||||
import { onMounted, ref } from 'vue';
|
||||
|
||||
import { Select } from 'ant-design-vue';
|
||||
|
||||
import { getSimpleProductList } from '#/api/iot/product/product';
|
||||
|
||||
/** 产品下拉选择器组件 */
|
||||
defineOptions({ name: 'ProductSelect' });
|
||||
|
||||
const props = defineProps<{
|
||||
deviceType?: number; // 设备类型过滤
|
||||
modelValue?: number;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', value?: number): void;
|
||||
(e: 'change', value?: number): void;
|
||||
}>();
|
||||
|
||||
const loading = ref(false);
|
||||
const productList = ref<IotProductApi.Product[]>([]);
|
||||
|
||||
/** 处理选择变化 */
|
||||
function handleChange(value?: number) {
|
||||
emit('update:modelValue', value);
|
||||
emit('change', value);
|
||||
}
|
||||
|
||||
/** 获取产品列表 */
|
||||
async function getProductList() {
|
||||
try {
|
||||
loading.value = true;
|
||||
productList.value = (await getSimpleProductList(props.deviceType)) || [];
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getProductList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Select
|
||||
:value="modelValue"
|
||||
:options="productList.map((p) => ({ label: p.name, value: p.id }))"
|
||||
:loading="loading"
|
||||
placeholder="请选择产品"
|
||||
allow-clear
|
||||
class="w-full"
|
||||
@change="handleChange"
|
||||
/>
|
||||
</template>
|
||||
@@ -153,9 +153,20 @@ export function useBasicFormSchema(
|
||||
];
|
||||
}
|
||||
|
||||
/** 高级设置表单字段(图标、图片、产品描述) */
|
||||
/** 高级设置表单字段(图标、图片、产品描述、动态注册) */
|
||||
export function useAdvancedFormSchema(): VbenFormSchema[] {
|
||||
return [
|
||||
{
|
||||
fieldName: 'registerEnabled',
|
||||
label: '动态注册',
|
||||
component: 'Switch',
|
||||
componentProps: {
|
||||
checkedChildren: '开',
|
||||
unCheckedChildren: '关',
|
||||
},
|
||||
defaultValue: false,
|
||||
help: '设备动态注册无需一一烧录设备证书(DeviceSecret),每台设备烧录相同的产品证书,即 ProductKey 和 ProductSecret ,云端鉴权通过后下发设备证书,您可以根据需要开启或关闭动态注册,保障安全性。',
|
||||
},
|
||||
{
|
||||
fieldName: 'icon',
|
||||
label: '产品图标',
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
<script lang="ts" setup>
|
||||
import type { IotProductApi } from '#/api/iot/product/product';
|
||||
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { DeviceTypeEnum, DICT_TYPE } from '@vben/constants';
|
||||
|
||||
import { Card, Descriptions } from 'ant-design-vue';
|
||||
import { Button, Card, Descriptions, message } from 'ant-design-vue';
|
||||
|
||||
import { DictTag } from '#/components/dict-tag';
|
||||
|
||||
@@ -13,11 +15,28 @@ interface Props {
|
||||
|
||||
defineProps<Props>();
|
||||
|
||||
const showProductSecret = ref(false); // 是否显示产品密钥
|
||||
|
||||
/** 格式化日期 */
|
||||
function formatDate(date?: Date | string) {
|
||||
if (!date) return '-';
|
||||
return new Date(date).toLocaleString('zh-CN');
|
||||
}
|
||||
|
||||
/** 切换产品密钥显示状态 */
|
||||
function toggleProductSecretVisible() {
|
||||
showProductSecret.value = !showProductSecret.value;
|
||||
}
|
||||
|
||||
/** 复制到剪贴板 */
|
||||
async function copyToClipboard(text: string) {
|
||||
try {
|
||||
await navigator.clipboard.writeText(text);
|
||||
message.success('复制成功');
|
||||
} catch {
|
||||
message.error('复制失败');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -54,6 +73,23 @@ function formatDate(date?: Date | string) {
|
||||
>
|
||||
<DictTag :type="DICT_TYPE.IOT_NET_TYPE" :value="product.netType" />
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item v-if="product.productSecret" label="ProductSecret">
|
||||
<span v-if="showProductSecret">{{ product.productSecret }}</span>
|
||||
<span v-else>********</span>
|
||||
<Button class="ml-2" size="small" @click="toggleProductSecretVisible">
|
||||
{{ showProductSecret ? '隐藏' : '显示' }}
|
||||
</Button>
|
||||
<Button
|
||||
class="ml-2"
|
||||
size="small"
|
||||
@click="copyToClipboard(product.productSecret || '')"
|
||||
>
|
||||
复制
|
||||
</Button>
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="动态注册">
|
||||
{{ product.registerEnabled ? '已开启' : '未开启' }}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item :span="3" label="产品描述">
|
||||
{{ product.description || '-' }}
|
||||
</Descriptions.Item>
|
||||
|
||||
@@ -68,6 +68,7 @@ async function getAdvancedFormValues() {
|
||||
}
|
||||
// 表单未挂载(折叠状态),从 formData 中获取
|
||||
return {
|
||||
registerEnabled: formData.value?.registerEnabled,
|
||||
icon: formData.value?.icon,
|
||||
picUrl: formData.value?.picUrl,
|
||||
description: formData.value?.description,
|
||||
@@ -120,6 +121,7 @@ const [Modal, modalApi] = useVbenModal({
|
||||
await formApi.setValues(formData.value);
|
||||
// 如果存在高级字段数据,自动展开 Collapse
|
||||
if (
|
||||
formData.value?.registerEnabled ||
|
||||
formData.value?.icon ||
|
||||
formData.value?.picUrl ||
|
||||
formData.value?.description
|
||||
|
||||
Reference in New Issue
Block a user