husq
2023-10-12 45bb6c748c3734469e5e80648d9d48c7e83fc8a4
Merge branch 'demo' of http://s16s652780.51mypc.cn:49896/r/yskj/iot_drone_web into demo
2 files modified
1 files added
542 ■■■■ changed files
src/components/g-map/use-drone-control-ws-event.ts 8 ●●●● patch | view | raw | blame | history
src/components/task/CreatePlan.vue 191 ●●●● patch | view | raw | blame | history
src/utils/jobTime.ts 343 ●●●●● patch | view | raw | blame | history
src/components/g-map/use-drone-control-ws-event.ts
@@ -27,7 +27,7 @@
    if (error !== 0) {
      notification.error({
        key: key,
        message: key + 'Error code:' + error,
        message: key + '错误码:' + error,
        description: message,
        duration: null
      })
@@ -54,19 +54,19 @@
      case EBizCode.FlyToPointProgress: {
        const { sn: deviceSn, result, message: msg } = payload.data as FlyToPointMessage
        if (deviceSn !== sn) return
        handleProgress(EBizCode.FlyToPointProgress, `device(sn: ${deviceSn}) ${msg}`, result)
        handleProgress(EBizCode.FlyToPointProgress, `设备(编码: ${deviceSn}) ${msg}`, result)
        break
      }
      case EBizCode.TakeoffToPointProgress: {
        const { sn: deviceSn, result, message: msg } = payload.data as TakeoffToPointMessage
        if (deviceSn !== sn) return
        handleProgress(EBizCode.TakeoffToPointProgress, `device(sn: ${deviceSn}) ${msg}`, result)
        handleProgress(EBizCode.TakeoffToPointProgress, `设备(编码: ${deviceSn}) ${msg}`, result)
        break
      }
      case EBizCode.JoystickInvalidNotify: {
        const { sn: deviceSn, result, message: msg } = payload.data as DrcModeExitNotifyMessage
        if (deviceSn !== sn) return
        handleProgress(EBizCode.JoystickInvalidNotify, `device(sn: ${deviceSn}) ${msg}`, result)
        handleProgress(EBizCode.JoystickInvalidNotify, `设备(编码: ${deviceSn}) ${msg}`, result)
        break
      }
      case EBizCode.DrcStatusNotify: {
src/components/task/CreatePlan.vue
@@ -105,41 +105,26 @@
        <a-form-item label="执行日期"
                     v-if="planBody.task_type === TaskType.Repeat || planBody.task_type === TaskType.Continuous"
                     name="time_range" :labelCol="{ span: 23 }">
          <a-range-picker v-model:value="planBody.time_range" format="YYYY-MM-DD" placeholder="请选择日期"/>
          <a-range-picker v-model:value="planBody.time_range" format="YYYY-MM-DD"
                          :placeholder="['开始时间','结束时间']"/>
        </a-form-item>
        <!-- 执行时间 (重复定时)-->
        <a-form-item label="执行时间" v-if="planBody.task_type === TaskType.Repeat" name="execute_time_arr"
                     :labelCol="{ span: 23 }">
          <div class="execute-time-arr-item" v-for="(item,index) in executeTimeRepeatArr" :key="index">
            <a-time-picker v-model:value="item.value" format="HH:mm"/>
            <a-button @click="addTime" type="default" shape="circle" :size="componentOptions.size">
              <template #icon>
                <PlusCircleOutlined/>
              </template>
            </a-button>
            <a-button @click="deleteTime(item)" type="default" shape="circle" :size="componentOptions.size">
              <template #icon>
                <MinusCircleOutlined/>
              </template>
            </a-button>
          </div>
        </a-form-item>
        <!-- 执行时间 (连续执行)-->
        <a-form-item label="执行时间" v-if="planBody.task_type === TaskType.Continuous" :labelCol="{ span: 23 }">
          <div class="execute-time-arr-continuous-item" v-for="(item,index) in executeTimeContinuousArr" :key="index">
            <div class="time-select">
              <div class="time-item">
                <a-time-picker style="width: 100px;" v-model:value="item.value[0]" format="HH:mm"/>
              </div>
              <div style="color: white">-</div>
              <div class="time-item">
                <a-time-picker style="width: 100px;" v-model:value="item.value[1]" format="HH:mm"/>
              </div>
            </div>
            <div class="btn-group">
        <div v-if="planBody.task_type === TaskType.Repeat">
          <div class="execute-time-arr-item">
          <a-form-item
              v-for="(item, index) in planBody.executeTimeRepeatArr"
              :key="item.index"
              :label="index === 0 ? '执行时间' : ''"
              :name="item.index+'repValue'"
              :labelCol="{ span: 23 }"
              :rules="[{
                required: true,
                trigger: ['change','blur'],
                validator: validateRepeatExecuteTime
              }]"
          >
              <a-time-picker v-model:value="item.value" @change="onRepeatChange(item)" format="HH:mm"/>
              <a-button @click="addTime" type="default" shape="circle" :size="componentOptions.size">
                <template #icon>
                  <PlusCircleOutlined/>
