Form.vue 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. <template>
  2. <a-form :form="form.fc" style="wdith: 400px;" v-bind="formItemLayout">
  3. <a-form-item :label="$t('compute.text_732')">
  4. <a-select v-decorator="decorators.metric" :disabled="metricDisabled" @change="metricChange">
  5. <a-select-option v-for="item in metricOpts" :key="item.key" :value="item.key">
  6. {{ item.label }}
  7. </a-select-option>
  8. </a-select>
  9. </a-form-item>
  10. <a-form-item :label="$t('compute.text_733')">
  11. <a-input-number v-decorator="decorators.window" :min="windowMin" />{{$t('compute.text_734')}}</a-form-item>
  12. <a-form-item :label="$t('compute.text_735')">
  13. <a-select v-decorator="decorators.comparator">
  14. <a-select-option v-for="item in comparatorOpts" :key="item.key" :value="item.key">
  15. {{ item.label }}
  16. </a-select-option>
  17. </a-select>
  18. </a-form-item>
  19. <a-form-item :label="$t('compute.text_736')">
  20. <a-input type="number" :min="0" v-decorator="[
  21. 'threshold',
  22. {
  23. initialValue: fdInitailValue.threshold,
  24. normalize: value => {
  25. if (R.isNil(value) || R.isEmpty(value)) return undefined
  26. return Number(value)
  27. },
  28. rules: [
  29. { required: true, message: $t('compute.text_737') },
  30. ...thresholdRules
  31. ]
  32. }
  33. ]">
  34. <div slot="addonAfter" v-if="thresholdUnit">{{ thresholdUnit }}</div>
  35. </a-input>
  36. </a-form-item>
  37. <a-form-item :label="$t('monitor.level')">
  38. <a-radio-group v-decorator="decorators.level">
  39. <a-radio-button v-for="item in levelOpts" :value="item.key" :key="item.key">{{ item.label }}</a-radio-button>
  40. </a-radio-group>
  41. </a-form-item>
  42. <a-form-item :label="$t('compute.text_739')">
  43. <a-select v-decorator="decorators.channel">
  44. <a-select-option v-for="item in channelOpts" :key="item.key" :value="item.key">
  45. {{ item.label }}
  46. </a-select-option>
  47. </a-select>
  48. </a-form-item>
  49. <a-form-item :label="$t('compute.text_740')">
  50. <a-spin v-show="!recipientsLoaded" />
  51. <base-select
  52. v-show="recipientsLoaded"
  53. v-decorator="decorators.recipients"
  54. class="w-100"
  55. :filterable="true"
  56. needParams
  57. resource="receivers"
  58. version="v1"
  59. :params="recipientParams"
  60. :resList.sync="recipientOpts"
  61. :initLoaded.sync="recipientsLoaded"
  62. :select-props="{ placeholder: $t('common.tips.select', [$t('compute.text_740')]), allowClear: true, mode: 'multiple' }" />
  63. </a-form-item>
  64. </a-form>
  65. </template>
  66. <script>
  67. import * as R from 'ramda'
  68. import { LEVEL_CN } from '@Compute/views/node-alert/constants'
  69. import { findPlatform } from '@/utils/common/hypervisor'
  70. export default {
  71. name: 'NodeAlertForm',
  72. props: {
  73. metricOpts: {
  74. type: Array,
  75. // required: true,
  76. },
  77. alertType: {
  78. type: String,
  79. required: true,
  80. validator: val => ['guest', 'host'].includes(val),
  81. },
  82. hypervisor: {
  83. type: String,
  84. },
  85. fdInitailValue: { // 表单初始化数据
  86. type: Object,
  87. default: () => {
  88. return {
  89. window: 5,
  90. comparator: '>=',
  91. level: 'normal',
  92. channel: 'email',
  93. }
  94. },
  95. },
  96. monitorMetric: {
  97. type: String,
  98. },
  99. },
  100. data () {
  101. const metric = this.monitorMetric || this.fdInitailValue.metric || this.metricOpts[0].key
  102. return {
  103. form: {
  104. fc: this.$form.createForm(this),
  105. },
  106. metric,
  107. recipientsLoaded: false, // 报警接收人是否加载完成
  108. decorators: {
  109. metric: [
  110. 'metric',
  111. {
  112. initialValue: metric,
  113. rules: [
  114. { required: true, message: this.$t('compute.text_742') },
  115. ],
  116. },
  117. ],
  118. window: [
  119. 'window',
  120. {
  121. initialValue: this.fdInitailValue.window,
  122. },
  123. ],
  124. comparator: [
  125. 'comparator',
  126. {
  127. initialValue: this.fdInitailValue.comparator,
  128. },
  129. ],
  130. // threshold 是动态表单规则,需在 template 里面写
  131. level: [
  132. 'level',
  133. {
  134. initialValue: this.fdInitailValue.level,
  135. },
  136. ],
  137. channel: [
  138. 'channel',
  139. {
  140. initialValue: this.fdInitailValue.channel,
  141. },
  142. ],
  143. recipients: [
  144. 'recipients',
  145. {
  146. initialValue: this.fdInitailValue.recipients,
  147. rules: [
  148. { required: true, message: this.$t('common.tips.select', [this.$t('compute.text_740')]), type: 'array' },
  149. ],
  150. },
  151. ],
  152. },
  153. formItemLayout: {
  154. wrapperCol: {
  155. span: 19,
  156. },
  157. labelCol: {
  158. span: 5,
  159. },
  160. },
  161. comparatorOpts: [
  162. { key: '>=', label: '>=' },
  163. { key: '<=', label: '<=' },
  164. // { key: '=', label: '=' },
  165. // { key: '!=', label: '!=' }
  166. ],
  167. levelOpts: [
  168. { key: 'normal', label: LEVEL_CN.normal.label },
  169. { key: 'important', label: LEVEL_CN.important.label },
  170. { key: 'fatal', label: LEVEL_CN.fatal.label },
  171. ],
  172. channelOpts: [
  173. { key: 'email', label: this.$t('compute.text_743') },
  174. // { key: 'moblie', label: '短信' },
  175. // { key: 'dingtalk', label: '钉钉通知' }
  176. ],
  177. recipientOpts: [], // 由 base-select 组件同步出来
  178. thresholdRules: [], // threshold 的规则
  179. windowMin: 5,
  180. R,
  181. }
  182. },
  183. computed: {
  184. domainParams () {
  185. // if (this.$store.getters.isAdminMode) {
  186. // return {}
  187. // }
  188. return {
  189. scope: this.$store.getters.scope,
  190. }
  191. },
  192. metricDisabled () {
  193. return R.is(String, this.fdInitailValue.metric) || R.is(String, this.monitorMetric) // 外部传递 metric 或者是 监控指标 则监控项不可变
  194. },
  195. thresholdUnit () {
  196. if (this.metric) {
  197. const metricItem = this.metricOpts.find(val => val.key === this.metric)
  198. if (metricItem && metricItem.unit) return metricItem.unit
  199. }
  200. return ''
  201. },
  202. recipientParams () {
  203. const params = {
  204. enabled: true,
  205. limit: 0,
  206. with_meta: true,
  207. ...this.domainParams,
  208. }
  209. return params
  210. },
  211. },
  212. created () {
  213. this.getThresholdRules(this.metric)
  214. this.getWindowRules()
  215. },
  216. methods: {
  217. metricChange (val) {
  218. this.metric = val
  219. this.getThresholdRules(val)
  220. this.$nextTick(() => {
  221. this.form.fc.validateFields(['threshold'], { force: true }) // 动态校验规则
  222. })
  223. },
  224. getThresholdRules (metric) {
  225. let rules = []
  226. const metricObj = this.metricOpts.find(item => item.key === this.metric)
  227. if (metricObj && metricObj.rules) {
  228. rules = metricObj.rules
  229. }
  230. this.thresholdRules = rules
  231. },
  232. getWindowRules () {
  233. let min = 5
  234. if (this.alertType === 'host') {
  235. min = 10
  236. }
  237. if (this.hypervisor) {
  238. const platform = findPlatform(this.hypervisor, 'hypervisor')
  239. if (platform === 'public') {
  240. min = 10
  241. }
  242. }
  243. this.windowMin = min
  244. },
  245. async validateForm () {
  246. try {
  247. const values = await this.form.fc.validateFields()
  248. return values
  249. } catch (error) {
  250. throw error
  251. }
  252. },
  253. },
  254. }
  255. </script>