fix: 物模型开发
This commit is contained in:
parent
ee37c20d8d
commit
9189d8a212
|
@ -2,20 +2,33 @@
|
||||||
<a-form-item label="来源" :name="name.concat(['source'])" v-if="type === 'product'" :rules="[
|
<a-form-item label="来源" :name="name.concat(['source'])" v-if="type === 'product'" :rules="[
|
||||||
{ required: true, message: '请选择来源' },
|
{ required: true, message: '请选择来源' },
|
||||||
]">
|
]">
|
||||||
<a-select v-model:value="_value.source" :options="PropertySource" size="small" :disabled="metadataStore.model.action === 'edit'"></a-select>
|
<a-select v-model:value="_value.source" :options="PropertySource" size="small"
|
||||||
|
:disabled="metadataStore.model.action === 'edit'"></a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<virtual-rule-param v-if="_value.source === 'rule'" v-model:value="_value.virtualRule" :name="name.concat(['virtualRule'])" :id="id" :showWindow="_value.source === 'rule'"></virtual-rule-param>
|
<virtual-rule-param v-if="_value.source === 'rule'" v-model:value="_value.virtualRule"
|
||||||
|
:name="name.concat(['virtualRule'])" :id="id" :showWindow="_value.source === 'rule'"></virtual-rule-param>
|
||||||
<a-form-item label="读写类型" :name="name.concat(['type'])" :rules="[
|
<a-form-item label="读写类型" :name="name.concat(['type'])" :rules="[
|
||||||
{ required: true, message: '请选择读写类型' },
|
{ required: true, message: '请选择读写类型' },
|
||||||
]">
|
]">
|
||||||
<a-select v-model:value="_value.type" :options="options" mode="multiple" size="small"></a-select>
|
<a-select v-model:value="_value.type" :options="options" mode="multiple" size="small"></a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
<a-form-item label="其他配置" v-if="config.length > 0">
|
||||||
|
<a-form-item v-for="(item, index) in config" :key="index">
|
||||||
|
<config-param v-model:value="_value" :config="item" :name="name"></config-param>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item v-if="type === 'product' && ['int', 'float', 'double', 'long', 'date', 'string', 'boolean'].includes(valueType.type)"
|
||||||
|
label="指标配置" :name="name.concat(['metrics'])">
|
||||||
|
<metrics-param v-model:value="_value.metrics" :type="valueType.type" :enum="valueType"></metrics-param>
|
||||||
|
</a-form-item>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts" name="ExpandsForm">
|
<script setup lang="ts" name="ExpandsForm">
|
||||||
import { useMetadataStore } from '@/store/metadata';
|
import { useMetadataStore } from '@/store/metadata';
|
||||||
import { PropertySource } from '@/views/device/data';
|
import { PropertySource } from '@/views/device/data';
|
||||||
import { PropType } from 'vue';
|
import { PropType } from 'vue';
|
||||||
import VirtualRuleParam from '@/components/Metadata/VirtualRuleParam/index.vue';
|
import VirtualRuleParam from '@/components/Metadata/VirtualRuleParam/index.vue';
|
||||||
|
import ConfigParam from '@/components/Metadata/ConfigParam/index.vue'
|
||||||
|
import MetricsParam from '@/components/Metadata/MetricsParam/index.vue'
|
||||||
|
|
||||||
type ValueType = Record<any, any>;
|
type ValueType = Record<any, any>;
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
@ -34,6 +47,14 @@ const props = defineProps({
|
||||||
id: {
|
id: {
|
||||||
type: String
|
type: String
|
||||||
},
|
},
|
||||||
|
config: {
|
||||||
|
type: Array as PropType<ValueType[]>,
|
||||||
|
default: () => ([])
|
||||||
|
},
|
||||||
|
valueType: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
interface Emits {
|
interface Emits {
|
||||||
|
|
|
@ -1,54 +1,83 @@
|
||||||
<template>
|
<template>
|
||||||
<a-form ref="addFormRef" :model="form.model" layout="vertical">
|
<a-form-item label="标识" name="id" :rules="[
|
||||||
<a-form-item label="标识" name="id" :rules="[
|
{ required: true, message: '请输入标识' },
|
||||||
{ required: true, message: '请输入标识' },
|
{ max: 64, message: '最多可输入64个字符' },
|
||||||
{ max: 64, message: '最多可输入64个字符' },
|
{
|
||||||
{
|
pattern: /^[a-zA-Z0-9_\-]+$/,
|
||||||
pattern: /^[a-zA-Z0-9_]+$/,
|
message: 'ID只能由数字、字母、下划线、中划线组成',
|
||||||
message: '请输入英文或者数字或者-或者_',
|
},
|
||||||
},
|
]">
|
||||||
]">
|
<a-input v-model:value="value.id" size="small" @change="asyncOtherConfig"></a-input>
|
||||||
<a-input v-model:value="form.model.id" size="small"></a-input>
|
</a-form-item>
|
||||||
</a-form-item>
|
<a-form-item label="名称" name="name" :rules="[
|
||||||
<a-form-item label="名称" name="name" :rules="[
|
{ required: true, message: '请输入名称' },
|
||||||
{ required: true, message: '请输入名称' },
|
{ max: 64, message: '最多可输入64个字符' },
|
||||||
{ max: 64, message: '最多可输入64个字符' },
|
]">
|
||||||
]">
|
<a-input v-model:value="value.name" size="small"></a-input>
|
||||||
<a-input v-model:value="form.model.name" size="small"></a-input>
|
</a-form-item>
|
||||||
</a-form-item>
|
<value-type-form :name="['valueType']" v-model:value="value.valueType" key="property"
|
||||||
<value-type-form :name="['valueType']" v-model:value="form.model.valueType" key="property"></value-type-form>
|
@change-type="changeValueType"></value-type-form>
|
||||||
|
|
||||||
<expands-form :name="['expands']" v-model:value="form.model.expands" :type="type" :id="form.model.id"></expands-form>
|
<expands-form :name="['expands']" v-model:value="value.expands" :type="type" :id="value.id" :config="config"
|
||||||
|
:valueType="value.valueType"></expands-form>
|
||||||
|
|
||||||
<a-form-item label="说明" name="description" :rules="[
|
<a-form-item label="说明" name="description" :rules="[
|
||||||
{ max: 200, message: '最多可输入200个字符' },
|
{ max: 200, message: '最多可输入200个字符' },
|
||||||
]">
|
]">
|
||||||
<a-textarea v-model:value="form.model.description" size="small"></a-textarea>
|
<a-textarea v-model:value="value.description" size="small"></a-textarea>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts" name="PropertyForm">
|
<script setup lang="ts" name="PropertyForm">
|
||||||
import { PropType } from 'vue';
|
import { PropType } from 'vue';
|
||||||
import ExpandsForm from './ExpandsForm.vue';
|
import ExpandsForm from './ExpandsForm.vue';
|
||||||
import ValueTypeForm from './ValueTypeForm.vue'
|
import ValueTypeForm from './ValueTypeForm.vue'
|
||||||
|
import { useProductStore } from '@/store/product';
|
||||||
|
import { getMetadataConfig } from '@/api/device/product'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
type: {
|
type: {
|
||||||
type: String as PropType<'product' | 'device'>,
|
type: String as PropType<'product' | 'device'>,
|
||||||
required: true,
|
required: true,
|
||||||
default: 'product'
|
default: 'product'
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
const productStore = useProductStore()
|
||||||
|
|
||||||
const form = reactive({
|
const config = ref<Record<any, any>[]>([])
|
||||||
model: {
|
const asyncOtherConfig = async () => {
|
||||||
valueType: {
|
if (props.type !== 'product') return
|
||||||
expands: {}
|
const { valueType: { type }, id } = props.value
|
||||||
|
const productId = productStore.current?.id
|
||||||
|
if (!productId || !id || !type) return
|
||||||
|
const resp = await getMetadataConfig({
|
||||||
|
deviceId: productId,
|
||||||
|
metadata: {
|
||||||
|
id,
|
||||||
|
type: 'property',
|
||||||
|
dataType: type,
|
||||||
},
|
},
|
||||||
expands: {}
|
})
|
||||||
} as any,
|
if (resp.status === 200) {
|
||||||
|
config.value = resp.result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onMounted(() => {
|
||||||
|
asyncOtherConfig()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const changeValueType = (val: string) => {
|
||||||
|
if (props.type === 'product' && ['int', 'float', 'double', 'long', 'date', 'string', 'boolean'].includes(val)) {
|
||||||
|
props.value.expands.metrics = []
|
||||||
|
} else {
|
||||||
|
delete props.value.expands?.metrics
|
||||||
|
}
|
||||||
|
asyncOtherConfig()
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
:deep(.ant-form-item-label) {
|
:deep(.ant-form-item-label) {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<a-form-item label="数据类型" :name="name.concat(['type'])" :rules="[
|
<a-form-item label="数据类型" :name="name.concat(['type'])" :rules="[
|
||||||
{ required: true, message: '请选择数据类型' },
|
{ required: true, message: '请选择数据类型' },
|
||||||
]">
|
]">
|
||||||
<a-select v-model:value="value.type" :options="_dataTypeList" size="small"></a-select>
|
<a-select v-model:value="value.type" :options="_dataTypeList" size="small" @change="changeType"></a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="单位" :name="name.concat(['unit'])" v-if="['int', 'float', 'long', 'double'].includes(value.type)">
|
<a-form-item label="单位" :name="name.concat(['unit'])" v-if="['int', 'float', 'long', 'double'].includes(value.type)">
|
||||||
<InputSelect v-model:value="value.unit" :options="unit.unitOptions" size="small"></InputSelect>
|
<InputSelect v-model:value="value.unit" :options="unit.unitOptions" size="small"></InputSelect>
|
||||||
|
@ -48,7 +48,7 @@
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup mame="BaseForm">
|
<script lang="ts" setup mame="BaseForm">
|
||||||
import { DataTypeList, FileTypeList } from '@/views/device/data';
|
import { DataTypeList, FileTypeList } from '@/views/device/data';
|
||||||
import { DefaultOptionType } from 'ant-design-vue/es/select';
|
import { DefaultOptionType, SelectValue } from 'ant-design-vue/es/select';
|
||||||
import { PropType } from 'vue'
|
import { PropType } from 'vue'
|
||||||
import { getUnit } from '@/api/device/instance';
|
import { getUnit } from '@/api/device/instance';
|
||||||
import { Store } from 'jetlinks-store';
|
import { Store } from 'jetlinks-store';
|
||||||
|
@ -79,6 +79,7 @@ const props = defineProps({
|
||||||
|
|
||||||
interface Emits {
|
interface Emits {
|
||||||
(e: 'update:value', data: ValueType): void;
|
(e: 'update:value', data: ValueType): void;
|
||||||
|
(e: 'changeType', data: string): void;
|
||||||
}
|
}
|
||||||
const emit = defineEmits<Emits>()
|
const emit = defineEmits<Emits>()
|
||||||
|
|
||||||
|
@ -107,6 +108,10 @@ const unit = {
|
||||||
unit.getUnit()
|
unit.getUnit()
|
||||||
|
|
||||||
const _dataTypeList = computed(() => props.isSub ? DataTypeList.filter(item => item.value !== 'array' && item.value !== 'object') : DataTypeList)
|
const _dataTypeList = computed(() => props.isSub ? DataTypeList.filter(item => item.value !== 'array' && item.value !== 'object') : DataTypeList)
|
||||||
|
|
||||||
|
const changeType = (val: SelectValue) => {
|
||||||
|
emit('changeType', val as string)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
:deep(.ant-form-item-label) {
|
:deep(.ant-form-item-label) {
|
||||||
|
|
|
@ -4,19 +4,20 @@
|
||||||
<template #extra>
|
<template #extra>
|
||||||
<a-button :loading="save.loading" type="primary" @click="save.saveMetadata">保存</a-button>
|
<a-button :loading="save.loading" type="primary" @click="save.saveMetadata">保存</a-button>
|
||||||
</template>
|
</template>
|
||||||
<PropertyForm v-if="metadataStore.model.type === 'properties'" :type="type"></PropertyForm>
|
<a-form ref="formRef" :model="form.model" layout="vertical">
|
||||||
|
<PropertyForm v-if="metadataStore.model.type === 'properties'" :type="type" ref="propertyForm" v-model:value="form.model"></PropertyForm>
|
||||||
|
</a-form>
|
||||||
</a-drawer>
|
</a-drawer>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup name="Edit">
|
<script lang="ts" setup name="Edit">
|
||||||
import { useInstanceStore } from '@/store/instance';
|
import { useInstanceStore } from '@/store/instance';
|
||||||
import { useMetadataStore } from '@/store/metadata';
|
import { useMetadataStore } from '@/store/metadata';
|
||||||
import { useProductStore } from '@/store/product';
|
import { useProductStore } from '@/store/product';
|
||||||
import { MetadataItem, ProductItem } from '@/views/device/Product/typings';
|
import { ProductItem } from '@/views/device/Product/typings';
|
||||||
import { message } from 'ant-design-vue/es';
|
import { message } from 'ant-design-vue/es';
|
||||||
import type { FormInstance } from 'ant-design-vue/es';
|
import type { FormInstance } from 'ant-design-vue/es';
|
||||||
import { updateMetadata, asyncUpdateMetadata } from '../../metadata'
|
import { updateMetadata, asyncUpdateMetadata } from '../../metadata'
|
||||||
import { Store } from 'jetlinks-store';
|
import { Store } from 'jetlinks-store';
|
||||||
import { SystemConst } from '@/utils/consts';
|
|
||||||
import { detail } from '@/api/device/instance';
|
import { detail } from '@/api/device/instance';
|
||||||
import { DeviceInstance } from '@/views/device/Instance/typings';
|
import { DeviceInstance } from '@/views/device/Instance/typings';
|
||||||
import PropertyForm from './PropertyForm.vue';
|
import PropertyForm from './PropertyForm.vue';
|
||||||
|
@ -50,7 +51,21 @@ const close = () => {
|
||||||
|
|
||||||
const title = computed(() => metadataStore.model.action === 'add' ? '新增' : '修改')
|
const title = computed(() => metadataStore.model.action === 'add' ? '新增' : '修改')
|
||||||
|
|
||||||
const addFormRef = ref<FormInstance>()
|
const propertyForm = ref()
|
||||||
|
|
||||||
|
const form = reactive({
|
||||||
|
model: {
|
||||||
|
valueType: {
|
||||||
|
expands: {}
|
||||||
|
},
|
||||||
|
expands: {}
|
||||||
|
} as any,
|
||||||
|
})
|
||||||
|
if (metadataStore.model.action === 'edit') {
|
||||||
|
form.model = metadataStore.model.item
|
||||||
|
}
|
||||||
|
|
||||||
|
const formRef = ref<FormInstance>()
|
||||||
/**
|
/**
|
||||||
* 保存按钮
|
* 保存按钮
|
||||||
*/
|
*/
|
||||||
|
@ -58,7 +73,7 @@ const save = reactive({
|
||||||
loading: false,
|
loading: false,
|
||||||
saveMetadata: (deploy?: boolean) => {
|
saveMetadata: (deploy?: boolean) => {
|
||||||
save.loading = true
|
save.loading = true
|
||||||
addFormRef.value?.validateFields().then(async (formValue) => {
|
formRef.value?.validateFields().then(async (formValue) => {
|
||||||
const type = metadataStore.model.type
|
const type = metadataStore.model.type
|
||||||
const _detail: ProductItem | DeviceInstance = props.type === 'device' ? instanceStore.detail : productStore.current
|
const _detail: ProductItem | DeviceInstance = props.type === 'device' ? instanceStore.detail : productStore.current
|
||||||
const _metadata = JSON.parse(_detail?.metadata || '{}')
|
const _metadata = JSON.parse(_detail?.metadata || '{}')
|
||||||
|
@ -90,8 +105,9 @@ const save = reactive({
|
||||||
setTimeout(() => window.close(), 300);
|
setTimeout(() => window.close(), 300);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Store.set(SystemConst.REFRESH_METADATA_TABLE, true);
|
// Store.set(SystemConst.REFRESH_METADATA_TABLE, true);
|
||||||
if (deploy) {
|
if (deploy) {
|
||||||
|
// TODO 是否发布
|
||||||
Store.set('product-deploy', deploy);
|
Store.set('product-deploy', deploy);
|
||||||
} else {
|
} else {
|
||||||
save.resetMetadata();
|
save.resetMetadata();
|
||||||
|
@ -121,9 +137,6 @@ const save = reactive({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const form = reactive({
|
|
||||||
model: {} as Record<string, any>
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|
||||||
|
|
|
@ -33,22 +33,24 @@
|
||||||
</a-tag>
|
</a-tag>
|
||||||
</template>
|
</template>
|
||||||
<template #action="slotProps">
|
<template #action="slotProps">
|
||||||
<PermissionButton :uhas-permission="`${permission}:update`" type="link" key="edit" style="padding: 0"
|
<a-space>
|
||||||
:udisabled="operateLimits('updata', type)" @click="handleEditClick(slotProps)" :tooltip="{
|
<PermissionButton :uhas-permission="`${permission}:update`" type="link" key="edit" style="padding: 0"
|
||||||
title: operateLimits('updata', type) ? '当前的存储方式不支持编辑' : '编辑',
|
:udisabled="operateLimits('updata', type)" @click="handleEditClick(slotProps)" :tooltip="{
|
||||||
}">
|
title: operateLimits('updata', type) ? '当前的存储方式不支持编辑' : '编辑',
|
||||||
<EditOutlined />
|
}">
|
||||||
</PermissionButton>
|
<EditOutlined />
|
||||||
<PermissionButton :uhas-permission="`${permission}:delete`" type="link" key="delete" style="padding: 0"
|
</PermissionButton>
|
||||||
:pop-confirm="{
|
<PermissionButton :uhas-permission="`${permission}:delete`" type="link" key="delete" style="padding: 0"
|
||||||
title: '确认删除?', onConfirm: async () => {
|
:pop-confirm="{
|
||||||
await removeItem(slotProps);
|
title: '确认删除?', onConfirm: async () => {
|
||||||
},
|
await removeItem(slotProps);
|
||||||
}" :tooltip="{
|
},
|
||||||
title: '删除',
|
}" :tooltip="{
|
||||||
}">
|
title: '删除',
|
||||||
<DeleteOutlined />
|
}">
|
||||||
</PermissionButton>
|
<DeleteOutlined />
|
||||||
|
</PermissionButton>
|
||||||
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
</JTable>
|
</JTable>
|
||||||
</template>
|
</template>
|
||||||
|
@ -123,6 +125,7 @@ onMounted(() => {
|
||||||
})
|
})
|
||||||
|
|
||||||
watch([route.params.id, type], () => {
|
watch([route.params.id, type], () => {
|
||||||
|
loading.value = true
|
||||||
// const res = target === 'product'
|
// const res = target === 'product'
|
||||||
// ? await productDetail(route.params.id as string)
|
// ? await productDetail(route.params.id as string)
|
||||||
// : await detail(route.params.id as string);
|
// : await detail(route.params.id as string);
|
||||||
|
|
Loading…
Reference in New Issue