CurrentTimeConditionConfig.vue 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. <!-- 当前时间条件配置组件 -->
  2. <template>
  3. <div class="flex flex-col gap-16px">
  4. <el-row :gutter="16">
  5. <!-- 时间操作符选择 -->
  6. <el-col :span="8">
  7. <el-form-item label="时间条件" required>
  8. <el-select
  9. :model-value="condition.operator"
  10. @update:model-value="(value) => updateConditionField('operator', value)"
  11. placeholder="请选择时间条件"
  12. class="w-full"
  13. >
  14. <el-option
  15. v-for="option in timeOperatorOptions"
  16. :key="option.value"
  17. :label="option.label"
  18. :value="option.value"
  19. >
  20. <div class="flex items-center justify-between w-full">
  21. <div class="flex items-center gap-8px">
  22. <Icon :icon="option.icon" :class="option.iconClass" />
  23. <span>{{ option.label }}</span>
  24. </div>
  25. <el-tag :type="option.tag as any" size="small">{{ option.category }}</el-tag>
  26. </div>
  27. </el-option>
  28. </el-select>
  29. </el-form-item>
  30. </el-col>
  31. <!-- 时间值输入 -->
  32. <el-col :span="8">
  33. <el-form-item label="时间值" required>
  34. <el-time-picker
  35. v-if="needsTimeInput"
  36. :model-value="timeValue"
  37. @update:model-value="handleTimeValueChange"
  38. placeholder="请选择时间"
  39. format="HH:mm:ss"
  40. value-format="HH:mm:ss"
  41. class="w-full"
  42. />
  43. <el-date-picker
  44. v-else-if="needsDateInput"
  45. :model-value="timeValue"
  46. @update:model-value="handleTimeValueChange"
  47. type="datetime"
  48. placeholder="请选择日期时间"
  49. format="YYYY-MM-DD HH:mm:ss"
  50. value-format="YYYY-MM-DD HH:mm:ss"
  51. class="w-full"
  52. />
  53. <div v-else class="text-[var(--el-text-color-placeholder)] text-14px">
  54. 无需设置时间值
  55. </div>
  56. </el-form-item>
  57. </el-col>
  58. <!-- 第二个时间值(范围条件) -->
  59. <el-col :span="8" v-if="needsSecondTimeInput">
  60. <el-form-item label="结束时间" required>
  61. <el-time-picker
  62. v-if="needsTimeInput"
  63. :model-value="timeValue2"
  64. @update:model-value="handleTimeValue2Change"
  65. placeholder="请选择结束时间"
  66. format="HH:mm:ss"
  67. value-format="HH:mm:ss"
  68. class="w-full"
  69. />
  70. <el-date-picker
  71. v-else
  72. :model-value="timeValue2"
  73. @update:model-value="handleTimeValue2Change"
  74. type="datetime"
  75. placeholder="请选择结束日期时间"
  76. format="YYYY-MM-DD HH:mm:ss"
  77. value-format="YYYY-MM-DD HH:mm:ss"
  78. class="w-full"
  79. />
  80. </el-form-item>
  81. </el-col>
  82. </el-row>
  83. </div>
  84. </template>
  85. <script setup lang="ts">
  86. import { useVModel } from '@vueuse/core'
  87. import { IotRuleSceneTriggerTimeOperatorEnum } from '@/views/iot/utils/constants'
  88. import type { TriggerCondition } from '@/api/iot/rule/scene'
  89. /** 当前时间条件配置组件 */
  90. defineOptions({ name: 'CurrentTimeConditionConfig' })
  91. const props = defineProps<{
  92. modelValue: TriggerCondition
  93. }>()
  94. const emit = defineEmits<{
  95. (e: 'update:modelValue', value: TriggerCondition): void
  96. }>()
  97. const condition = useVModel(props, 'modelValue', emit)
  98. // 时间操作符选项
  99. const timeOperatorOptions = [
  100. {
  101. value: IotRuleSceneTriggerTimeOperatorEnum.BEFORE_TIME.value,
  102. label: IotRuleSceneTriggerTimeOperatorEnum.BEFORE_TIME.name,
  103. icon: 'ep:arrow-left',
  104. iconClass: 'text-blue-500',
  105. tag: 'primary',
  106. category: '时间点'
  107. },
  108. {
  109. value: IotRuleSceneTriggerTimeOperatorEnum.AFTER_TIME.value,
  110. label: IotRuleSceneTriggerTimeOperatorEnum.AFTER_TIME.name,
  111. icon: 'ep:arrow-right',
  112. iconClass: 'text-green-500',
  113. tag: 'success',
  114. category: '时间点'
  115. },
  116. {
  117. value: IotRuleSceneTriggerTimeOperatorEnum.BETWEEN_TIME.value,
  118. label: IotRuleSceneTriggerTimeOperatorEnum.BETWEEN_TIME.name,
  119. icon: 'ep:sort',
  120. iconClass: 'text-orange-500',
  121. tag: 'warning',
  122. category: '时间段'
  123. },
  124. {
  125. value: IotRuleSceneTriggerTimeOperatorEnum.AT_TIME.value,
  126. label: IotRuleSceneTriggerTimeOperatorEnum.AT_TIME.name,
  127. icon: 'ep:position',
  128. iconClass: 'text-purple-500',
  129. tag: 'info',
  130. category: '时间点'
  131. },
  132. {
  133. value: IotRuleSceneTriggerTimeOperatorEnum.TODAY.value,
  134. label: IotRuleSceneTriggerTimeOperatorEnum.TODAY.name,
  135. icon: 'ep:calendar',
  136. iconClass: 'text-red-500',
  137. tag: 'danger',
  138. category: '日期'
  139. }
  140. ]
  141. // 计算属性:是否需要时间输入
  142. const needsTimeInput = computed(() => {
  143. const timeOnlyOperators = [
  144. IotRuleSceneTriggerTimeOperatorEnum.BEFORE_TIME.value,
  145. IotRuleSceneTriggerTimeOperatorEnum.AFTER_TIME.value,
  146. IotRuleSceneTriggerTimeOperatorEnum.BETWEEN_TIME.value,
  147. IotRuleSceneTriggerTimeOperatorEnum.AT_TIME.value
  148. ]
  149. return timeOnlyOperators.includes(condition.value.operator as any)
  150. })
  151. // 计算属性:是否需要日期输入
  152. const needsDateInput = computed(() => {
  153. return false // 暂时不支持日期输入,只支持时间
  154. })
  155. // 计算属性:是否需要第二个时间输入
  156. const needsSecondTimeInput = computed(() => {
  157. return condition.value.operator === IotRuleSceneTriggerTimeOperatorEnum.BETWEEN_TIME.value
  158. })
  159. // 计算属性:从 param 中解析时间值
  160. const timeValue = computed(() => {
  161. if (!condition.value.param) return ''
  162. const params = condition.value.param.split(',')
  163. return params[0] || ''
  164. })
  165. // 计算属性:从 param 中解析第二个时间值
  166. const timeValue2 = computed(() => {
  167. if (!condition.value.param) return ''
  168. const params = condition.value.param.split(',')
  169. return params[1] || ''
  170. })
  171. /**
  172. * 更新条件字段
  173. * @param field 字段名
  174. * @param value 字段值
  175. */
  176. const updateConditionField = (field: any, value: any) => {
  177. condition.value[field] = value
  178. }
  179. /**
  180. * 处理第一个时间值变化
  181. * @param value 时间值
  182. */
  183. const handleTimeValueChange = (value: string) => {
  184. const currentParams = condition.value.param ? condition.value.param.split(',') : []
  185. currentParams[0] = value || ''
  186. // 如果是范围条件,保留第二个值;否则只保留第一个值
  187. if (needsSecondTimeInput.value) {
  188. condition.value.param = currentParams.slice(0, 2).join(',')
  189. } else {
  190. condition.value.param = currentParams[0]
  191. }
  192. }
  193. /**
  194. * 处理第二个时间值变化
  195. * @param value 时间值
  196. */
  197. const handleTimeValue2Change = (value: string) => {
  198. const currentParams = condition.value.param ? condition.value.param.split(',') : ['']
  199. currentParams[1] = value || ''
  200. condition.value.param = currentParams.slice(0, 2).join(',')
  201. }
  202. /** 监听操作符变化,清理不相关的时间值 */
  203. watch(
  204. () => condition.value.operator,
  205. (newOperator) => {
  206. if (newOperator === IotRuleSceneTriggerTimeOperatorEnum.TODAY.value) {
  207. // 今日条件不需要时间参数
  208. condition.value.param = ''
  209. } else if (!needsSecondTimeInput.value) {
  210. // 非范围条件只保留第一个时间值
  211. const currentParams = condition.value.param ? condition.value.param.split(',') : []
  212. condition.value.param = currentParams[0] || ''
  213. }
  214. }
  215. )
  216. </script>