@@ -150,11 +135,52 @@
                  <MinusCircleOutlined/>
                </template>
              </a-button>
            </div>
          </a-form-item>
          </div>
        </a-form-item>
        </div>
        <!-- 重复频率-->
        <!-- 执行时间 (连续执行)-->
        <div v-if="planBody.task_type === TaskType.Continuous">
          <a-form-item
              v-for="(item, index) in planBody.executeTimeContinuousArr"
              :key="item.index"
              :label="index === 0 ? '执行时间' : ''"
              :name="item.index+'conValue'"
              :labelCol="{ span: 23 }"
              :rules="{
                required: true,
                trigger: ['change', 'blur'],
               validator: validateContinuousExecuteTime
              }"
          >
            <div class="execute-time-arr-continuous-item">
              <div class="time-select">
                <div class="time-item">
                  <a-time-picker style="width: 100px;" v-model:value="item.value[0]" @change="onContinuousChange(item)" format="HH:mm"/>
                </div>
                <div style="color: white">-</div>
                <div class="time-item">
                  <a-time-picker style="width: 100px;" v-model:value="item.value[1]" @change="onContinuousChange(item)" format="HH:mm"/>
                </div>
              </div>
              <div class="btn-group">
                <a-button @click="addTime" type="default" shape="circle" :size="componentOptions.size">
                  <template #icon>
                    <PlusCircleOutlined/>
                  </template>
                </a-button>
                <a-button @click="deleteTime(item)" type="default" shape="circle" :size="componentOptions.size">
                  <template #icon>
                    <MinusCircleOutlined/>
                  </template>
                </a-button>
              </div>
            </div>
          </a-form-item>
        </div>
        <!-- 任务开始执行的电量-->
        <a-form-item label="任务开始执行的电量" v-if=" planBody.task_type === TaskType.Continuous"
                     name="battery_capacity" :labelCol="{ span: 23 }">
          <a-input style="background: black;" v-model:value="planBody.battery_capacity"/>
@@ -163,6 +189,7 @@
        <!-- 重复频率-->
        <a-form-item label="重复频率"
                     v-if="planBody.task_type === TaskType.Repeat || planBody.task_type === TaskType.Continuous"
                     name="rep_fre_val"
                     :labelCol="{ span: 23 }">
          <div class="rep-fre-item">
            <div>每</div>
@@ -186,7 +213,7 @@
          </a-button>
        </a-form-item>
        <!-- 重复频率-->
        <!-- 重复规则-->
        <a-form-item label="重复规则"
                     v-if="(planBody.task_type === TaskType.Repeat || planBody.task_type === TaskType.Continuous) && planBody.rep_fre_type === FrequencyType.month"
                     :labelCol="{ span: 23 }">
