CurrentTimeConditionConfig.vue 7.5 KB

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