74888c3689f7adfb80c84b2dcb7cb3fb565a6639.svn-base 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. <template>
  2. <a-drawer
  3. :title="title"
  4. :maskClosable="true"
  5. width="45%"
  6. placement="right"
  7. v-if="visible"
  8. :closable="true"
  9. @close="handleCancel"
  10. :visible="visible"
  11. style="overflow: auto;padding-bottom: 53px;">
  12. <a-form-model ref="form" :layout="layout" :label-col="labelCol" :wrapper-col="wrapperCol" :model="router">
  13. <a-form-model-item label="路由ID">
  14. <a-input v-model="router.routerId" placeholder="路由唯一ID"/>
  15. </a-form-model-item>
  16. <a-form-model-item label="路由名称">
  17. <a-input v-model="router.name" placeholder="路由名称"/>
  18. </a-form-model-item>
  19. <a-form-model-item label="路由URI">
  20. <a-input v-model="router.uri" placeholder="路由URL"/>
  21. </a-form-model-item>
  22. <a-form-model-item label="路由状态" prop="status">
  23. <a-switch default-checked v-model="router.status"/>
  24. </a-form-model-item>
  25. <a-form-model-item prop="predicates" label="路由条件">
  26. <div v-for="(item,index) in router.predicates">
  27. <a-divider>{{item.name}}
  28. <a-icon type="delete" size="22" @click="removePredicate(router,index)"/>
  29. </a-divider>
  30. <div>
  31. <template v-for="(tag, index) in item.args">
  32. <a-input v-if="index==currentTagIndex" ref="input" type="text" size="small"
  33. :style="{ width: '190px' }"
  34. :value="tag"
  35. @change="handleInputChange" @blur="handleInputEditConfirm(item,tag,index)"
  36. @keyup.enter="handleInputEditConfirm(item,tag,index)"/>
  37. <a-tag v-else :key="tag" :closable="true" @close="() => removeTag(item,tag)" @click="editTag(tag,index)">
  38. {{ tag }}
  39. </a-tag>
  40. </template>
  41. <a-input v-if="inputVisible&&index==currentNameIndex" ref="input" type="text" size="small"
  42. :style="{ width: '100px' }"
  43. :value="inputValue"
  44. @change="handleInputChange" @blur="handleInputConfirm(item)"
  45. @keyup.enter="handleInputConfirm(item)"/>
  46. <a-tag v-else style="background: #fff; borderStyle: dashed;" @click="showInput(item,index)">
  47. <a-icon type="plus"/>
  48. 新建{{item.name}}
  49. </a-tag>
  50. </div>
  51. </div>
  52. <p class="btn" style="padding-top: 10px">
  53. <a-dropdown>
  54. <a-menu slot="overlay" @click="predicatesHandleMenuClick">
  55. <a-menu-item :key="item" v-for="item in tagArray">{{item}}</a-menu-item>
  56. </a-menu>
  57. <a-button type="dashed" style="margin-left: 8px;width:100%"> 添加路由条件
  58. <a-icon type="down"/>
  59. </a-button>
  60. </a-dropdown>
  61. </p>
  62. </a-form-model-item>
  63. <a-form-model-item prop="predicates" label="过滤器">
  64. <div v-for="(item,index) in router.filters">
  65. <a-divider>{{item.name}}
  66. <a-icon type="delete" size="22" @click="removeFilter(router,index)"/>
  67. </a-divider>
  68. <div v-for="(tag, index) in item.args" :key="tag.key">
  69. <a-input v-model="tag.key" placeholder="参数键" style="width: 45%; margin-right: 8px"/>
  70. <a-input v-model="tag.value" placeholder="参数值" style="width: 40%; margin-right: 8px"/>
  71. <a-icon class="dynamic-delete-button" type="minus-circle-o" @click="removeFilterParams(item,index)"/>
  72. </div>
  73. <a-button type="dashed" style="margin-left:28%;width: 30%" size="small" @click="addFilterParams(item)">
  74. <a-icon type="plus"/>
  75. 添加参数
  76. </a-button>
  77. </div>
  78. <p class="btn" style="padding-top: 10px">
  79. <a-dropdown>
  80. <a-menu slot="overlay" @click="filterHandleMenuClick">
  81. <a-menu-item :key="item.key" :name="item.name" v-for="item in filterArray">{{item.name}}</a-menu-item>
  82. </a-menu>
  83. <a-button type="dashed" style="margin-left: 8px;width:100%"> 添加过滤器
  84. <a-icon type="down"/>
  85. </a-button>
  86. </a-dropdown>
  87. </p>
  88. </a-form-model-item>
  89. <a-row :style="{textAlign:'right'}" class="drawer-bootom-button">
  90. <a-button :style="{marginRight: '8px'}" @click="handleCancel">
  91. 关闭
  92. </a-button>
  93. <a-button @click="handleSubmit" type="primary">确定</a-button>
  94. </a-row>
  95. </a-form-model>
  96. </a-drawer>
  97. </template>
  98. <script>
  99. import { postAction } from '@/api/manage'
  100. export default {
  101. name: 'GateWayRouteModal',
  102. components: {},
  103. data() {
  104. return {
  105. layout: 'horizontal',
  106. labelCol: { span: 3 },
  107. wrapperCol: { span: 14 },
  108. currentNameIndex: 0,
  109. currentTagIndex:-1,
  110. predicates: {},
  111. filterArray: [{ key: 0, name: '熔断器' }, { key: 1, name: '限流过滤器' }],
  112. tagArray: ['Path', 'Host', 'Cookie', 'Header', 'Method', 'Query', 'After', 'Before', 'Between', 'RemoteAddr'],
  113. inputVisible: false,
  114. inputValue: '',
  115. url: {
  116. update: '/sys/gatewayRoute/updateAll',
  117. clear: '/sys/gatewayRoute/clearRedis'
  118. },
  119. router: this.getRouter(),
  120. title: '路由编辑',
  121. visible: false,
  122. loading: false
  123. }
  124. },
  125. methods: {
  126. getRouter() {
  127. return {
  128. routerId: '',
  129. name: '',
  130. uri: '',
  131. predicates: [],
  132. filters: []
  133. }
  134. },
  135. show(router) {
  136. if (router) {
  137. router.status=Boolean(router.status)
  138. this.router = router
  139. } else {
  140. this.router = this.getRouter()
  141. this.inputValue=''
  142. }
  143. this.visible = true
  144. this.currentTagIndex=-1
  145. this.currentNameIndex=-1
  146. },
  147. close() {
  148. this.reset()
  149. this.$emit('close')
  150. this.$refs['form'].resetFields()
  151. this.visible = false
  152. },
  153. //删除路由条件配置项
  154. removeTag(item, removedTag) {
  155. const tags = item.args.filter(tag => tag !== removedTag)
  156. item.args = tags
  157. },
  158. //添加路由选项
  159. predicatesHandleMenuClick(e) {
  160. this.router.predicates.push({
  161. args: [],
  162. name: e.key
  163. })
  164. },
  165. editTag(tag,index){
  166. this.currentTagIndex=index
  167. },
  168. //显示输入框
  169. showInput(item, index) {
  170. this.inputVisible = true
  171. this.currentNameIndex = index
  172. },
  173. //路由选项输入框失去焦点事件
  174. handleInputChange(e) {
  175. this.inputValue = e.target.value
  176. },
  177. //删除路由条件
  178. removePredicate(item, index) {
  179. item.predicates.splice(index, 1)
  180. },
  181. //删除过滤器参数
  182. removeFilterParams(item, index) {
  183. item.args.splice(index, 1)
  184. },
  185. //删除过滤器
  186. removeFilter(item, index) {
  187. item.filters.splice(index, 1)
  188. },
  189. //添加过滤器参数
  190. addFilterParams(item) {
  191. item.args.push({
  192. key: 'key' + item.args.length + 1,
  193. value: ''
  194. })
  195. },
  196. //过滤器添加事件
  197. filterHandleMenuClick(e) {
  198. if (e.key == 0) {
  199. this.router.filters.push({
  200. args: [ {
  201. key: 'name',
  202. value: 'default'
  203. },{
  204. key: 'fallbackUri',
  205. value: 'forward:/fallback'
  206. }],
  207. name:'Hystrix',
  208. title: this.filterArray[0].name
  209. })
  210. }
  211. if (e.key == 1) {
  212. this.router.filters.push({
  213. args: [ {
  214. key: 'key-resolver',
  215. value: '#{@ipKeyResolver}'
  216. }, {
  217. key: 'redis-rate-limiter.replenishRate',
  218. value: 20
  219. }, {
  220. key: 'redis-rate-limiter.burstCapacity',
  221. value: 20
  222. }],
  223. name:"RequestRateLimiter",
  224. title: this.filterArray[1].name
  225. })
  226. }
  227. },
  228. //输入框确认
  229. handleInputConfirm(item) {
  230. const inputValue = this.inputValue
  231. let tags = item.args
  232. if (inputValue && tags.indexOf(inputValue) === -1) {
  233. item.args = [...tags, inputValue]
  234. }
  235. console.log(tags)
  236. Object.assign(this, {
  237. tags,
  238. inputVisible: false,
  239. inputValue: ''
  240. })
  241. this.currentTagIndex=-1
  242. },
  243. //输入框确认
  244. handleInputEditConfirm(item,tag,index) {
  245. if(this.inputValue)
  246. {
  247. const inputValue = this.inputValue
  248. item.args[index]=inputValue
  249. }
  250. this.currentTagIndex=-1
  251. },
  252. reset() {
  253. this.expandedKeysss = []
  254. this.checkedKeys = []
  255. this.defaultCheckedKeys = []
  256. this.loading = false
  257. },
  258. //关闭弹窗
  259. handleCancel() {
  260. this.close()
  261. },
  262. //提交路由
  263. handleSubmit() {
  264. let { predicates, filters, ...other } = this.router
  265. let router = other
  266. router.predicates = JSON.stringify(this.router.predicates)
  267. router.filters = JSON.stringify(this.router.filters)
  268. postAction(this.url.update, {
  269. router
  270. }).then(res => {
  271. if (res.success) {
  272. this.close()
  273. this.$emit('ok')
  274. this.$message.success(res.message)
  275. } else {
  276. this.$message.error(res.message)
  277. }
  278. })
  279. }
  280. }
  281. }
  282. </script>
  283. <style lang="less" scoped>
  284. .drawer-bootom-button {
  285. position: absolute;
  286. bottom: 0;
  287. width: 100%;
  288. border-top: 1px solid #e8e8e8;
  289. padding: 10px 16px;
  290. text-align: right;
  291. left: 0;
  292. background: #fff;
  293. border-radius: 0 0 2px 2px;
  294. }
  295. </style>