@@ -318,14 +345,35 @@
  rep_fre_val: 1,
  rep_fre_type: 3,
  rep_rule_type: 1,
  executeTimeContinuousArr: [{ index: 1, value: [] }],
  executeTimeRepeatArr: [{ index: 1, value: '' }]
})
const executeTimeRepeatArr = ref([
  { index: 1, value: '' }
])
const executeTimeContinuousArr = ref([
  { index: 1, value: [] }
])
watch(
  planBody.executeTimeRepeatArr,
  (newVal) => {
    if (newVal.length) {
      newVal.forEach(item => {
        planBody[`${item.index}repValue`] = item.value
      })
    }
  },
  { deep: true, immediate: true }
)
watch(
  planBody.executeTimeContinuousArr,
  (newVal) => {
    if (newVal.length) {
      newVal.forEach(item => {
        planBody[`${item.index}conValue`] = item.value
      })
    }
  },
  { deep: true, immediate: true }
)
// 重复规则为按星期时
const repeatRuleValueWeek = ref([1, 1])
// 重复规则为按日期时
@@ -401,19 +449,58 @@
    }
  ],
  out_of_control_action: [{ required: true, message: '请选择航线飞行中失联' }],
  rep_fre_val: [
    {
      validator: async (rule: RuleObject, value: string) => {
        if (!/^[0-9]{1,}$/.test(value)) {
          planBody.rep_fre_val = ''
          throw new Error('重复频率不能为空')
        }
      },
      trigger: ['blur', 'change']
    }
  ]
}
function validateContinuousExecuteTime (rule: RuleObject, value: Moment[]) {
  if (!value[0]) {
    return Promise.reject(new Error('请选择执行时间'))
  } else if (value.length < 2) {
    return Promise.reject(new Error('请选择执行结束时间'))
  } else if (value[1].isBefore(value[0])) {
    return Promise.reject(new Error('执行结束时间不能小于执行开始时间'))
  } else {
    return Promise.resolve()
  }
}
function validateRepeatExecuteTime (rule: RuleObject, value: any) {
  console.log('验证值', rule)
  if (!value) {
    return Promise.reject(new Error('请选择执行时间'))
  }
}
function onRepeatChange (item: any) {
  planBody[`${item.index}repValue`] = item.value
  console.log('表单:', planBody)
}
function onContinuousChange (item: any) {
  planBody[`${item.index}conValue`] = item.value
  console.log('表单:', planBody)
}
// 重复定时添加执行时间
function addTime () {
  if (planBody.task_type === TaskType.Repeat) {
    const index = executeTimeRepeatArr.value[executeTimeRepeatArr.value.length - 1].index
    executeTimeRepeatArr.value.push({
    const index = planBody.executeTimeRepeatArr[planBody.executeTimeRepeatArr.length - 1].index
    planBody.executeTimeRepeatArr.push({
      index: index + 1,
      value: ''
    })
  } else if (planBody.task_type === TaskType.Continuous) {
    const index = executeTimeContinuousArr.value[executeTimeContinuousArr.value.length - 1].index
    executeTimeContinuousArr.value.push({
    const index = planBody.executeTimeContinuousArr[planBody.executeTimeContinuousArr.length - 1].index
    planBody.executeTimeContinuousArr.push({
      index: index + 1,
      value: []
    })
@@ -423,9 +510,9 @@
// 删除执行时间
function deleteTime (item: any) {
  if (planBody.task_type === TaskType.Repeat) {
    executeTimeRepeatArr.value = executeTimeRepeatArr.value.filter(e => e.index !== item.index)
    planBody.executeTimeRepeatArr = planBody.executeTimeRepeatArr.filter(e => e.index !== item.index)
  } else if (planBody.task_type === TaskType.Continuous) {
    executeTimeContinuousArr.value = executeTimeContinuousArr.value.filter(e => e.index !== item.index)
    planBody.executeTimeContinuousArr = planBody.executeTimeContinuousArr.filter(e => e.index !== item.index)
  }
}
@@ -448,7 +535,7 @@
        createPlanBody.task_days = [moment(planBody.time_range[0]).unix(), moment(planBody.time_range[1]).unix()]
        createPlanBody.task_periods = []
        // 执行时间
        executeTimeRepeatArr.value.forEach(item => {
        planBody.executeTimeRepeatArr.forEach(item => {
          console.log(item, '------')
          createPlanBody.task_periods.push([moment(item.value).unix()])
@@ -470,7 +557,7 @@
        break
      case TaskType.Continuous:
        createPlanBody.task_type = 2
        // createPlanBody.task_type = 2
        createPlanBody.task_days = [moment(planBody.time_range[0]).unix(), moment(planBody.time_range[1]).unix()]
        if (planBody.rep_fre_type === FrequencyType.month) {
@@ -487,7 +574,7 @@
        }
        createPlanBody.task_periods = []
        // 执行时间
        executeTimeContinuousArr.value.forEach(item => {
        planBody.executeTimeContinuousArr.forEach(item => {
          createPlanBody.task_periods.push([moment(item.value[0]).unix(), moment(item.value[1]).unix()])
        })
@@ -500,7 +587,7 @@
    }
    // getFlyTimeList(createPlanBody)
    disabled.value = false
    createPlan(workspaceId, createPlanBody)
      .then(res => {
        disabled.value = false
src/utils/jobTime.ts
New file
@@ -0,0 +1,343 @@
import { CreatePlan } from '/@/api/wayline'
import { FrequencyType, RepeatRuleType, TaskType } from '/@/types/task'
import { dateFormat } from '/@/utils/time'
import moment from 'moment'
/**
 * 根据规则获取起飞时间节点(时间戳)
 * @param creatPlan
 */
export function getFlyTimeList (creatPlan: CreatePlan) {
  console.log('表单', creatPlan)
  const startDate = moment.unix(creatPlan.task_days[0]).toDate()
  const endDate = moment.unix(creatPlan.task_days[1]).toDate()
  console.log('开始时间:', startDate, '结束时间:', endDate)
  let finalDateTimeArr = [] as any
  if (creatPlan.task_type === TaskType.Repeat) {
    // 重复定时
    switch (creatPlan.rep_fre_type) {
      // 月
      case FrequencyType.month: {
        // 先计算这几个月分别是哪个月
        const monthList = getYearMonth(startDate, endDate, creatPlan.rep_fre_val)
        console.log('月:', monthList)
        if (creatPlan.rep_rule_type === RepeatRuleType.day) {
          // 按日期
          // 拼接日期
          const dateList = [] as any
          monthList.forEach(date => {
            creatPlan.rep_rule_val?.forEach(day => {
              if (day < 10) {
                day = '0' + day
              }
              creatPlan.task_periods?.forEach(timearr => {
                const timeStr = moment.unix(timearr[0]).format('HH:mm')
                const str = date + '-' + day + ' ' + timeStr
                const tempDate = new Date(str)
                dateList.push(tempDate)
              })
            })
          })
          console.log('日期时间:', dateList)
          // 过滤掉不在选择日期内的日期
          finalDateTimeArr = dateList.filter(date => {
            // 如果该日期的时间大于结束时间,则过滤掉
            if (date.getTime() > endDate.getTime()) {
              return false
            }
            const tempDate = date.getDate()
            let j = 0
            for (let i = 0; i < creatPlan.rep_rule_val?.length; i++) {
              if (tempDate === creatPlan.rep_rule_val[i]) {
                return true
              } else {
                j++
                // 全都不符合
                if (j === creatPlan.rep_rule_val?.length) {
                  return false
                }
              }
            }
            return false
          })
          // 去重
          finalDateTimeArr = Array.from(new Set(finalDateTimeArr.map(date => dateFormat(date, 'yyyy-MM-dd hh:mm'))))
        } else if (creatPlan.rep_rule_type === RepeatRuleType.week) {
          // 按星期
          monthList.forEach(yearMonth => {
            const tmpDate = new Date(yearMonth)
            const date = getMonthWeek(tmpDate.getFullYear(), tmpDate.getMonth(), creatPlan.rep_rule_val[0], creatPlan.rep_rule_val[1])
            creatPlan.task_periods?.forEach(timearr => {
              const timeStr = moment.unix(timearr[0]).format('HH:mm')
              const dateStr = date + ' ' + timeStr
              finalDateTimeArr.push(dateStr)
            })
          })
        }
        break
      }
      // 周
      case FrequencyType.week: {
        // 获取每n周的日期
        const weekDate = gainAllDateBetRange(startDate, endDate, creatPlan.rep_fre_val * 7)
        console.log('星期时间:', weekDate)
        // 获取星期
        const dateList = getDateListOfWeek(weekDate, creatPlan.rep_rule_val)
        // 拼接时间
        dateList.forEach(date => {
          creatPlan.task_periods?.forEach(timearr => {
            const timeStr = moment.unix(timearr[0]).format('HH:mm')
            finalDateTimeArr.push(date + ' ' + timeStr)
          })
        })
        break
      }
      // 日
      case FrequencyType.day: {
        // 根据每几天获取时间
        const dateList = gainAllDateBetRange(startDate, endDate, creatPlan.rep_fre_val)
        // 拼接执行时间即可
        dateList.forEach(date => {
          creatPlan.task_periods?.forEach(timearr => {
            const timeStr = moment.unix(timearr[0]).format('HH:mm')
            finalDateTimeArr.push(date + ' ' + timeStr)
          })
        })
        break
      }
    }
  } else if (creatPlan.task_type === TaskType.Continuous) {
    // 连续执行
    switch (creatPlan.rep_fre_type) {
        // 月
      case FrequencyType.month: {
        // 先计算这几个月分别是哪个月
        const monthList = getYearMonth(startDate, endDate, creatPlan.rep_fre_val)
        console.log('月:', monthList)
        if (creatPlan.rep_rule_type === RepeatRuleType.day) {
          // 按日期
          // 拼接日期
          const dateList = [] as any
          monthList.forEach(date => {
            creatPlan.rep_rule_val?.forEach(day => {
              if (day < 10) {
                day = '0' + day
              }
              creatPlan.task_periods?.forEach(timearr => {
                timearr.forEach(time=>{
                  const timeStr = moment.unix(time).format('HH:mm')
                  const str = date + '-' + day + ' ' + timeStr
                  const tempDate = new Date(str)
                  dateList.push(tempDate)
                })
              })
            })
          })
          console.log('日期时间:', dateList)
          // 过滤掉不在选择日期内的日期
          finalDateTimeArr = dateList.filter(date => {
            // 如果该日期的时间大于结束时间,则过滤掉
            if (date.getTime() > endDate.getTime()) {
              return false
            }
            const tempDate = date.getDate()
            let j = 0
            for (let i = 0; i < creatPlan.rep_rule_val?.length; i++) {
              if (tempDate === creatPlan.rep_rule_val[i]) {
                return true
              } else {
                j++
                // 全都不符合
                if (j === creatPlan.rep_rule_val?.length) {
                  return false
                }
              }
            }
            return false
          })
          // 去重
          finalDateTimeArr = Array.from(new Set(finalDateTimeArr.map(date => dateFormat(date, 'yyyy-MM-dd hh:mm'))))
        } else if (creatPlan.rep_rule_type === RepeatRuleType.week) {
          // 按星期
          monthList.forEach(yearMonth => {
            const tmpDate = new Date(yearMonth)
            const date = getMonthWeek(tmpDate.getFullYear(), tmpDate.getMonth(), creatPlan.rep_rule_val[0], creatPlan.rep_rule_val[1])
            creatPlan.task_periods?.forEach(timearr => {
              timearr.forEach(time=>{
                const timeStr = moment.unix(time).format('HH:mm')
                const dateStr = date + ' ' + timeStr
                finalDateTimeArr.push(dateStr)
              })
            })
          })
        }
        break
      }
        // 周
      case FrequencyType.week: {
        // 获取每n周的日期
        const weekDate = gainAllDateBetRange(startDate, endDate, creatPlan.rep_fre_val * 7)
        console.log('星期时间:', weekDate)
        // 获取星期
        const dateList = getDateListOfWeek(weekDate, creatPlan.rep_rule_val)
        // 拼接时间
        dateList.forEach(date => {
          creatPlan.task_periods?.forEach(timearr => {
            timearr.forEach(time=>{
              const timeStr = moment.unix(time).format('HH:mm')
              finalDateTimeArr.push(date + ' ' + timeStr)
            })
          })
        })
        break
      }
        // 日
      case FrequencyType.day: {
        // 根据每几天获取时间
        const dateList = gainAllDateBetRange(startDate, endDate, creatPlan.rep_fre_val)
        // 拼接执行时间即可
        dateList.forEach(date => {
          creatPlan.task_periods?.forEach(timearr => {
            console.log(timearr,"***************************")
            timearr.forEach(time=>{
              console.log("time:",time)
              const timeStr = moment.unix(time).format('HH:mm')
              console.log("timeStr:",timeStr)
              finalDateTimeArr.push(date + ' ' + timeStr)
            })
          })
        })
        break
      }
    }
  }
  console.log('最终时间:', finalDateTimeArr)
  var tempDateTimeArr = []
  if (creatPlan.task_type === TaskType.Repeat) {
    tempDateTimeArr =  finalDateTimeArr.map(dateTime=>[dateTime])
  }else if (creatPlan.task_type === TaskType.Continuous){
  }
  // 对finalDateTimeArr进行时间过滤,筛选掉过去时间和无效时间
  const futureDateTimeArr = finalDateTimeArr.filter(dateStr => {
    return new Date(dateStr).getTime() >= new Date().getTime()
  })
  console.log('未来时间:', futureDateTimeArr)
  return futureDateTimeArr
}
// 获取一个日期范围内的每n天的日期,入参为Date对象
function gainAllDateBetRange (startDate: Date, endDate: Date, n = 1) {
  const dateArr = [] as any
  if (!(startDate instanceof Date && endDate instanceof Date)) return dateArr // 非时间格式返回空数组
  const startTime = startDate.getTime() // 获取开始日期的毫秒数
  const endTime = endDate.getTime() // 获取结束日期的毫秒数
  const numTime = 24 * 60 * 60 * 1000 * n // 一天的毫秒数
  for (let time = startTime; time <= endTime;) {
    dateArr.push(dateFormat(new Date(time), 'yyyy-MM-dd')) // 将格式化后的时间存入结果数组
    time += numTime // 每次加n天
  }
  console.log('每', n, '天的日期', dateArr)
  return dateArr
}
/**
 * 获取当前日期的星期数的日期
 * @param date
 */
function getDateListOfWeek (dateArr: any[], week: number[]) {
  console.log('获取当前日期的星期数的日期:', dateArr, week)
  const list = [] as any
  dateArr.forEach(dateStr => {
    const date = new Date(dateStr)
    week.forEach(n => {
      const tempDate = weekDate(date, n)
      list.push(tempDate)
    })
  })
  return list
}
/**
 * 根据日期获取星期日期
 * @param date
 * @param n
 */
function weekDate (date: Date, n: number) {
  date.setDate(date.getDate() + n - (date.getDay() || 7))
  const dateStr = dateFormat(new Date(date), 'yyyy-MM-dd')
  return dateStr
}
function getYearMonth (startDate: Date, endDate: Date, n: number) {
  const dateArr = [] as any
  const startTime = startDate.getTime()
  const endTime = endDate.getTime()
  console.log('开始时间结束时间时间戳', startTime, endTime)
  let date = startDate
  for (let dateTime = startTime; dateTime <= endTime;) {
    const str = dateFormat(date, 'yyyy-MM')
    dateArr.push(str)
    date = new Date(date.getFullYear(), date.getMonth() + Number(n))
    dateTime = date.getTime()
  }
  return dateArr
}
/**
 * 获取某年月的第几周的周几的日期
 * @param year
 * @param month
 */
function getMonthWeek (year:number, month:number, whichWeek:number, whichDay:number) {
  // 获取该月的第一天
  const firstDayOfMonth = new Date(year, month, 1)
  const daysOffset = whichDay - firstDayOfMonth.getDay() // 计算第一周的差几天
  const day = firstDayOfMonth.getDate() + daysOffset + 7 * (whichWeek - 1) // 第二周的星期一的日期
  return dateFormat(new Date(year, month, day), 'yyyy-MM-dd')
}