fix: iot 补齐 vue3 源缺失的表单校验(P1)
- 物模型功能定义「数据类型」字段补 required 必填校验 - 产品选择器(ProductSelect)补搜索能力:antd 加 show-search + option-filter-prop ,ele 加 filterable - 设备表单 onConfirm 增加 advancedFormApi.validate() 调用, 否则高级表单(含经纬度等字段)的 schema rules 不会触发 - 设备经纬度增加「成对填写」跨字段校验:仅填一项时给 warning 提示, 与 vue3 源 DeviceForm.vue 行为对齐pull/345/head
parent
d207e3b82c
commit
58f2e23654
|
|
@ -75,7 +75,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||
label: '是否处理',
|
||||
component: 'Select',
|
||||
componentProps: {
|
||||
options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING),
|
||||
options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'),
|
||||
placeholder: '请选择是否处理',
|
||||
allowClear: true,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -118,6 +118,26 @@ const [Modal, modalApi] = useVbenModal({
|
|||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
// 高级表单:先单独校验,再做经纬度成对填写的跨字段检查
|
||||
if (advancedFormApi.isMounted) {
|
||||
const { valid: advancedValid } = await advancedFormApi.validate();
|
||||
if (!advancedValid) {
|
||||
return;
|
||||
}
|
||||
const advValues = await advancedFormApi.getValues();
|
||||
const hasLongitude =
|
||||
advValues.longitude !== undefined &&
|
||||
advValues.longitude !== null &&
|
||||
advValues.longitude !== '';
|
||||
const hasLatitude =
|
||||
advValues.latitude !== undefined &&
|
||||
advValues.latitude !== null &&
|
||||
advValues.latitude !== '';
|
||||
if (hasLongitude !== hasLatitude) {
|
||||
message.warning(hasLongitude ? '请同时填写设备纬度' : '请同时填写设备经度');
|
||||
return;
|
||||
}
|
||||
}
|
||||
modalApi.lock();
|
||||
// 合并两个表单的值(字段不冲突,可直接合并)
|
||||
const basicValues = await formApi.getValues();
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ export function getMessageTrendChartOptions(
|
|||
},
|
||||
},
|
||||
legend: {
|
||||
data: ['上行消息', '下行消息'],
|
||||
data: ['上行消息量', '下行消息量'],
|
||||
top: '5%',
|
||||
},
|
||||
grid: {
|
||||
|
|
@ -40,11 +40,21 @@ export function getMessageTrendChartOptions(
|
|||
],
|
||||
series: [
|
||||
{
|
||||
name: '上行消息',
|
||||
name: '上行消息量',
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
areaStyle: {
|
||||
opacity: 0.3,
|
||||
color: {
|
||||
type: 'linear',
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 0,
|
||||
y2: 1,
|
||||
colorStops: [
|
||||
{ offset: 0, color: 'rgba(24, 144, 255, 0.3)' },
|
||||
{ offset: 1, color: 'rgba(24, 144, 255, 0)' },
|
||||
],
|
||||
},
|
||||
},
|
||||
emphasis: {
|
||||
focus: 'series',
|
||||
|
|
@ -55,11 +65,21 @@ export function getMessageTrendChartOptions(
|
|||
},
|
||||
},
|
||||
{
|
||||
name: '下行消息',
|
||||
name: '下行消息量',
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
areaStyle: {
|
||||
opacity: 0.3,
|
||||
color: {
|
||||
type: 'linear',
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 0,
|
||||
y2: 1,
|
||||
colorStops: [
|
||||
{ offset: 0, color: 'rgba(82, 196, 26, 0.3)' },
|
||||
{ offset: 1, color: 'rgba(82, 196, 26, 0)' },
|
||||
],
|
||||
},
|
||||
},
|
||||
emphasis: {
|
||||
focus: 'series',
|
||||
|
|
@ -84,8 +104,8 @@ export function getDeviceStateGaugeChartOptions(
|
|||
series: [
|
||||
{
|
||||
type: 'gauge',
|
||||
startAngle: 225,
|
||||
endAngle: -45,
|
||||
startAngle: 360,
|
||||
endAngle: 0,
|
||||
min: 0,
|
||||
max,
|
||||
center: ['50%', '50%'],
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import type { Dayjs } from 'dayjs';
|
|||
|
||||
import type { IotStatisticsApi } from '#/api/iot/statistics';
|
||||
|
||||
import { computed, nextTick, onMounted, reactive, ref } from 'vue';
|
||||
import { computed, nextTick, reactive, ref } from 'vue';
|
||||
|
||||
import { DICT_TYPE } from '@vben/constants';
|
||||
import { getDictOptions } from '@vben/hooks';
|
||||
|
|
@ -123,10 +123,6 @@ async function renderChartWhenReady() {
|
|||
initChart();
|
||||
}
|
||||
|
||||
/** 组件挂载时查询数据 */
|
||||
onMounted(() => {
|
||||
fetchMessageData();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@ onMounted(() => {
|
|||
placeholder="请选择产品"
|
||||
allow-clear
|
||||
class="w-full"
|
||||
option-filter-prop="label"
|
||||
show-search
|
||||
@change="handleChange"
|
||||
/>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -102,7 +102,11 @@ if (!props.isStructDataSpecs && !props.isParams) {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<Form.Item label="数据类型">
|
||||
<Form.Item
|
||||
:name="['property', 'dataType']"
|
||||
:rules="[{ required: true, message: '请选择数据类型', trigger: 'change' }]"
|
||||
label="数据类型"
|
||||
>
|
||||
<Select
|
||||
v-model:value="property.dataType"
|
||||
placeholder="请选择数据类型"
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||
label: '是否处理',
|
||||
component: 'Select',
|
||||
componentProps: {
|
||||
options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING),
|
||||
options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'),
|
||||
placeholder: '请选择是否处理',
|
||||
clearable: true,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -123,6 +123,28 @@ const [Modal, modalApi] = useVbenModal({
|
|||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
// 高级表单:先单独校验,再做经纬度成对填写的跨字段检查
|
||||
if (advancedFormApi.isMounted) {
|
||||
const { valid: advancedValid } = await advancedFormApi.validate();
|
||||
if (!advancedValid) {
|
||||
return;
|
||||
}
|
||||
const advValues = await advancedFormApi.getValues();
|
||||
const hasLongitude =
|
||||
advValues.longitude !== undefined &&
|
||||
advValues.longitude !== null &&
|
||||
advValues.longitude !== '';
|
||||
const hasLatitude =
|
||||
advValues.latitude !== undefined &&
|
||||
advValues.latitude !== null &&
|
||||
advValues.latitude !== '';
|
||||
if (hasLongitude !== hasLatitude) {
|
||||
ElMessage.warning(
|
||||
hasLongitude ? '请同时填写设备纬度' : '请同时填写设备经度',
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
modalApi.lock();
|
||||
// 合并两个表单的值(字段不冲突,可直接合并)
|
||||
const basicValues = await formApi.getValues();
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ export function getMessageTrendChartOptions(
|
|||
},
|
||||
},
|
||||
legend: {
|
||||
data: ['上行消息', '下行消息'],
|
||||
data: ['上行消息量', '下行消息量'],
|
||||
top: '5%',
|
||||
},
|
||||
grid: {
|
||||
|
|
@ -40,11 +40,21 @@ export function getMessageTrendChartOptions(
|
|||
],
|
||||
series: [
|
||||
{
|
||||
name: '上行消息',
|
||||
name: '上行消息量',
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
areaStyle: {
|
||||
opacity: 0.3,
|
||||
color: {
|
||||
type: 'linear',
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 0,
|
||||
y2: 1,
|
||||
colorStops: [
|
||||
{ offset: 0, color: 'rgba(24, 144, 255, 0.3)' },
|
||||
{ offset: 1, color: 'rgba(24, 144, 255, 0)' },
|
||||
],
|
||||
},
|
||||
},
|
||||
emphasis: {
|
||||
focus: 'series',
|
||||
|
|
@ -55,11 +65,21 @@ export function getMessageTrendChartOptions(
|
|||
},
|
||||
},
|
||||
{
|
||||
name: '下行消息',
|
||||
name: '下行消息量',
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
areaStyle: {
|
||||
opacity: 0.3,
|
||||
color: {
|
||||
type: 'linear',
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 0,
|
||||
y2: 1,
|
||||
colorStops: [
|
||||
{ offset: 0, color: 'rgba(82, 196, 26, 0.3)' },
|
||||
{ offset: 1, color: 'rgba(82, 196, 26, 0)' },
|
||||
],
|
||||
},
|
||||
},
|
||||
emphasis: {
|
||||
focus: 'series',
|
||||
|
|
@ -84,8 +104,8 @@ export function getDeviceStateGaugeChartOptions(
|
|||
series: [
|
||||
{
|
||||
type: 'gauge',
|
||||
startAngle: 225,
|
||||
endAngle: -45,
|
||||
startAngle: 360,
|
||||
endAngle: 0,
|
||||
min: 0,
|
||||
max,
|
||||
center: ['50%', '50%'],
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import type { Dayjs } from 'dayjs';
|
|||
|
||||
import type { IotStatisticsApi } from '#/api/iot/statistics';
|
||||
|
||||
import { computed, nextTick, onMounted, reactive, ref } from 'vue';
|
||||
import { computed, nextTick, reactive, ref } from 'vue';
|
||||
|
||||
import { DICT_TYPE } from '@vben/constants';
|
||||
import { getDictOptions } from '@vben/hooks';
|
||||
|
|
@ -123,10 +123,6 @@ async function renderChartWhenReady() {
|
|||
initChart();
|
||||
}
|
||||
|
||||
/** 组件挂载时查询数据 */
|
||||
onMounted(() => {
|
||||
fetchMessageData();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ onMounted(() => {
|
|||
:loading="loading"
|
||||
placeholder="请选择产品"
|
||||
clearable
|
||||
filterable
|
||||
class="w-full"
|
||||
@change="handleChange"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -109,7 +109,11 @@ if (!props.isStructDataSpecs && !props.isParams) {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<ElFormItem label="数据类型">
|
||||
<ElFormItem
|
||||
:rules="[{ required: true, message: '请选择数据类型', trigger: 'change' }]"
|
||||
label="数据类型"
|
||||
prop="property.dataType"
|
||||
>
|
||||
<ElSelect
|
||||
v-model="property.dataType"
|
||||
placeholder="请选择数据类型"
|
||||
|
|
|
|||
Loading…
Reference in New Issue