diff --git a/apps/web-antd/src/constants/dicts/device.ts b/apps/web-antd/src/constants/dicts/device.ts
index 07cf9dd..6618a91 100644
--- a/apps/web-antd/src/constants/dicts/device.ts
+++ b/apps/web-antd/src/constants/dicts/device.ts
@@ -21,3 +21,93 @@ export const deviceTypeOptions = [
tooltip: '能挂载子设备与平台进行通信的设备',
},
];
+
+// 数据类型选项
+export const dataTypeOptions = [
+ {
+ value: 'int',
+ label: 'int(整数型)',
+ },
+ {
+ value: 'long',
+ label: 'long(长整数型)',
+ },
+ {
+ value: 'float',
+ label: 'float(单精度浮点型)',
+ },
+ {
+ value: 'double',
+ label: 'double(双精度浮点数)',
+ },
+ {
+ value: 'string',
+ label: 'text(字符串)',
+ },
+ {
+ value: 'boolean',
+ label: 'boolean(布尔型)',
+ },
+ {
+ value: 'date',
+ label: 'date(时间型)',
+ },
+ {
+ value: 'enum',
+ label: 'enum(枚举)',
+ },
+ // {
+ // value: 'array',
+ // label: 'array(数组)',
+ // },
+ // {
+ // value: 'object',
+ // label: 'object(结构体)',
+ // },
+ // {
+ // value: 'file',
+ // label: 'file(文件)',
+ // },
+ // {
+ // value: 'password',
+ // label: 'password(密码)',
+ // },
+ // {
+ // value: 'geoPoint',
+ // label: 'geoPoint(地理位置)',
+ // }
+];
+
+// 表单类型选项
+export const formTypeOptions = [
+ { label: '文本', value: 'input' },
+ { label: '开关', value: 'switch' },
+ { label: '数字', value: 'number' },
+ { label: '进度条', value: 'progress' },
+ { label: '选择器', value: 'select' },
+ { label: '时间选择器', value: 'time' },
+ // { label: '文本域', value: 'textarea' },
+];
+
+export const viewTypeOptions = [
+ { label: '文本', value: 'input' },
+ { label: '开关', value: 'switch' },
+ { label: '选择器', value: 'select' },
+ { label: '进度条', value: 'progress' },
+ { label: '图片', value: 'img' },
+ { label: '折线图', value: 'line' },
+ { label: '仪表盘', value: 'dashboard' },
+];
+
+// 读写类型选项
+export const readWriteTypeOptions = [
+ { label: '读', value: 'R' },
+ { label: '写', value: 'W' },
+ { label: '读写', value: 'RW' },
+];
+
+export const timeOptions = [
+ { label: 'yyyy-MM-dd HH:mm:ss', value: 'yyyy-MM-dd HH:mm:ss' },
+ { label: 'yyyy-MM-dd', value: 'yyyy-MM-dd' },
+ { label: 'HH:mm:ss', value: 'HH:mm:ss' },
+];
diff --git a/apps/web-antd/src/views/device/product/detail/components/BasicInfo.vue b/apps/web-antd/src/views/device/product/detail/components/BasicInfo.vue
index c0d34c4..a931625 100644
--- a/apps/web-antd/src/views/device/product/detail/components/BasicInfo.vue
+++ b/apps/web-antd/src/views/device/product/detail/components/BasicInfo.vue
@@ -129,7 +129,7 @@ const productParams = computed(() =>
{{ formatTime(productInfo.updateTime) }}
-
+
{{ productInfo.description || '暂无描述' }}
diff --git a/apps/web-antd/src/views/device/product/detail/components/EventDrawer.vue b/apps/web-antd/src/views/device/product/detail/components/EventDrawer.vue
new file mode 100644
index 0000000..36d65a2
--- /dev/null
+++ b/apps/web-antd/src/views/device/product/detail/components/EventDrawer.vue
@@ -0,0 +1,412 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/web-antd/src/views/device/product/detail/components/FunctionDrawer.vue b/apps/web-antd/src/views/device/product/detail/components/FunctionDrawer.vue
new file mode 100644
index 0000000..9c08229
--- /dev/null
+++ b/apps/web-antd/src/views/device/product/detail/components/FunctionDrawer.vue
@@ -0,0 +1,504 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/web-antd/src/views/device/product/detail/components/MetadataTable.vue b/apps/web-antd/src/views/device/product/detail/components/MetadataTable.vue
index 10b9e27..446f45d 100644
--- a/apps/web-antd/src/views/device/product/detail/components/MetadataTable.vue
+++ b/apps/web-antd/src/views/device/product/detail/components/MetadataTable.vue
@@ -2,28 +2,13 @@
import { computed, onMounted, ref, watch } from 'vue';
import { PlusOutlined } from '@ant-design/icons-vue';
-import {
- Button,
- Col,
- Drawer,
- Form,
- FormItem,
- Input,
- InputNumber,
- message,
- Popconfirm,
- RadioButton,
- RadioGroup,
- Row,
- Select,
- Space,
- Switch,
- Table,
- Tag,
- Textarea,
-} from 'ant-design-vue';
+import { Button, message, Popconfirm, Space, Table, Tag } from 'ant-design-vue';
-import EnumListModal from './EnumListModal.vue';
+import { dataTypeOptions, readWriteTypeOptions } from '#/constants/dicts';
+
+import EventDrawer from './EventDrawer.vue';
+import FunctionDrawer from './FunctionDrawer.vue';
+import PropertyDrawer from './PropertyDrawer.vue';
const props = defineProps<{
metadata: any[];
@@ -38,139 +23,14 @@ const emit = defineEmits<{
const loading = ref(false);
const drawerVisible = ref(false);
-const saveLoading = ref(false);
-const isEdit = ref(false);
-const formRef = ref();
-// 枚举列表弹窗相关
-const enumModalVisible = ref(false);
+const isEdit = ref(false);
+
+const editDataIndex = ref(-1);
const tableData = ref([]);
-const defaultPropertiesFormData = {
- id: '',
- name: '',
- sort: 1,
- description: '',
- required: false,
- expands: {
- source: 'device',
- type: 'R',
- },
- valueParams: {
- dataType: 'string',
- formType: 'input',
- length: null,
- viewType: 'input',
- unit: '',
- enumConf: [],
- },
-};
-
-const formData = ref({});
-
-const formRules = {
- id: [
- { required: true, message: '请输入标识符', trigger: 'blur' },
- {
- pattern: /^[a-z]\w*$/i,
- message: '请输入以字母开头,只包含字母、数字和下划线的标识符',
- trigger: 'blur',
- },
- ],
- name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
- valueParams: [{ required: true, message: '请选择数据类型', trigger: 'blur' }],
-};
-
-// 数据类型选项
-const dataTypeOptions = ref([
- {
- value: 'int',
- label: 'int(整数型)',
- },
- {
- value: 'long',
- label: 'long(长整数型)',
- },
- {
- value: 'float',
- label: 'float(单精度浮点型)',
- },
- {
- value: 'double',
- label: 'double(双精度浮点数)',
- },
- {
- value: 'string',
- label: 'text(字符串)',
- },
- {
- value: 'boolean',
- label: 'boolean(布尔型)',
- },
- {
- value: 'date',
- label: 'date(时间型)',
- },
- {
- value: 'enum',
- label: 'enum(枚举)',
- },
- // {
- // value: 'array',
- // label: 'array(数组)',
- // },
- // {
- // value: 'object',
- // label: 'object(结构体)',
- // },
- // {
- // value: 'file',
- // label: 'file(文件)',
- // },
- // {
- // value: 'password',
- // label: 'password(密码)',
- // },
- // {
- // value: 'geoPoint',
- // label: 'geoPoint(地理位置)',
- // }
-]);
-
-// 表单类型选项
-const formTypeOptions = ref([
- { label: '文本', value: 'input' },
- { label: '开关', value: 'switch' },
- { label: '数字', value: 'number' },
- { label: '进度条', value: 'progress' },
- { label: '选择器', value: 'select' },
- { label: '时间选择器', value: 'time' },
- // { label: '文本域', value: 'textarea' },
-]);
-
-const viewTypeOptions = ref([
- { label: '文本', value: 'input' },
- { label: '开关', value: 'switch' },
- { label: '选择器', value: 'select' },
- { label: '进度条', value: 'progress' },
- { label: '图片', value: 'img' },
- { label: '折线图', value: 'line' },
- { label: '仪表盘', value: 'dashboard' },
-]);
-
-// 读写类型选项
-const readWriteTypeOptions = ref([
- { label: '读', value: 'R' },
- { label: '写', value: 'W' },
- { label: '读写', value: 'RW' },
-]);
-
-const timeOptions = ref([
- { label: 'yyyy-MM-dd HH:mm:ss', value: 'yyyy-MM-dd HH:mm:ss' },
- { label: 'yyyy-MM-dd', value: 'yyyy-MM-dd' },
- { label: 'HH:mm:ss', value: 'HH:mm:ss' },
-]);
+const formData = ref(null);
// 表格列配置
const columns = computed(() => {
@@ -273,11 +133,6 @@ const getTypeLabel = () => {
return labels[props.type];
};
-// 抽屉标题
-const drawerTitle = computed(() => {
- return isEdit.value ? `编辑${getTypeLabel()}` : `新增${getTypeLabel()}`;
-});
-
// 加载数据
const loadData = async () => {
loading.value = true;
@@ -299,9 +154,10 @@ const handleAdd = () => {
};
// 编辑
-const handleEdit = (record: any) => {
+const handleEdit = (record: any, index: number) => {
+ editDataIndex.value = index;
isEdit.value = true;
- formData.value = structuredClone(record.value);
+ formData.value = JSON.parse(JSON.stringify(record));
drawerVisible.value = true;
};
@@ -321,54 +177,30 @@ const handleDelete = async (record: any) => {
};
// 保存
-const handleSave = async () => {
+const handleSave = async (data: any) => {
try {
- await formRef.value.validate();
- saveLoading.value = true;
-
if (isEdit.value) {
// 编辑模式
- const index = tableData.value.findIndex(
- (item) => item.id === formData.value.id,
- );
- if (index !== -1) {
- tableData.value[index] = { ...formData.value };
+ if (editDataIndex.value === -1) {
+ tableData.value.push({ ...data });
+ } else {
+ tableData.value[editDataIndex.value] = { ...data };
}
} else {
// 新增模式
- tableData.value.push({ ...formData.value });
+ tableData.value.push({ ...data });
}
- message.success('保存成功');
drawerVisible.value = false;
emit('change', tableData.value);
} catch {
message.error('保存失败');
- } finally {
- saveLoading.value = false;
}
};
-// 关闭抽屉
-const handleDrawerClose = () => {
- drawerVisible.value = false;
- resetForm();
-};
-
// 重置表单
const resetForm = () => {
- Object.assign(formData.value, structuredClone(defaultPropertiesFormData));
-};
-
-// 打开枚举列表编辑弹窗
-const handleEditEnum = () => {
- enumModalVisible.value = true;
-};
-
-// 确认枚举列表
-const handleEnumConfirm = (enumList: any[]) => {
- formData.value.valueParams.enumConf = enumList;
- enumModalVisible.value = false;
+ formData.value = null;
};
// 监听metadata变化
@@ -407,13 +239,13 @@ onMounted(() => {
:pagination="false"
row-key="id"
>
-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/apps/web-antd/src/views/device/product/detail/components/ParameterModal.vue b/apps/web-antd/src/views/device/product/detail/components/ParameterModal.vue
new file mode 100644
index 0000000..4ebbae8
--- /dev/null
+++ b/apps/web-antd/src/views/device/product/detail/components/ParameterModal.vue
@@ -0,0 +1,387 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/web-antd/src/views/device/product/detail/components/PropertyDrawer.vue b/apps/web-antd/src/views/device/product/detail/components/PropertyDrawer.vue
new file mode 100644
index 0000000..f8332a9
--- /dev/null
+++ b/apps/web-antd/src/views/device/product/detail/components/PropertyDrawer.vue
@@ -0,0 +1,468 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+