fix: 优化物模型-编辑表格标识校验

This commit is contained in:
xieyonghong 2023-07-07 21:57:12 +08:00
parent 2e50b866f0
commit 3231c7ea12
8 changed files with 162 additions and 72 deletions

View File

@ -89,7 +89,7 @@
{{ sourceMap?.[data.record?.expands?.source] || '' }} {{ sourceMap?.[data.record?.expands?.source] || '' }}
</template> </template>
<template #inputs="{ data }"> <template #inputs="{ data }">
<InputParams v-model:value="dataSource[data.index]" /> <InputParams v-model:value="data.record" />
</template> </template>
<template #output="{ data }"> <template #output="{ data }">
{{ data.record.output?.type }} {{ data.record.output?.type }}
@ -101,7 +101,7 @@
{{ levelMap?.[data.record.expands?.level] || '-' }} {{ levelMap?.[data.record.expands?.level] || '-' }}
</template> </template>
<template #properties="{ data }"> <template #properties="{ data }">
<ConfigParams v-model:value="dataSource[data.index]" /> <ConfigParams v-model:value="data.record" />
</template> </template>
<template #outInput> <template #outInput>
object object
@ -112,7 +112,7 @@
</j-tag> </j-tag>
</template> </template>
<template #other="{ data }"> <template #other="{ data }">
<OtherSetting v-model:value="dataSource[data.index]" /> <OtherSetting v-model:value="data.record" />
</template> </template>
<template #action="{data}"> <template #action="{data}">
<j-space> <j-space>

View File

