|
@@ -0,0 +1,323 @@
|
|
|
|
+<template>
|
|
|
|
+ <div ref="mod">
|
|
|
|
+ <a-modal
|
|
|
|
+ :get-container="() => $refs.mod"
|
|
|
|
+ :open="props.open"
|
|
|
|
+ :title="title"
|
|
|
|
+ :mask-closable="false"
|
|
|
|
+ width="600px"
|
|
|
|
+ @cancel="cancel"
|
|
|
|
+ :footer="null"
|
|
|
|
+ >
|
|
|
|
+ <a-form
|
|
|
|
+ ref="formRef"
|
|
|
|
+ :model="formState"
|
|
|
|
+ :label-col="{ style: { width: '80px' } }"
|
|
|
|
+ hideRequiredMark
|
|
|
|
+ >
|
|
|
|
+ <a-form-item
|
|
|
|
+ label="计划名称"
|
|
|
|
+ name="planName"
|
|
|
|
+ :rules="[{ required: true, message: '请输入计划名称' }]"
|
|
|
|
+ >
|
|
|
|
+ <a-input
|
|
|
|
+ v-model:value.trim="formState.planName"
|
|
|
|
+ placeholder="请输入计划名称"
|
|
|
|
+ :maxlength="20"
|
|
|
|
+ show-count
|
|
|
|
+ allow-clear
|
|
|
|
+ />
|
|
|
|
+ </a-form-item>
|
|
|
|
+
|
|
|
|
+ <a-form-item label="检测区域" name="region"> 检测区域选择组件 </a-form-item>
|
|
|
|
+
|
|
|
|
+ <a-form-item
|
|
|
|
+ label="事件类型"
|
|
|
|
+ name="eventType"
|
|
|
|
+ :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-form-item>
|
|
|
|
+
|
|
|
|
+ <a-form-item
|
|
|
|
+ label="计划时间"
|
|
|
|
+ name="planTime"
|
|
|
|
+ :rules="[{ type: 'array' as const, required: true, message: '请选择计划时间' }]"
|
|
|
|
+ >
|
|
|
|
+ <a-range-picker
|
|
|
|
+ v-model:value="formState.planTime"
|
|
|
|
+ style="width: 100%"
|
|
|
|
+ show-time
|
|
|
|
+ valueFormat="YYYY-MM-DD HH:mm:ss"
|
|
|
|
+ />
|
|
|
|
+ </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="mouth">按月</a-radio>
|
|
|
|
+ </a-radio-group>
|
|
|
|
+ </a-form-item>
|
|
|
|
+
|
|
|
|
+ <a-form-item label="生效范围" name="firmwareVersion">
|
|
|
|
+ <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>
|
|
|
|
+
|
|
|
|
+ <a-form-item label="生效时段">
|
|
|
|
+ <div style="display: flex; align-items: center; gap: 8px">
|
|
|
|
+ <a-time-range-picker
|
|
|
|
+ v-model:value="formState.effectTimeFrame"
|
|
|
|
+ valueFormat="HH:mm:ss"
|
|
|
|
+ style="width: 100%"
|
|
|
|
+ />
|
|
|
|
+ <a-button size="small" type="link" @click="addEffectTime">添加</a-button>
|
|
|
|
+ </div>
|
|
|
|
+ <div style="margin-top: 12px">
|
|
|
|
+ <span v-if="!formState.effectTimeFrames.length" style="color: #aaa; font-size: 12px"
|
|
|
|
+ >暂无生效时段</span
|
|
|
|
+ >
|
|
|
|
+ <a-space wrap v-else>
|
|
|
|
+ <a-tag
|
|
|
|
+ v-for="(item, index) in formState.effectTimeFrames"
|
|
|
|
+ :key="index"
|
|
|
|
+ closable
|
|
|
|
+ style="font-size: 14px; padding: 4px 10px"
|
|
|
|
+ @close="deleteEffectTimeItem($event, index)"
|
|
|
|
+ >{{ item.startTime }} - {{ item.endTime }}</a-tag
|
|
|
|
+ >
|
|
|
|
+ </a-space>
|
|
|
|
+ </div>
|
|
|
|
+ </a-form-item>
|
|
|
|
+ <a-form-item label="是否启用">
|
|
|
|
+ <a-switch v-model:checked="formState.isEnable" />
|
|
|
|
+ </a-form-item>
|
|
|
|
+ </a-form>
|
|
|
|
+
|
|
|
|
+ <div class="footer">
|
|
|
|
+ <a-space>
|
|
|
|
+ <a-button @click="cancel">取消</a-button>
|
|
|
|
+ <a-button type="primary" :loading="submitLoading" @click="submit">保存</a-button>
|
|
|
|
+ </a-space>
|
|
|
|
+ </div>
|
|
|
|
+ </a-modal>
|
|
|
|
+ </div>
|
|
|
|
+</template>
|
|
|
|
+
|
|
|
|
+<script setup lang="ts">
|
|
|
|
+import { ref, reactive, watch } from 'vue'
|
|
|
|
+import { message, type FormInstance } from 'ant-design-vue'
|
|
|
|
+// import * as deviceApi from '@/api/device'
|
|
|
|
+// import type { Rule } from 'ant-design-vue/es/form'
|
|
|
|
+
|
|
|
|
+defineOptions({
|
|
|
|
+ name: 'AlarmPlanModal',
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+const formRef = ref<FormInstance>()
|
|
|
|
+
|
|
|
|
+type Props = {
|
|
|
|
+ open: boolean
|
|
|
|
+ title?: string
|
|
|
|
+}
|
|
|
|
+const emit = defineEmits<{
|
|
|
|
+ (e: 'update:open', value: boolean): void
|
|
|
|
+ (e: 'success', value: void): void
|
|
|
|
+}>()
|
|
|
|
+
|
|
|
|
+const props = withDefaults(defineProps<Props>(), {
|
|
|
|
+ open: false,
|
|
|
|
+ title: '告警计划',
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+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',
|
|
|
|
+]
|
|
|
|
+
|
|
|
|
+type FormState = {
|
|
|
|
+ planName: string // 计划名称
|
|
|
|
+ region: string[] // 检测区域 [left, top, width, height]
|
|
|
|
+ eventType: string | null // 事件类型
|
|
|
|
+ planTime: string[] // 计划时间
|
|
|
|
+ effectType: 'week' | 'month' // 生效方式 周week、月month
|
|
|
|
+ effectTimeRanges: string[] // 生效范围 周 1-7、月 1-31
|
|
|
|
+ effectTimeFrame: string[] // 生效时段 单条 00:00:00 - 23:59:59
|
|
|
|
+ effectTimeFrames: { startTime: string; endTime: string }[] // 生效时段 多条
|
|
|
|
+ isEnable: boolean // 是否启用
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const formState = reactive<FormState>({
|
|
|
|
+ planName: '',
|
|
|
|
+ region: [],
|
|
|
|
+ eventType: '',
|
|
|
|
+ planTime: [],
|
|
|
|
+ effectType: 'week',
|
|
|
|
+ effectTimeRanges: weekOptions,
|
|
|
|
+ effectTimeFrame: [],
|
|
|
|
+ effectTimeFrames: [],
|
|
|
|
+ isEnable: true,
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+const plainOptions = ref<string[]>(weekOptions)
|
|
|
|
+const checkState = reactive({
|
|
|
|
+ indeterminate: true,
|
|
|
|
+ checkAll: false,
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+const onCheckAllChange = (e: Event) => {
|
|
|
|
+ const checked = (e.target as HTMLInputElement).checked
|
|
|
|
+ checkState.checkAll = checked
|
|
|
|
+ console.log('onCheckAllChange', e, checked)
|
|
|
|
+ formState.effectTimeRanges = checked ? [...plainOptions.value] : []
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+watch(
|
|
|
|
+ () => formState.effectTimeRanges,
|
|
|
|
+ (val) => {
|
|
|
|
+ checkState.indeterminate = !!val.length && val.length < plainOptions.value.length //设置全选按钮的半选状态
|
|
|
|
+ checkState.checkAll = val.length === plainOptions.value.length // 设置全选按钮的选中状态
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ immediate: true,
|
|
|
|
+ }
|
|
|
|
+)
|
|
|
|
+
|
|
|
|
+// 生效方式变化 周week、月month
|
|
|
|
+const effectTypeChange = (e: Event) => {
|
|
|
|
+ const value = (e.target as HTMLInputElement).value
|
|
|
|
+ console.log('effectTypeChange', e, value)
|
|
|
|
+
|
|
|
|
+ if (value === 'week') {
|
|
|
|
+ plainOptions.value = weekOptions
|
|
|
|
+ formState.effectTimeRanges = weekOptions
|
|
|
|
+ } else if (value === 'mouth') {
|
|
|
|
+ plainOptions.value = mouthOptions
|
|
|
|
+ formState.effectTimeRanges = mouthOptions
|
|
|
|
+ }
|
|
|
|
+ /* 置全选按钮的状态 */
|
|
|
|
+ checkState.indeterminate =
|
|
|
|
+ !!formState.effectTimeRanges.length &&
|
|
|
|
+ formState.effectTimeRanges.length < plainOptions.value.length // 设置全选按钮的半选状态
|
|
|
|
+ checkState.checkAll = formState.effectTimeRanges.length === plainOptions.value.length // 设置全选按钮的选中状态
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// 添加时间段
|
|
|
|
+const addEffectTime = () => {
|
|
|
|
+ console.log('addEffectTime', formState.effectTimeFrame)
|
|
|
|
+ if (!formState.effectTimeFrame || !formState.effectTimeFrame.length) {
|
|
|
|
+ message.warn('请选择时间段')
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ formState.effectTimeFrames.push({
|
|
|
|
+ startTime: formState.effectTimeFrame[0],
|
|
|
|
+ endTime: formState.effectTimeFrame[1],
|
|
|
|
+ })
|
|
|
|
+ // formState.effectTimeFrame = [] // 清空选择的时间段
|
|
|
|
+}
|
|
|
|
+// 删除已添加的时间段
|
|
|
|
+const deleteEffectTimeItem = (e: Event, index: number) => {
|
|
|
|
+ console.log('deleteEffectTimeItem', e, index)
|
|
|
|
+ formState.effectTimeFrames.splice(index, 1)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const cancel = () => {
|
|
|
|
+ formRef?.value?.resetFields()
|
|
|
|
+ emit('update:open', false)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const submitLoading = ref(false)
|
|
|
|
+// 确定
|
|
|
|
+const submit = () => {
|
|
|
|
+ formRef?.value
|
|
|
|
+ ?.validate()
|
|
|
|
+ .then(() => {
|
|
|
|
+ console.log('校验通过', formState)
|
|
|
|
+ // submitLoading.value = true
|
|
|
|
+ // deviceApi
|
|
|
|
+ // .addDevice({
|
|
|
|
+ // clientId: formState.deviceId,
|
|
|
|
+ // devType: formState.deviceType,
|
|
|
|
+ // software: formState.firmwareVersion,
|
|
|
|
+ // tenantId: formState.tenantId,
|
|
|
|
+ // })
|
|
|
|
+ // .then((res) => {
|
|
|
|
+ // console.log('添加成功', res)
|
|
|
|
+ // submitLoading.value = false
|
|
|
|
+ // message.success('添加成功')
|
|
|
|
+ // emit('success')
|
|
|
|
+ // cancel()
|
|
|
|
+ // })
|
|
|
|
+ // .catch(() => {
|
|
|
|
+ // submitLoading.value = false
|
|
|
|
+ // })
|
|
|
|
+ })
|
|
|
|
+ .catch((err) => {
|
|
|
|
+ console.log('校验失败', err)
|
|
|
|
+ })
|
|
|
|
+}
|
|
|
|
+</script>
|
|
|
|
+
|
|
|
|
+<style scoped lang="less">
|
|
|
|
+:deep(.ant-modal) {
|
|
|
|
+ .footer {
|
|
|
|
+ text-align: right;
|
|
|
|
+ }
|
|
|
|
+ .ant-modal-body {
|
|
|
|
+ padding: 12px 0;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+:deep(.ant-checkbox-group) {
|
|
|
|
+ .ant-checkbox + span {
|
|
|
|
+ min-width: 32px;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+:deep(.ant-tag) {
|
|
|
|
+ margin-inline-end: 0 !important;
|
|
|
|
+}
|
|
|
|
+</style>
|