RateLimitRuleForm.vue 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. <template>
  2. <div>
  3. <template v-for="(group, idx) in form[ruleFormKey]">
  4. <div :key="idx">
  5. <div>
  6. <div v-for="(rule, idx2) in group" :key="`${idx}-${idx2}`">
  7. <div class="d-flex">
  8. <div style="flex: 0 0 40%;">
  9. <!-- 字段 -->
  10. <a-form-model-item class="mb-0">
  11. <a-select v-model="rule.type" :placeholder="$t('network.field')" @change="handleTypeChange(idx, idx2)">
  12. <a-select-option v-for="item in rateLimitRuleTypes" :key="item.key" :value="item.key">
  13. {{ item.label }}
  14. </a-select-option>
  15. </a-select>
  16. </a-form-model-item>
  17. </div>
  18. <div class="ml-2" style="flex: 1 1 auto" v-if="getRule(idx, idx2).valueType">
  19. <!-- 值 -->
  20. <a-form-model-item class="mb-0">
  21. <a-input v-model="rule.value" :placeholder="$t('network.value')" />
  22. </a-form-model-item>
  23. </div>
  24. <div><a-button @click="addRule('and', idx, idx2)" class="ml-2">And</a-button></div>
  25. <div v-if="allRuleLen > 1"><a-icon type="close" class="ml-2 mr-1 close-icon" @click="delRule(idx, idx2)" /></div>
  26. </div>
  27. <div class="split-and-container" v-if="idx2 !== group.length - 1">
  28. <div class="split-and">And</div>
  29. <div class="left-border" />
  30. </div>
  31. </div>
  32. </div>
  33. <div class="split-or" v-if="idx !== form[ruleFormKey].length - 1">Or</div>
  34. </div>
  35. </template>
  36. <div class="error" v-if="!validate">{{ $t('network.waf.rule_form.error') }}</div>
  37. </div>
  38. </template>
  39. <script>
  40. import { RATE_LIMIT_RULE_TYPES, RATE_LIMIT_RULE_TYPES_MAP } from '../constants'
  41. export default {
  42. name: 'RateLimitRuleForm',
  43. props: {
  44. form: {
  45. type: Object,
  46. required: true,
  47. },
  48. ruleFormKey: {
  49. type: String,
  50. required: true,
  51. default: 'rules',
  52. },
  53. },
  54. data () {
  55. return {
  56. validate: true,
  57. rateLimitRuleTypes: RATE_LIMIT_RULE_TYPES.map(item => {
  58. return {
  59. key: item.type,
  60. label: this.$t(`network.waf.rate_limit_rule_type.${item.type}`),
  61. ...item,
  62. }
  63. }),
  64. }
  65. },
  66. computed: {
  67. allRuleLen () {
  68. return this.form[this.ruleFormKey].reduce((acc, cur) => acc + cur.length, 0)
  69. },
  70. },
  71. methods: {
  72. getRule (idx, idx2) {
  73. const rule = this.form[this.ruleFormKey][idx][idx2]
  74. if (rule.type) {
  75. const target = this.rateLimitRuleTypes.find(item => item.key === rule.type)
  76. return target
  77. }
  78. return {}
  79. },
  80. addRule (type, idx, idx2) {
  81. if (type === 'or') {
  82. this.form[this.ruleFormKey].push([{ type: undefined, value: undefined }])
  83. } else {
  84. const list = []
  85. this.form[this.ruleFormKey][idx].forEach((item, i) => {
  86. list.push(item)
  87. if (i === idx2) {
  88. list.push({ type: undefined, value: undefined })
  89. }
  90. })
  91. this.$set(this.form[this.ruleFormKey], idx, list)
  92. }
  93. },
  94. delRule (idx, idx2) {
  95. if (this.form[this.ruleFormKey][idx].length === 1) {
  96. this.form[this.ruleFormKey].splice(idx, 1)
  97. } else {
  98. this.form[this.ruleFormKey][idx].splice(idx2, 1)
  99. }
  100. },
  101. handleTypeChange (idx, idx2) {
  102. this.$nextTick(() => {
  103. this.form[this.ruleFormKey][idx][idx2].value = undefined
  104. })
  105. },
  106. validateRule () {
  107. const rules = this.form[this.ruleFormKey]
  108. let validate = true
  109. rules.forEach(group => {
  110. group.forEach(rule => {
  111. if (!rule.type) {
  112. validate = false
  113. return
  114. }
  115. if (RATE_LIMIT_RULE_TYPES_MAP[rule.type].valueType) {
  116. if (!rule.value) {
  117. validate = false
  118. }
  119. }
  120. })
  121. })
  122. this.validate = validate
  123. return validate
  124. },
  125. },
  126. }
  127. </script>
  128. <style lang="less" scoped>
  129. .rule-group-container {
  130. background-color: #cacaca50;
  131. padding: 10px;
  132. }
  133. .close-icon {
  134. font-size: 18px;
  135. transform: translateY(3px);
  136. cursor: pointer;
  137. &:hover {
  138. color: var(--antd-wave-shadow-color);
  139. }
  140. }
  141. .split-or {
  142. display: inline-block;
  143. height: 30px;
  144. line-height: 30px;
  145. padding: 0 15px;
  146. // padding: 3px 10px;
  147. background-color: #cacaca50;
  148. border: solid 1px #cacaca80;
  149. margin: 15px 0;
  150. }
  151. .split-and-container {
  152. height: 30px;
  153. position: relative;
  154. .split-and {
  155. display: inline-block;
  156. height: 25px;
  157. line-height: 25px;
  158. padding: 0 10px;
  159. // background-color: #cacaca50;
  160. border: solid 1px #cacaca80;
  161. border-left: none;
  162. position: absolute;
  163. left: 0;
  164. top: 2.5px;
  165. color: #aaa;
  166. }
  167. .left-border {
  168. position: absolute;
  169. width: 1px;
  170. height: 40px;
  171. left: 0;
  172. top: -5px;
  173. font-size: 18px;
  174. border-left: solid 1px #cacaca90;
  175. }
  176. }
  177. .error {
  178. font-size: 14px;
  179. color: red;
  180. }
  181. </style>