@ -4,7 +4,7 @@ import SelectColumn from './components/Events/SelectColumn.vue';
import AsyncSelect from './components/Function/AsyncSelect.vue'; import AsyncSelect from './components/Function/AsyncSelect.vue';
import { EventLevel } from "@/views/device/data"; import { EventLevel } from "@/views/device/data";
import {MetadataType} from "@/views/device/Product/typings"; import {MetadataType} from "@/views/device/Product/typings";
import rule from "components/Metadata/Rule"; import { getUnit } from '@/api/device/instance';
import {Ref} from "vue"; import {Ref} from "vue";
interface DataTableColumnProps extends ColumnProps { interface DataTableColumnProps extends ColumnProps {
type?: string, type?: string,
@ -352,6 +352,25 @@ export const useColumns = (type?: MetadataType, target?: 'device' | 'product', n
return {columns} return {columns}
} }
export const useUnit = (type: Ref<string>) => {
const unitOptions = ref<Array<{ label: string, value: any }>>([])
watch(() => type.value, () => {
if (['float', 'double', 'int', 'long'].includes(type.value) && !unitOptions.value.length) {
getUnit().then((res) => {
if (res.success) {
unitOptions.value = res.result.map((item: any) => ({
label: item.description,
value: item.id,
}));
}
});
}
})
return { unitOptions }
}
// const MetadataMapping = new Map<string, DataTableColumnProps[]>(); // const MetadataMapping = new Map<string, DataTableColumnProps[]>();
// MetadataMapping.set('properties', PropertyColumns); // MetadataMapping.set('properties', PropertyColumns);

View File

@ -2,7 +2,7 @@
<DataTableArray <DataTableArray
v-if="type === 'array'" v-if="type === 'array'"
v-model:value="myValue.elementType" v-model:value="myValue.elementType"
:unitOptions="options" :unitOptions="unitOptions"
placement="topRight" placement="topRight"
@confirm="valueChange" @confirm="valueChange"
> >
@ -17,8 +17,44 @@
placement="topRight" placement="topRight"
:onAdd="objectAdd" :onAdd="objectAdd"
:columns="[ :columns="[
{ title: '参数标识', dataIndex: 'id', type: 'text', width: 100 }, {
{ title: '参数名称', dataIndex: 'name', type: 'text', width: 100 }, title: '参数标识',
dataIndex: 'id',
type: 'text',
width: 100,
form: {
required: true,
rules: [
{
callback(rule:any,value: any, _dataSource: any[]) {
if (value) {
const field = rule.field.split('.')
const fieldIndex = Number(field[1])
const hasId = _dataSource.some((item, index) => item.id === value && fieldIndex !== index)
if (hasId) {
return Promise.reject('该标识存在')
}
return Promise.resolve()
}
return Promise.reject('请输入标识')
}
}
]
}
},
{
title: '参数名称',
dataIndex: 'name',
type: 'text',
width: 100,
form: {
required: true,
rules: [{
required: true,
message: '请输入参数名称'
}]
}
},
{ {
title: '数据类型', title: '数据类型',
type: 'components', type: 'components',
@ -83,7 +119,7 @@
</DataTableBoolean> </DataTableBoolean>
<DataTableDouble <DataTableDouble
v-else-if="['float', 'double'].includes(type)" v-else-if="['float', 'double'].includes(type)"
:options="options" :options="unitOptions"
v-model:value="myValue" v-model:value="myValue"
placement="topRight" placement="topRight"
@confirm="valueChange" @confirm="valueChange"
@ -95,7 +131,7 @@
</DataTableDouble> </DataTableDouble>
<DataTableInteger <DataTableInteger
v-else-if="['int', 'long'].includes(type)" v-else-if="['int', 'long'].includes(type)"
:options="options" :options="unitOptions"
v-model:value="myValue.unit" v-model:value="myValue.unit"
placement="topRight" placement="topRight"
@confirm="valueChange" @confirm="valueChange"
@ -171,6 +207,7 @@ const props = defineProps({
}) })
const emit = defineEmits(['update:value']) const emit = defineEmits(['update:value'])
import {useUnit} from "@/views/device/components/Metadata/Base/columns";
const objectAdd = () => { const objectAdd = () => {
return { return {
@ -186,6 +223,8 @@ const options = ref([])
const type = ref(props.value?.[props.valueKey]?.type) const type = ref(props.value?.[props.valueKey]?.type)
const { unitOptions } = useUnit(type)
const myValue = ref(props.value?.[props.valueKey]) const myValue = ref(props.value?.[props.valueKey])
const valueChange = () => { const valueChange = () => {

View File

@ -6,7 +6,7 @@
<DataTableArray <DataTableArray
v-if="type === 'array'" v-if="type === 'array'"
v-model:value="_valueType.elementType" v-model:value="_valueType.elementType"
:unitOptions="options" :unitOptions="unitOptions"
placement="topRight" placement="topRight"
@confirm="(data) => {valueChange(data, 'array')}" @confirm="(data) => {valueChange(data, 'array')}"
/> />
@ -22,7 +22,7 @@
</template> </template>
<template #config="{ data }"> <template #config="{ data }">
<!-- <OtherConfigInfo :value="data.record.valueType"></OtherConfigInfo>--> <!-- <OtherConfigInfo :value="data.record.valueType"></OtherConfigInfo>-->
<ConfigModal v-model:value="data.record" /> <ConfigModal v-model:value="data.record" :unitOptions="unitOptions" />
</template> </template>
</DataTableObject> </DataTableObject>
<DataTableEnum v-else-if="type === 'enum'" v-model:value="_valueType" placement="topRight" @confirm="(data) => {valueChange(data, 'enum')}"/> <DataTableEnum v-else-if="type === 'enum'" v-model:value="_valueType" placement="topRight" @confirm="(data) => {valueChange(data, 'enum')}"/>
@ -68,7 +68,7 @@ import {
DataTableObject, DataTableObject,
} from 'jetlinks-ui-components'; } from 'jetlinks-ui-components';
import { cloneDeep } from 'lodash-es'; import { cloneDeep } from 'lodash-es';
import {handleTypeValue, typeSelectChange} from '../columns' import {handleTypeValue, typeSelectChange, useUnit } from '../columns'
import ConfigModal from './ConfigModal.vue' import ConfigModal from './ConfigModal.vue'
const props = defineProps({ const props = defineProps({
@ -155,22 +155,24 @@ const valueChange = (_data: any, _type: string) => {
}); });
} }
const { unitOptions } = useUnit(type)
watch( watch(
() => JSON.stringify(props.value), () => JSON.stringify(props.value),
() => { () => {
type.value = props.value?.valueType?.type; type.value = props.value?.valueType?.type;
_valueType.value = props.value?.valueType _valueType.value = props.value?.valueType
// elements.value = props.value?.valueType.elements; // elements.value = props.value?.valueType.elements;
if (['float', 'double', 'int', 'long'].includes(type.value)) { // if (['float', 'double', 'int', 'long'].includes(type.value)) {
const res = getUnit().then((res) => { // const res = getUnit().then((res) => {
if (res.success) { // if (res.success) {
options.value = res.result.map((item) => ({ // options.value = res.result.map((item) => ({
label: item.description, // label: item.description,
value: item.id, // value: item.id,
})); // }));
} // }
}); // });
} // }
}, },
{ immediate: true }, { immediate: true },
); );

View File

@ -29,7 +29,6 @@
<script setup lang="ts" name="DataTypeObjectChild"> <script setup lang="ts" name="DataTypeObjectChild">
import { getUnit } from '@/api/device/instance'; import { getUnit } from '@/api/device/instance';
import { OtherConfigInfo } from '../components'
import { import {
DataTableString, DataTableString,
DataTableArray, DataTableArray,

View File

@ -4,7 +4,7 @@
<span>{{ data.record.valueType?.type }}</span> <span>{{ data.record.valueType?.type }}</span>
</template> </template>
<template #config="{ data }"> <template #config="{ data }">
<OtherConfigInfo :value="data.record.valueType"></OtherConfigInfo> <ConfigModal v-model:value="data.record" />
</template> </template>
<j-button> <j-button>
<AIcon type="SettingOutlined" /> <AIcon type="SettingOutlined" />
@ -15,11 +15,12 @@
<script setup lang="ts" name="InputParams"> <script setup lang="ts" name="InputParams">
import type { PropType } from 'vue'; import type { PropType } from 'vue';
import DataTypeObjectChild from '../DataTypeObjectChild.vue'
import { import {
DataTableObject, DataTableObject,
} from 'jetlinks-ui-components'; } from 'jetlinks-ui-components';
import { OtherConfigInfo, ValueObject } from '../index' import { ValueObject } from '../index'
import ConfigModal from '@/views/device/components/Metadata/Base/components/ConfigModal.vue'
const columns = [ const columns = [
{ {
@ -29,8 +30,18 @@ const columns = [
form: { form: {
required: true, required: true,
rules: [{ rules: [{
required: true, callback(rule:any,value: any, _dataSource: any[]) {
message: '请输入参数标识' if (value) {
const field = rule.field.split('.')
const fieldIndex = Number(field[1])
const hasId = _dataSource.some((item, index) => item.id === value && fieldIndex !== index)
if (hasId) {
return Promise.reject('该标识存在')
}
return Promise.resolve()
}
return Promise.reject('请输入标识')
}
}] }]
} }
}, },
@ -52,15 +63,14 @@ const columns = [
dataIndex: 'valueType', dataIndex: 'valueType',
components: { components: {
name: ValueObject, name: ValueObject,
props: {
filter: ['object']
}
}, },
}, },
{ {
title: '其他配置', title: '其他配置',
dataIndex: 'config', dataIndex: 'config',
type: 'components',
components: {
name: DataTypeObjectChild
}
}, },
{ {
title: '操作', title: '操作',
@ -91,15 +101,18 @@ const props = defineProps({
}); });
const value = ref(props.value.valueType?.properties); const value = ref(props.value.valueType?.properties);
const type = computed(() => {
return props.value.valueType?.type
})
const change = (v: string) => { const change = (v: string) => {
emit('update:value', { ...props.value, async: value.value }); emit('update:value', { ...props.value, async: value.value });
emit('change', v); emit('change', v);
}; };
const confirm = () => { const confirm = (data: any) => {
const newObject = value.value.map((item) => { const newObject = data.map((item) => {
const { config, action, ...extra } = item const { config, action, _sortIndex, ...extra } = item
return extra return extra
}) })

View File

@ -22,7 +22,7 @@ import ConfigModal from '@/views/device/components/Metadata/Base/components/Conf
import { import {
DataTableObject, DataTableObject,
} from 'jetlinks-ui-components'; } from 'jetlinks-ui-components';
import { ConstraintSelect, OtherConfigInfo, ValueObject } from '../index' import { ConstraintSelect, ValueObject } from '../index'
type Emits = { type Emits = {
@ -70,12 +70,11 @@ const columns = ref([
rules: [ rules: [
{ required: true, message: '请输入标识' }, { required: true, message: '请输入标识' },
{ {
validator(va:any,value: any) { callback(rule:any,value: any, _dataSource: any[]) {
const fieldIndex = va.field.split('.')[1]
const oldValue = (dataSource!.value || []).filter((_, index) => index != fieldIndex)
console.log(dataSource!.value)
const hasId = oldValue.some((item) => item.id === value)
if (value) { if (value) {
const field = rule.field.split('.')
const fieldIndex = Number(field[1])
const hasId = _dataSource.some((item, index) => item.id === value && fieldIndex !== index)
if (hasId) { if (hasId) {
return Promise.reject('该标识存在') return Promise.reject('该标识存在')
} }
@ -103,6 +102,9 @@ const columns = ref([
dataIndex: 'valueType', dataIndex: 'valueType',
components: { components: {
name: ValueObject, name: ValueObject,
form: {
required: true
}
}, },
}, },
{ {

View File

@ -11,6 +11,7 @@
<DataTableObject <DataTableObject
v-else-if="type === 'object'" v-else-if="type === 'object'"
v-model:value="data.properties" v-model:value="data.properties"
placement="topRight"
:columns="[ :columns="[
{ {
title: '参数标识', title: '参数标识',
@ -19,8 +20,18 @@
form: { form: {
required: true, required: true,
rules: [{ rules: [{
required: true, callback(rule:any,value: any, dataSource: any[]) {
message: '请输入参数标识' if (value) {
const field = rule.field.split('.')
const fieldIndex = Number(field[1])
const hasId = dataSource.some((item, index) => item.id === value && fieldIndex !== index)
if (hasId) {
return Promise.reject('该标识存在')
}
return Promise.resolve()
}
return Promise.reject('请输入标识')
}
}] }]
} }
}, },
@ -32,7 +43,7 @@
required: true, required: true,
rules: [{ rules: [{
required: true, required: true,
message: '请输入参数标识名称' message: '请输入参数名称'
}] }]
} }
}, },
@ -42,15 +53,18 @@
dataIndex: 'valueType', dataIndex: 'valueType',
components: { components: {
name: Type, name: Type,
},
form: {
required: true,
rules: [{
required: true,
message: '请选择数据类型'
}]
} }
}, },
{ {
title: '其他配置', title: '其他配置',
type: 'components',
dataIndex: 'config', dataIndex: 'config',
components: {
name: DataTypeObjectChild
}
}, },
{ {
title: '操作', title: '操作',
@ -65,20 +79,20 @@
<span>{{ data.record.valueType?.type }}</span> <span>{{ data.record.valueType?.type }}</span>
</template> </template>
<template #config="{ data }"> <template #config="{ data }">
<OtherConfigInfo :value="data.record.valueType"></OtherConfigInfo> <ConfigModal v-model:value="data.record" />
</template> </template>
</DataTableObject> </DataTableObject>
<DataTableEnum v-else-if="type === 'enum'" v-model:value="data" @confirm="valueChange"/> <DataTableEnum v-else-if="type === 'enum'" v-model:value="data" @confirm="valueChange"/>
<DataTableBoolean v-else-if="type === 'boolean'" v-model:value="data" @confirm="valueChange"/> <DataTableBoolean v-else-if="type === 'boolean'" v-model:value="data" @confirm="valueChange"/>
<DataTableDouble <DataTableDouble
v-else-if="['float', 'double'].includes(type)" v-else-if="['float', 'double'].includes(type)"
:options="options" :options="unitOptions"
v-model:value="data" v-model:value="data"
@confirm="valueChange" @confirm="valueChange"
/> />
<DataTableInteger <DataTableInteger
v-else-if="['int', 'long'].includes(type)" v-else-if="['int', 'long'].includes(type)"
:options="options" :options="unitOptions"
v-model:value="data.unit" v-model:value="data.unit"
@confirm="valueChange" @confirm="valueChange"
/> />
@ -107,10 +121,9 @@ import {
DataTableObject, DataTableObject,
} from 'jetlinks-ui-components'; } from 'jetlinks-ui-components';
import DataTypeObjectChild from '../DataTypeObjectChild.vue'; import ConfigModal from '@/views/device/components/Metadata/Base/components/ConfigModal.vue'
import { cloneDeep } from 'lodash-es'; import { cloneDeep } from 'lodash-es';
import {typeSelectChange} from "@/views/device/components/Metadata/Base/columns"; import {typeSelectChange, useUnit} from "@/views/device/components/Metadata/Base/columns";
import { OtherConfigInfo } from '../index'
import Type from './Type.vue' import Type from './Type.vue'
const props = defineProps({ const props = defineProps({
@ -120,12 +133,15 @@ const props = defineProps({
}, },
}); });
const options = ref<{ label: string; value: string }[]>([]); const options = ref<{ label: string; value: string }[]>([]);
const emit = defineEmits(['update:value']); const emit = defineEmits(['update:value']);
const type = ref(props.value?.output?.type); const type = ref(props.value?.output?.type);
const data = ref(cloneDeep(props.value?.output)); const data = ref(cloneDeep(props.value?.output));
const { unitOptions } = useUnit(type)
const typeChange = (e: string) => { const typeChange = (e: string) => {
data.value = typeSelectChange(e) data.value = typeSelectChange(e)
emit('update:value', { emit('update:value', {
@ -139,16 +155,16 @@ watch(
() => { () => {
type.value = props.value?.output?.type; type.value = props.value?.output?.type;
data.value = props.value?.output data.value = props.value?.output
if (['float', 'double', 'int', 'long'].includes(type.value)) { // if (['float', 'double', 'int', 'long'].includes(type.value)) {
const res = getUnit().then((res) => { // const res = getUnit().then((res) => {
if (res.success) { // if (res.success) {
options.value = res.result.map((item) => ({ // options.value = res.result.map((item) => ({
label: item.description, // label: item.description,
value: item.id, // value: item.id,
})); // }));
} // }
}); // });
} // }
}, },
{ immediate: true, deep: true }, { immediate: true, deep: true },
); );