|
@@ -3,7 +3,7 @@
|
|
<a-modal
|
|
<a-modal
|
|
:get-container="() => $refs.mod"
|
|
:get-container="() => $refs.mod"
|
|
:open="props.open"
|
|
:open="props.open"
|
|
- :title="title"
|
|
|
|
|
|
+ :title="modelTitle"
|
|
:mask-closable="false"
|
|
:mask-closable="false"
|
|
width="600px"
|
|
width="600px"
|
|
@cancel="cancel"
|
|
@cancel="cancel"
|
|
@@ -29,17 +29,110 @@
|
|
/>
|
|
/>
|
|
</a-form-item>
|
|
</a-form-item>
|
|
|
|
|
|
- <a-form-item label="检测区域" name="region"> 检测区域选择组件 </a-form-item>
|
|
|
|
|
|
+ <a-form-item
|
|
|
|
+ label="计划备注"
|
|
|
|
+ name="planName"
|
|
|
|
+ :rules="[{ required: true, message: '请输入计划备注' }]"
|
|
|
|
+ >
|
|
|
|
+ <a-input
|
|
|
|
+ v-model:value.trim="formState.remark"
|
|
|
|
+ placeholder="请输入备注"
|
|
|
|
+ :maxlength="200"
|
|
|
|
+ show-count
|
|
|
|
+ allow-clear
|
|
|
|
+ />
|
|
|
|
+ </a-form-item>
|
|
|
|
+
|
|
|
|
+ <a-form-item
|
|
|
|
+ label="触发阈值"
|
|
|
|
+ name="thresholdTime"
|
|
|
|
+ :rules="[{ required: true, message: '请输入触发阈值' }]"
|
|
|
|
+ >
|
|
|
|
+ <a-input-number
|
|
|
|
+ v-model:value.trim="formState.thresholdTime"
|
|
|
|
+ placeholder="请输入(默认300,需要大于0)"
|
|
|
|
+ min="0"
|
|
|
|
+ show-count
|
|
|
|
+ allow-clear
|
|
|
|
+ style="width: 100%"
|
|
|
|
+ />
|
|
|
|
+ </a-form-item>
|
|
|
|
+
|
|
|
|
+ <a-form-item
|
|
|
|
+ label="归并时间"
|
|
|
|
+ name="mergeTime"
|
|
|
|
+ :rules="[{ required: true, message: '请输入归并时间' }]"
|
|
|
|
+ >
|
|
|
|
+ <a-input-number
|
|
|
|
+ v-model:value.trim="formState.mergeTime"
|
|
|
|
+ placeholder="请输入(默认30,需要大于0)"
|
|
|
|
+ min="0"
|
|
|
|
+ show-count
|
|
|
|
+ allow-clear
|
|
|
|
+ style="width: 100%"
|
|
|
|
+ />
|
|
|
|
+ </a-form-item>
|
|
|
|
|
|
<a-form-item
|
|
<a-form-item
|
|
label="事件类型"
|
|
label="事件类型"
|
|
name="eventType"
|
|
name="eventType"
|
|
:rules="[{ required: true, message: '请选择事件类型' }]"
|
|
:rules="[{ required: true, message: '请选择事件类型' }]"
|
|
>
|
|
>
|
|
- <a-select v-model:value="formState.eventType" placeholder="请选择事件类型">
|
|
|
|
- <a-select-option value="1">跌倒</a-select-option>
|
|
|
|
- <a-select-option value="2">滞留</a-select-option>
|
|
|
|
- </a-select>
|
|
|
|
|
|
+ <a-select
|
|
|
|
+ v-model:value="formState.eventType"
|
|
|
|
+ :options="eventTypeList"
|
|
|
|
+ placeholder="请选择事件类型"
|
|
|
|
+ />
|
|
|
|
+
|
|
|
|
+ <a-form-item-rest v-if="formState.eventType && ![1, 2, 3].includes(formState.eventType)">
|
|
|
|
+ <div class="eventTypeBox">
|
|
|
|
+ <div v-if="[4, 5, 6, 7, 8].includes(formState.eventType)" class="eventTypeBox-item">
|
|
|
|
+ <span class="eventTypeBox-item-label">统计时间:</span>
|
|
|
|
+ <a-form-item
|
|
|
|
+ name="statisticsTime"
|
|
|
|
+ :rules="[{ required: true, message: '请选择统计时间' }]"
|
|
|
|
+ >
|
|
|
|
+ <a-time-range-picker
|
|
|
|
+ v-model:value="formState.statisticsTime"
|
|
|
|
+ valueFormat="HH:mm"
|
|
|
|
+ format="HH:mm"
|
|
|
|
+ style="width: 100%"
|
|
|
|
+ />
|
|
|
|
+ </a-form-item>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <div v-if="[6, 7].includes(formState.eventType)" class="eventTypeBox-item">
|
|
|
|
+ <span class="eventTypeBox-item-label">异常阈值:</span>
|
|
|
|
+ <a-form-item name="count" :rules="[{ required: true, message: '请输入异常阈值' }]">
|
|
|
|
+ <a-input-number
|
|
|
|
+ v-model:value.trim="formState.count"
|
|
|
|
+ placeholder="请输入(默认3,需要大于0)"
|
|
|
|
+ min="0"
|
|
|
|
+ show-count
|
|
|
|
+ allow-clear
|
|
|
|
+ style="width: 100%"
|
|
|
|
+ />
|
|
|
|
+ </a-form-item>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <div v-if="formState.eventType === 9" class="eventTypeBox-item">
|
|
|
|
+ <span class="eventTypeBox-item-labelend">异常消失时间阈值:</span>
|
|
|
|
+ <a-form-item
|
|
|
|
+ name="timeThreshold"
|
|
|
|
+ :rules="[{ required: true, message: '请输入异常消失时间阈值' }]"
|
|
|
|
+ >
|
|
|
|
+ <a-input-number
|
|
|
|
+ v-model:value.trim="formState.timeThreshold"
|
|
|
|
+ placeholder="请输入(默认300,需要大于0)"
|
|
|
|
+ min="0"
|
|
|
|
+ show-count
|
|
|
|
+ allow-clear
|
|
|
|
+ style="width: 100%"
|
|
|
|
+ />
|
|
|
|
+ </a-form-item>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </a-form-item-rest>
|
|
</a-form-item>
|
|
</a-form-item>
|
|
|
|
|
|
<a-form-item
|
|
<a-form-item
|
|
@@ -55,30 +148,6 @@
|
|
/>
|
|
/>
|
|
</a-form-item>
|
|
</a-form-item>
|
|
|
|
|
|
- <a-form-item label="生效方式" name="firmwareVersion">
|
|
|
|
- <a-radio-group
|
|
|
|
- v-model:value="formState.effectType"
|
|
|
|
- name="radioGroup"
|
|
|
|
- @change="effectTypeChange"
|
|
|
|
- >
|
|
|
|
- <a-radio value="week">按周</a-radio>
|
|
|
|
- <a-radio value="month">按月</a-radio>
|
|
|
|
- </a-radio-group>
|
|
|
|
- </a-form-item>
|
|
|
|
-
|
|
|
|
- <a-form-item label="生效范围" name="firmwareVersion">
|
|
|
|
- <a-form-item-rest>
|
|
|
|
- <a-checkbox
|
|
|
|
- v-model:checked="checkState.checkAll"
|
|
|
|
- :indeterminate="checkState.indeterminate"
|
|
|
|
- @change="onCheckAllChange"
|
|
|
|
- >
|
|
|
|
- 全选
|
|
|
|
- </a-checkbox>
|
|
|
|
- <a-checkbox-group v-model:value="formState.effectTimeRanges" :options="plainOptions" />
|
|
|
|
- </a-form-item-rest>
|
|
|
|
- </a-form-item>
|
|
|
|
-
|
|
|
|
<a-form-item label="生效时段">
|
|
<a-form-item label="生效时段">
|
|
<div style="display: flex; align-items: center; gap: 8px">
|
|
<div style="display: flex; align-items: center; gap: 8px">
|
|
<a-time-range-picker
|
|
<a-time-range-picker
|
|
@@ -89,7 +158,9 @@
|
|
<a-button size="small" type="link" @click="addEffectTime">添加</a-button>
|
|
<a-button size="small" type="link" @click="addEffectTime">添加</a-button>
|
|
</div>
|
|
</div>
|
|
<div style="margin-top: 12px">
|
|
<div style="margin-top: 12px">
|
|
- <span v-if="!formState.effectTimeFrames.length" style="color: #aaa; font-size: 14px"
|
|
|
|
|
|
+ <span
|
|
|
|
+ v-if="formState.effectTimeFrames && !formState.effectTimeFrames.length"
|
|
|
|
+ style="color: #aaa; font-size: 14px"
|
|
>⚠️暂无生效时段</span
|
|
>⚠️暂无生效时段</span
|
|
>
|
|
>
|
|
<a-space wrap v-else>
|
|
<a-space wrap v-else>
|
|
@@ -104,8 +175,34 @@
|
|
</a-space>
|
|
</a-space>
|
|
</div>
|
|
</div>
|
|
</a-form-item>
|
|
</a-form-item>
|
|
|
|
+
|
|
|
|
+ <a-form-item label="生效方式">
|
|
|
|
+ <a-form-item-rest>
|
|
|
|
+ <a-radio-group
|
|
|
|
+ v-model:value="formState.effectType"
|
|
|
|
+ name="radioGroup"
|
|
|
|
+ @change="effectTypeChange"
|
|
|
|
+ >
|
|
|
|
+ <a-radio value="week">按周</a-radio>
|
|
|
|
+ <a-radio value="month">按月</a-radio>
|
|
|
|
+ </a-radio-group>
|
|
|
|
+ <a-checkbox
|
|
|
|
+ v-model:checked="checkState.checkAll"
|
|
|
|
+ :indeterminate="checkState.indeterminate"
|
|
|
|
+ @change="onCheckAllChange"
|
|
|
|
+ >
|
|
|
|
+ 全选
|
|
|
|
+ </a-checkbox>
|
|
|
|
+ <a-checkbox-group v-model:value="formState.effectTimeRanges" :options="plainOptions" />
|
|
|
|
+ </a-form-item-rest>
|
|
|
|
+ </a-form-item>
|
|
|
|
+
|
|
|
|
+ <a-form-item label="检测区域" name="region">
|
|
|
|
+ 检测区域选择组件 {{ formState.region }}
|
|
|
|
+ </a-form-item>
|
|
|
|
+
|
|
<a-form-item label="是否启用">
|
|
<a-form-item label="是否启用">
|
|
- <a-switch v-model:checked="formState.isEnable" />
|
|
|
|
|
|
+ <a-switch v-model:checked="formState.enable" />
|
|
</a-form-item>
|
|
</a-form-item>
|
|
</a-form>
|
|
</a-form>
|
|
|
|
|
|
@@ -120,10 +217,9 @@
|
|
</template>
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
<script setup lang="ts">
|
|
-import { ref, reactive, watch } from 'vue'
|
|
|
|
|
|
+import { ref, reactive, watch, computed } from 'vue'
|
|
import { message, type FormInstance } from 'ant-design-vue'
|
|
import { message, type FormInstance } from 'ant-design-vue'
|
|
import * as alarmApi from '@/api/alarm'
|
|
import * as alarmApi from '@/api/alarm'
|
|
-import type { EventVal, EventValParam } from '@/api/alarm/types'
|
|
|
|
|
|
|
|
defineOptions({
|
|
defineOptions({
|
|
name: 'AlarmPlanModal',
|
|
name: 'AlarmPlanModal',
|
|
@@ -131,9 +227,43 @@ defineOptions({
|
|
|
|
|
|
const formRef = ref<FormInstance>()
|
|
const formRef = ref<FormInstance>()
|
|
|
|
|
|
|
|
+type AlarmPlan = {
|
|
|
|
+ id: number
|
|
|
|
+ uuid: ID
|
|
|
|
+ name: string
|
|
|
|
+ clientId: string
|
|
|
|
+ enable: SwitchType
|
|
|
|
+ region: string
|
|
|
|
+ eventVal: number
|
|
|
|
+ alarmTimePlanId: ID
|
|
|
|
+ thresholdTime: ID
|
|
|
|
+ mergeTime: ID
|
|
|
|
+ param: string
|
|
|
|
+ createTime: string
|
|
|
|
+ updateTime: string
|
|
|
|
+ remark: string | null
|
|
|
|
+ alarmTimePlan: {
|
|
|
|
+ createId: ID
|
|
|
|
+ updateId: ID
|
|
|
|
+ createTime: ID
|
|
|
|
+ updateTime: ID
|
|
|
|
+ isDeleted: SwitchType | null
|
|
|
|
+ remark: ID
|
|
|
|
+ id: ID
|
|
|
|
+ startDate: string
|
|
|
|
+ stopDate: string
|
|
|
|
+ timeRange: string
|
|
|
|
+ monthDays: string
|
|
|
|
+ weekdays: string
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
type Props = {
|
|
type Props = {
|
|
open: boolean
|
|
open: boolean
|
|
title?: string
|
|
title?: string
|
|
|
|
+ clientId: string // 设备ID
|
|
|
|
+ alarmPlanId?: number | null // 告警计划ID 编辑时传入
|
|
|
|
+ data?: AlarmPlan // 编辑数据
|
|
}
|
|
}
|
|
const emit = defineEmits<{
|
|
const emit = defineEmits<{
|
|
(e: 'update:open', value: boolean): void
|
|
(e: 'update:open', value: boolean): void
|
|
@@ -143,68 +273,57 @@ const emit = defineEmits<{
|
|
const props = withDefaults(defineProps<Props>(), {
|
|
const props = withDefaults(defineProps<Props>(), {
|
|
open: false,
|
|
open: false,
|
|
title: '告警计划',
|
|
title: '告警计划',
|
|
|
|
+ clientId: '',
|
|
|
|
+ alarmPlanId: null,
|
|
|
|
+ data: undefined,
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+const modelTitle = computed(() => {
|
|
|
|
+ return props.alarmPlanId ? '编辑告警计划' : '新增告警计划'
|
|
})
|
|
})
|
|
|
|
|
|
const weekOptions = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
|
|
const weekOptions = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
|
|
-const mouthOptions = [
|
|
|
|
- '1',
|
|
|
|
- '2',
|
|
|
|
- '3',
|
|
|
|
- '4',
|
|
|
|
- '5',
|
|
|
|
- '6',
|
|
|
|
- '7',
|
|
|
|
- '8',
|
|
|
|
- '9',
|
|
|
|
- '10',
|
|
|
|
- '11',
|
|
|
|
- '12',
|
|
|
|
- '13',
|
|
|
|
- '14',
|
|
|
|
- '15',
|
|
|
|
- '16',
|
|
|
|
- '17',
|
|
|
|
- '18',
|
|
|
|
- '19',
|
|
|
|
- '20',
|
|
|
|
- '21',
|
|
|
|
- '22',
|
|
|
|
- '23',
|
|
|
|
- '24',
|
|
|
|
- '25',
|
|
|
|
- '26',
|
|
|
|
- '27',
|
|
|
|
- '28',
|
|
|
|
- '29',
|
|
|
|
- '30',
|
|
|
|
- '31',
|
|
|
|
|
|
+const monthOptions = [
|
|
|
|
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
|
|
|
|
+ 28, 29, 30, 31,
|
|
]
|
|
]
|
|
|
|
|
|
type FormState = {
|
|
type FormState = {
|
|
planName: string // 计划名称
|
|
planName: string // 计划名称
|
|
- region: string[] // 检测区域 [left, top, width, height]
|
|
|
|
- eventType: EventVal | null // 事件类型
|
|
|
|
|
|
+ region: number[] // 检测区域 [left, top, width, height]
|
|
|
|
+ eventType: number | null // 事件类型
|
|
|
|
+ thresholdTime: number | null // 触发阈值
|
|
|
|
+ mergeTime: number | null // 归并时间
|
|
planTime: string[] // 计划时间
|
|
planTime: string[] // 计划时间
|
|
effectType: 'week' | 'month' // 生效方式 周week、月month
|
|
effectType: 'week' | 'month' // 生效方式 周week、月month
|
|
- effectTimeRanges: string[] // 生效范围 周 1-7、月 1-31
|
|
|
|
|
|
+ effectTimeRanges: (number | string)[] // 生效范围 周 1-7、月 1-31
|
|
effectTimeFrame: string[] // 生效时段 单条 00:00:00 - 23:59:59
|
|
effectTimeFrame: string[] // 生效时段 单条 00:00:00 - 23:59:59
|
|
effectTimeFrames: { startTime: string; endTime: string }[] // 生效时段 多条
|
|
effectTimeFrames: { startTime: string; endTime: string }[] // 生效时段 多条
|
|
- isEnable: boolean // 是否启用
|
|
|
|
|
|
+ enable: boolean // 是否启用
|
|
|
|
+ statisticsTime: string[] // 统计时间
|
|
|
|
+ count?: number | null // 异常阈值
|
|
|
|
+ timeThreshold?: number | null // 异常消失时间阈值(单位:秒)
|
|
|
|
+ remark?: string // 备注
|
|
}
|
|
}
|
|
|
|
|
|
const formState = reactive<FormState>({
|
|
const formState = reactive<FormState>({
|
|
planName: '',
|
|
planName: '',
|
|
- region: [],
|
|
|
|
|
|
+ region: [-200, 200, 400, 400],
|
|
eventType: null,
|
|
eventType: null,
|
|
|
|
+ thresholdTime: 300,
|
|
|
|
+ mergeTime: 30,
|
|
planTime: [],
|
|
planTime: [],
|
|
effectType: 'week',
|
|
effectType: 'week',
|
|
effectTimeRanges: weekOptions,
|
|
effectTimeRanges: weekOptions,
|
|
effectTimeFrame: [],
|
|
effectTimeFrame: [],
|
|
effectTimeFrames: [],
|
|
effectTimeFrames: [],
|
|
- isEnable: true,
|
|
|
|
|
|
+ enable: true,
|
|
|
|
+ statisticsTime: [],
|
|
|
|
+ count: 3,
|
|
|
|
+ timeThreshold: 300,
|
|
})
|
|
})
|
|
|
|
|
|
-const plainOptions = ref<string[]>(weekOptions)
|
|
|
|
|
|
+const plainOptions = ref<(number | string)[]>(weekOptions)
|
|
const checkState = reactive({
|
|
const checkState = reactive({
|
|
indeterminate: true,
|
|
indeterminate: true,
|
|
checkAll: false,
|
|
checkAll: false,
|
|
@@ -217,6 +336,27 @@ const onCheckAllChange = (e: Event) => {
|
|
formState.effectTimeRanges = checked ? [...plainOptions.value] : []
|
|
formState.effectTimeRanges = checked ? [...plainOptions.value] : []
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// 星期映射数字
|
|
|
|
+const weekToNumMap: Record<string, number> = {
|
|
|
|
+ 周一: 1,
|
|
|
|
+ 周二: 2,
|
|
|
|
+ 周三: 3,
|
|
|
|
+ 周四: 4,
|
|
|
|
+ 周五: 5,
|
|
|
|
+ 周六: 6,
|
|
|
|
+ 周日: 7,
|
|
|
|
+}
|
|
|
|
+// 数字映射星期
|
|
|
|
+const numToWeekMap: Record<number, string> = {
|
|
|
|
+ 1: '周一',
|
|
|
|
+ 2: '周二',
|
|
|
|
+ 3: '周三',
|
|
|
|
+ 4: '周四',
|
|
|
|
+ 5: '周五',
|
|
|
|
+ 6: '周六',
|
|
|
|
+ 7: '周日',
|
|
|
|
+}
|
|
|
|
+
|
|
watch(
|
|
watch(
|
|
() => formState.effectTimeRanges,
|
|
() => formState.effectTimeRanges,
|
|
(val) => {
|
|
(val) => {
|
|
@@ -228,6 +368,102 @@ watch(
|
|
}
|
|
}
|
|
)
|
|
)
|
|
|
|
|
|
|
|
+const safeParse = <T,>(str: string | undefined | null, fallback: T): T => {
|
|
|
|
+ try {
|
|
|
|
+ return JSON.parse(str ?? JSON.stringify(fallback)) as T
|
|
|
|
+ } catch {
|
|
|
|
+ return fallback
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+interface ParamType {
|
|
|
|
+ start_time?: string
|
|
|
|
+ end_time?: string
|
|
|
|
+ count?: number
|
|
|
|
+ time_threshold?: number
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+interface TimeFrame {
|
|
|
|
+ start_time?: string
|
|
|
|
+ end_time?: string
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+interface AlarmTimePlan {
|
|
|
|
+ startDate?: string
|
|
|
|
+ stopDate?: string
|
|
|
|
+ weekdays?: string
|
|
|
|
+ monthDays?: string
|
|
|
|
+ timeRange?: string
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+interface SourceData {
|
|
|
|
+ name?: string
|
|
|
|
+ remark?: string
|
|
|
|
+ thresholdTime?: number
|
|
|
|
+ mergeTime?: number
|
|
|
|
+ eventVal?: number | null
|
|
|
|
+ param?: string
|
|
|
|
+ alarmTimePlan?: AlarmTimePlan
|
|
|
|
+ region?: string
|
|
|
|
+ enable?: number
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const echoFormState = (val: SourceData) => {
|
|
|
|
+ const paramObj = safeParse<ParamType>(val.param, {})
|
|
|
|
+ const weekdays = safeParse<string[]>(val.alarmTimePlan?.weekdays, [])
|
|
|
|
+ const monthDays = safeParse<string[]>(val.alarmTimePlan?.monthDays, [])
|
|
|
|
+ const timeFrames = safeParse<TimeFrame[]>(val.alarmTimePlan?.timeRange, [])
|
|
|
|
+ plainOptions.value = weekdays.length === 0 ? monthOptions : weekOptions
|
|
|
|
+
|
|
|
|
+ return {
|
|
|
|
+ planName: val.name ?? '',
|
|
|
|
+ remark: val.remark ?? '',
|
|
|
|
+ thresholdTime: typeof val.thresholdTime === 'number' ? val.thresholdTime : null,
|
|
|
|
+ mergeTime: typeof val.mergeTime === 'number' ? val.mergeTime : null,
|
|
|
|
+ eventType: val.eventVal ?? null,
|
|
|
|
+ statisticsTime: [paramObj.start_time ?? null, paramObj.end_time ?? null] as string[],
|
|
|
|
+ count: paramObj.count ?? null,
|
|
|
|
+ timeThreshold: paramObj.time_threshold ?? null,
|
|
|
|
+ planTime: [val.alarmTimePlan?.startDate ?? '', val.alarmTimePlan?.stopDate ?? ''],
|
|
|
|
+ effectType: (weekdays.length === 0 ? 'month' : 'week') as 'week' | 'month',
|
|
|
|
+ effectTimeRanges:
|
|
|
|
+ weekdays.length === 0
|
|
|
|
+ ? monthDays
|
|
|
|
+ : weekdays.map((item: string) => numToWeekMap[Number(item)]),
|
|
|
|
+ effectTimeFrames: Array.isArray(timeFrames)
|
|
|
|
+ ? timeFrames.map((item) => ({
|
|
|
|
+ startTime: item?.start_time ?? '',
|
|
|
|
+ endTime: item?.end_time ?? '',
|
|
|
|
+ }))
|
|
|
|
+ : [],
|
|
|
|
+ region: JSON.parse(val.region ?? '[]'),
|
|
|
|
+ enable: val?.enable === 1,
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+watch(
|
|
|
|
+ () => props.open,
|
|
|
|
+ (value) => {
|
|
|
|
+ const val = props.data as SourceData
|
|
|
|
+ console.log('🌸🌸 监听data用于编辑回显数据 🌸🌸', value, val)
|
|
|
|
+ if (value && val) {
|
|
|
|
+ formState.planName = echoFormState(val).planName
|
|
|
|
+ formState.remark = echoFormState(val).remark
|
|
|
|
+ formState.thresholdTime = echoFormState(val).thresholdTime
|
|
|
|
+ formState.mergeTime = echoFormState(val).mergeTime
|
|
|
|
+ formState.eventType = echoFormState(val).eventType
|
|
|
|
+ formState.statisticsTime = echoFormState(val).statisticsTime
|
|
|
|
+ formState.count = echoFormState(val).count
|
|
|
|
+ formState.timeThreshold = echoFormState(val).timeThreshold
|
|
|
|
+ formState.planTime = echoFormState(val).planTime
|
|
|
|
+ formState.effectType = echoFormState(val).effectType
|
|
|
|
+ formState.effectTimeRanges = echoFormState(val).effectTimeRanges
|
|
|
|
+ formState.effectTimeFrames = echoFormState(val).effectTimeFrames
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ { immediate: true }
|
|
|
|
+)
|
|
|
|
+
|
|
// 生效方式变化 周week、月month
|
|
// 生效方式变化 周week、月month
|
|
const effectTypeChange = (e: Event) => {
|
|
const effectTypeChange = (e: Event) => {
|
|
const value = (e.target as HTMLInputElement).value
|
|
const value = (e.target as HTMLInputElement).value
|
|
@@ -236,9 +472,9 @@ const effectTypeChange = (e: Event) => {
|
|
if (value === 'week') {
|
|
if (value === 'week') {
|
|
plainOptions.value = weekOptions
|
|
plainOptions.value = weekOptions
|
|
formState.effectTimeRanges = weekOptions
|
|
formState.effectTimeRanges = weekOptions
|
|
- } else if (value === 'mouth') {
|
|
|
|
- plainOptions.value = mouthOptions
|
|
|
|
- formState.effectTimeRanges = mouthOptions
|
|
|
|
|
|
+ } else if (value === 'month') {
|
|
|
|
+ plainOptions.value = monthOptions
|
|
|
|
+ formState.effectTimeRanges = monthOptions
|
|
}
|
|
}
|
|
/* 置全选按钮的状态 */
|
|
/* 置全选按钮的状态 */
|
|
checkState.indeterminate =
|
|
checkState.indeterminate =
|
|
@@ -266,21 +502,48 @@ const deleteEffectTimeItem = (e: Event, index: number) => {
|
|
formState.effectTimeFrames.splice(index, 1)
|
|
formState.effectTimeFrames.splice(index, 1)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// 关闭弹窗
|
|
const cancel = () => {
|
|
const cancel = () => {
|
|
formRef?.value?.resetFields()
|
|
formRef?.value?.resetFields()
|
|
emit('update:open', false)
|
|
emit('update:open', false)
|
|
|
|
+ // 重置表单
|
|
|
|
+ formState.planName = ''
|
|
|
|
+ formState.region = []
|
|
|
|
+ formState.eventType = null
|
|
|
|
+ formState.thresholdTime = 300
|
|
|
|
+ formState.mergeTime = 30
|
|
|
|
+ formState.planTime = []
|
|
|
|
+ formState.effectType = 'week'
|
|
|
|
+ plainOptions.value = weekOptions
|
|
|
|
+ formState.effectTimeRanges = weekOptions
|
|
|
|
+ formState.effectTimeFrame = []
|
|
|
|
+ formState.effectTimeFrames = []
|
|
|
|
+ formState.enable = true
|
|
|
|
+ formState.statisticsTime = []
|
|
|
|
+ formState.count = 3
|
|
|
|
+ formState.timeThreshold = 300
|
|
|
|
+ formState.remark = ''
|
|
}
|
|
}
|
|
|
|
|
|
-// 星期映射数字
|
|
|
|
-const weekdaysReverseMap: Record<string, number> = {
|
|
|
|
- 周一: 1,
|
|
|
|
- 周二: 2,
|
|
|
|
- 周三: 3,
|
|
|
|
- 周四: 4,
|
|
|
|
- 周五: 5,
|
|
|
|
- 周六: 6,
|
|
|
|
- 周日: 7,
|
|
|
|
|
|
+const eventTypeList = ref<{ label: string; value: string }[]>([])
|
|
|
|
+// 获取事件类型下拉列表
|
|
|
|
+const fetchEventTypeList = async () => {
|
|
|
|
+ try {
|
|
|
|
+ const res = await alarmApi.getAlarmEventTypeList()
|
|
|
|
+ console.log('获取事件类型下拉列表成功✅', res)
|
|
|
|
+ const data = res.data
|
|
|
|
+ eventTypeList.value =
|
|
|
|
+ (Array.isArray(data) &&
|
|
|
|
+ data.map((item) => ({
|
|
|
|
+ label: item.eventDesc,
|
|
|
|
+ value: item.eventVal,
|
|
|
|
+ }))) ||
|
|
|
|
+ []
|
|
|
|
+ } catch (err) {
|
|
|
|
+ console.log('获取事件类型下拉列表失败❌', err)
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
+fetchEventTypeList()
|
|
|
|
|
|
const submitLoading = ref(false)
|
|
const submitLoading = ref(false)
|
|
// 确定
|
|
// 确定
|
|
@@ -289,55 +552,79 @@ const submit = () => {
|
|
?.validate()
|
|
?.validate()
|
|
.then(() => {
|
|
.then(() => {
|
|
console.log('校验通过', formState)
|
|
console.log('校验通过', formState)
|
|
- let paramData: EventValParam = {}
|
|
|
|
- if (
|
|
|
|
- ['stay_detection', 'retention_detection', 'toileting_detection'].includes(
|
|
|
|
- formState.eventType as string
|
|
|
|
- )
|
|
|
|
- ) {
|
|
|
|
- console.log('参数传 {}')
|
|
|
|
|
|
+ let paramData = {}
|
|
|
|
+ if ([1, 2, 3].includes(formState.eventType as number)) {
|
|
paramData = {}
|
|
paramData = {}
|
|
- } else if (
|
|
|
|
- ['toileting_frequency', 'night_toileting_frequency', 'bathroom_stay_frequency'].includes(
|
|
|
|
- formState.eventType as string
|
|
|
|
- )
|
|
|
|
- ) {
|
|
|
|
- console.log('参数传 { "start_time": "22:00", "end_time": "6:00" }')
|
|
|
|
- paramData = { start_time: '22:00', end_time: '6:00' }
|
|
|
|
- } else if (
|
|
|
|
- ['toilet_frequency_abnormal', 'night_toileting_frequency_abnormal'].includes(
|
|
|
|
- formState.eventType as string
|
|
|
|
- )
|
|
|
|
- ) {
|
|
|
|
- console.log('参数传 { "start_time": "22:00", "end_time": "6:00", "count": 3 }')
|
|
|
|
- paramData = { start_time: '22:00', end_time: '6:00', count: 3 }
|
|
|
|
- } else if (['target_absence'].includes(formState.eventType as string)) {
|
|
|
|
- console.log('参数传 { "time_threshold": 300 }')
|
|
|
|
- paramData = { time_threshold: 300 }
|
|
|
|
|
|
+ console.log('🔥paramData🔥', paramData)
|
|
|
|
+ } else if ([4, 5, 8].includes(formState.eventType as number)) {
|
|
|
|
+ paramData = {
|
|
|
|
+ start_time: formState.statisticsTime[0],
|
|
|
|
+ end_time: formState.statisticsTime[1],
|
|
|
|
+ }
|
|
|
|
+ console.log('🔥paramData🔥', paramData)
|
|
|
|
+ } else if ([6, 7].includes(formState.eventType as number)) {
|
|
|
|
+ paramData = {
|
|
|
|
+ start_time: formState.statisticsTime[0],
|
|
|
|
+ end_time: formState.statisticsTime[1],
|
|
|
|
+ count: isNaN(Number(formState.count)) ? 0 : Number(formState.count),
|
|
|
|
+ }
|
|
|
|
+ console.log('🔥paramData🔥', paramData)
|
|
|
|
+ } else if ([9].includes(formState.eventType as number)) {
|
|
|
|
+ paramData = {
|
|
|
|
+ time_threshold: isNaN(Number(formState.timeThreshold))
|
|
|
|
+ ? 0
|
|
|
|
+ : Number(formState.timeThreshold),
|
|
|
|
+ }
|
|
|
|
+ console.log('🔥paramData🔥', paramData)
|
|
}
|
|
}
|
|
|
|
|
|
const params = {
|
|
const params = {
|
|
- clientId: '', // 设备ID
|
|
|
|
|
|
+ alarmPlanId: props.alarmPlanId || undefined, // 告警计划ID 编辑时传入
|
|
|
|
+ clientId: props.clientId, // 设备ID
|
|
name: formState.planName, // 计划名称
|
|
name: formState.planName, // 计划名称
|
|
- region: formState.region, // 检测区域 [left, top, width, height]
|
|
|
|
- eventVal: formState.eventType, // 事件类型 与 param 有联动关系
|
|
|
|
- param: paramData, // 事件参数 与 eventVal 有联动关系
|
|
|
|
- enable: Number(formState.isEnable) as 0 | 1, // 是否启用 0否 1是
|
|
|
|
|
|
+ remark: formState.remark || '', // 备注
|
|
|
|
+ thresholdTime: Number(formState.thresholdTime) || 300, // 触发阈值
|
|
|
|
+ mergeTime: Number(formState.mergeTime) || 30, // 归并时间
|
|
|
|
+ eventVal: formState.eventType as number, // 事件类型 与 param 有联动关系
|
|
|
|
+ param: JSON.stringify(paramData), // 事件参数 与 eventVal 有联动关系
|
|
|
|
+ region: JSON.stringify(formState.region), // 检测区域
|
|
|
|
+ enable: Number(formState.enable) as 0 | 1, // 是否启用 0否 1是
|
|
|
|
+
|
|
|
|
+ // 生效方式
|
|
alarmTimePlan: {
|
|
alarmTimePlan: {
|
|
startDate: formState.planTime[0], // 计划开始时间
|
|
startDate: formState.planTime[0], // 计划开始时间
|
|
stopDate: formState.planTime[1], // 计划结束时间
|
|
stopDate: formState.planTime[1], // 计划结束时间
|
|
- monthDays: formState.effectType === 'month' ? formState.effectTimeRanges : [], // 按月生效范围 1-31
|
|
|
|
- weekdays:
|
|
|
|
|
|
+ // 生效时段
|
|
|
|
+ timeRange: JSON.stringify(
|
|
|
|
+ formState.effectTimeFrames.map((item) => ({
|
|
|
|
+ start_time: item.startTime,
|
|
|
|
+ end_time: item.endTime,
|
|
|
|
+ }))
|
|
|
|
+ ),
|
|
|
|
+ monthDays: JSON.stringify(
|
|
|
|
+ formState.effectType === 'month' ? formState.effectTimeRanges : []
|
|
|
|
+ ),
|
|
|
|
+ weekdays: JSON.stringify(
|
|
formState.effectType === 'week'
|
|
formState.effectType === 'week'
|
|
- ? formState.effectTimeRanges.map((item: string) => String(weekdaysReverseMap[item]))
|
|
|
|
- : [], // 按周生效范围 1-7
|
|
|
|
- timeRange: formState.effectTimeFrames.map((item) => ({
|
|
|
|
- start_time: item.startTime, // 生效开始时间
|
|
|
|
- end_time: item.endTime, // 生效结束时间
|
|
|
|
- })),
|
|
|
|
|
|
+ ? formState.effectTimeRanges.map((item) => weekToNumMap[item])
|
|
|
|
+ : []
|
|
|
|
+ ),
|
|
},
|
|
},
|
|
}
|
|
}
|
|
console.log('🚀🚀🚀提交参数', params)
|
|
console.log('🚀🚀🚀提交参数', params)
|
|
|
|
+ if (formState.effectTimeFrames.length === 0) {
|
|
|
|
+ message.warn('请添加生效时段')
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ if (formState.effectTimeRanges.length === 0) {
|
|
|
|
+ message.warn('请选择生效方式的范围')
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ // if (formState.region.length !== 4) {
|
|
|
|
+ // message.warn('请选择检测区域')
|
|
|
|
+ // return
|
|
|
|
+ // }
|
|
|
|
+
|
|
submitLoading.value = true
|
|
submitLoading.value = true
|
|
alarmApi
|
|
alarmApi
|
|
.saveAlarmPlan(params)
|
|
.saveAlarmPlan(params)
|
|
@@ -377,4 +664,34 @@ const submit = () => {
|
|
:deep(.ant-tag) {
|
|
:deep(.ant-tag) {
|
|
margin-inline-end: 0 !important;
|
|
margin-inline-end: 0 !important;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+.eventTypeBox {
|
|
|
|
+ margin-top: 12px;
|
|
|
|
+ color: #555;
|
|
|
|
+ font-size: 14px;
|
|
|
|
+ padding: 20px 12px;
|
|
|
|
+ background: #fafafa;
|
|
|
|
+ border-radius: 8px;
|
|
|
|
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);
|
|
|
|
+ &-item {
|
|
|
|
+ margin-bottom: 12px;
|
|
|
|
+ display: flex;
|
|
|
|
+ align-items: center;
|
|
|
|
+ gap: 8px;
|
|
|
|
+
|
|
|
|
+ &-label {
|
|
|
|
+ width: 100px;
|
|
|
|
+ }
|
|
|
|
+ &-labelend {
|
|
|
|
+ width: 140px;
|
|
|
|
+ }
|
|
|
|
+ &:last-child {
|
|
|
|
+ margin-bottom: 0;
|
|
|
|
+ }
|
|
|
|
+ :deep(.ant-form-item) {
|
|
|
|
+ flex: 1;
|
|
|
|
+ margin-bottom: 0;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
</style>
|
|
</style>
|