| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385 |
- <template>
- <BasicDrawer v-bind="$attrs" @register="registerDrawer" :title="getTitle" width="30%" @ok="handleSubmit" destroyOnClose showFooter>
- <a-form ref="formRef" :label-col="labelCol" :wrapper-col="wrapperCol" :model="router" :rules="validatorRules">
- <a-form-item label="路由ID" name="routerId">
- <a-input v-model:value="router.routerId" placeholder="路由唯一ID"/>
- </a-form-item>
- <a-form-item label="路由名称" name="name">
- <a-input v-model:value="router.name" placeholder="路由名称"/>
- </a-form-item>
- <a-form-item label="路由URI" name="uri">
- <a-input v-model:value="router.uri" placeholder="路由URL"/>
- </a-form-item>
- <a-form-item label="路由状态" name="status">
- <a-switch default-checked :checked-value="1" :un-checked-value="0" v-model:checked="router.status"/>
- </a-form-item>
- <a-form-item name="predicates" label="路由条件">
- <div v-for="(item,index) in router.predicates" >
- <!--当name在noKeyRouter时不需要指定key-->
- <template v-if="noKeyRouter.includes(item.name)">
- <a-divider>{{item.name}}
- <DeleteOutlined size="22" @click="removePredicate(router,index)"/>
- </a-divider>
- <div>
- <template v-for="(tag, tagIndx) in item.args">
- <a-input ref="inputRef2" v-if="tagIndx==currentTagIndex&&index==currentNameIndex" type="text" size="small" :style="{ width: '190px' }" v-model:value="state.inputValue" @change="handleInputChange" @blur="handleInputEditConfirm(item,tag,tagIndx)" @keyup.enter="handleInputEditConfirm(item,tag,tagIndx)"/>
- <a-tag v-else :key="tag" style="margin-bottom:2px" :closable="true" @close="() => removeTag(item,tag)" @click="editTag(item,tag,tagIndx,index)">
- {{ tag }}
- </a-tag>
- </template>
- <a-input ref="inputRef" v-if="state.inputVisible&&index==currentNameIndex" type="text" size="small" :style="{ width: '100px' }" v-model:value="state.inputValue" @change="handleInputChange" @blur="handleInputConfirm(item)" @keyup.enter="handleInputConfirm(item)"/>
- <a-tag v-else style="background: #fff; borderStyle: dashed;margin-bottom:2px" @click="showInput(item,index)">
- <PlusOutlined size="22" />
- 新建{{item.name}}
- </a-tag>
- </div>
- </template>
- <!--当name不在noKeyRouter时需要指定key-->
- <template v-if="!noKeyRouter.includes(item.name)">
- <a-divider>{{item.name}}
- <DeleteOutlined size="22" @click="removePredicate(router,index)"/>
- </a-divider>
- <div>
- <template v-for="(value, key) in item.args">
- <a-row>
- <a-col :span="5" style="margin-top: 8px">
- <span v-if="key=='header'" >Header名称</span>
- <span v-if="key=='regexp'">参数值</span>
- <span v-if="key=='param'">参数名</span>
- <span v-if="key=='name'">参数名</span>
- </a-col>
- <a-col :span="18">
- <a-input :defaultValue="value" placeholder="参数值" style="width: 70%; margin-right: 8px;margin-top: 3px" @change="(e)=>valueChange(e,item.args,key)"/>
- </a-col>
- </a-row>
- </template>
- </div>
- </template>
- </div>
- <p class="btn" style="padding-top: 10px">
- <a-dropdown>
- <template #overlay>
- <a-menu >
- <a-menu-item :key="item.name" v-for="item in tagArray" @click="predicatesHandleMenuClick(item)">{{item.name}}</a-menu-item>
- </a-menu>
- </template>
- <a-button type="dashed" style="margin-left: 8px;width:100%"> 添加路由条件
- <DownOutlined :size="22"/>
- </a-button>
- </a-dropdown>
- </p>
- </a-form-item>
- <a-form-item name="predicates" label="过滤器">
- <div v-for="(item,index) in router.filters">
- <a-divider>{{item.name}}
- <DeleteOutlined size="22" @click="removeFilter(router,index)"/>
- </a-divider>
- <div v-for="(tag, index) in item.args" :key="tag.key">
- <a-input v-model:value="tag.key" placeholder="参数键" style="width: 45%; margin-right: 8px"/>
- <a-input v-model:value="tag.value" placeholder="参数值" style="width: 40%; margin-right: 8px;margin-top: 3px"/>
- <CloseOutlined :size="22" @click="removeFilterParams(item,index)"/>
- </div>
- <a-button type="dashed" style="margin-left:28%;width: 37%;margin-top:5px" size="small" @click="addFilterParams(item)">
- <DownOutlined :size="22"/>
- 添加参数
- </a-button>
- </div>
- <p class="btn" style="padding-top: 10px">
- <a-dropdown>
- <template #overlay>
- <a-menu @click="filterHandleMenuClick">
- <a-menu-item :key="item.key" :name="item.name" v-for="item in filterArray">{{item.name}}</a-menu-item>
- </a-menu>
- </template>
- <a-button type="dashed" style="margin-left: 8px;width:100%"> 添加过滤器
- <DownOutlined />
- </a-button>
- </a-dropdown>
- </p>
- </a-form-item>
- </a-form>
- </BasicDrawer>
- </template>
- <script lang="ts" setup>
- import { ref, computed, unref, useAttrs, reactive,nextTick } from 'vue';
- import {BasicDrawer, useDrawerInner} from '/@/components/Drawer';
- import { saveOrUpdateRoute } from './route.api';
- import {DeleteOutlined} from '@ant-design/icons-vue';
- import {PlusOutlined} from '@ant-design/icons-vue';
- import {CloseOutlined} from '@ant-design/icons-vue';
- import {DownOutlined} from '@ant-design/icons-vue';
- // 声明Emits
- const emit = defineEmits(['register', 'success']);
- const labelCol = reactive({
- xs: { span: 24 },
- sm: { span: 5 },
- });
- const wrapperCol = reactive({
- xs: { span: 24 },
- sm: { span: 16 },
- });
- const attrs = useAttrs();
- const isUpdate = ref(true);
- const inputRef = ref();
- const inputRef2 = ref();
- let state = reactive({
- inputVisible: false,
- inputValue: '',
- });
- const currentNameIndex = ref(0);
- const currentTagIndex = ref(-1);
- const validatorRules = {
- routerId: [
- { required: true, message: 'routerId不能为空', trigger: 'blur' },
- ],
- name: [
- { required: true, message: '路由名称不能为空', trigger: 'blur' },
- ],
- uri: [
- { required: true, message: 'uri不能为空', trigger: 'blur' },
- ],
- };
- const noKeyRouter=["Path","Host","Method","After","Before","Between","RemoteAddr"];
- const filterArray = [/*{ key: 0, name: '熔断器' },*/ { key: 1, name: '限流过滤器' }];
- const tagArray = ref([
- {
- name:'Header',
- args:{
- header:'',
- regexp:''
- }
- },
- {
- name:'Query',
- args:{
- param:'',
- regexp:''
- }
- },
- {
- name:'Method',
- args:[]
- },
- {
- name:'Host',
- args:[]
- },
- {
- name:'Cookie',
- args:{
- name:'',
- regexp:''
- }
- },
- {
- name:'After',
- args:[]
- },
- {
- name:'Before',
- args:[]
- },
- {
- name:'Between',
- args:[]
- },
- {
- name:'RemoteAddr',
- args:[]
- }
- ]);
- const formRef = ref();
- let router = reactive({});
- const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
- isUpdate.value = !!data?.isUpdate;
- setDrawerProps({ confirmLoading: false });
- initRouter();
- if (unref(isUpdate)) {
- router = Object.assign(router, data.record);
- }
- });
- /**
- * 标题
- */
- const getTitle = computed(() => (!unref(isUpdate) ? '新增路由' : '编辑路由'));
- //删除路由条件配置项
- function removeTag(item, removedTag) {
- let tags = item.args.filter(tag => tag !== removedTag);
- item.args = tags;
- }
- //初始化参数
- function initRouter() {
- router = Object.assign(router, {
- id: '',
- routerId: '',
- name: '',
- uri: '',
- status: 1,
- predicates: [],
- filters: [],
- });
- }
- //添加路由选项
- function predicatesHandleMenuClick(e) {
- router.predicates.push({
- args: e.args,
- name: e.name,
- });
- }
- /**
- * 值修改事件
- * @param e
- * @param item
- * @param key
- */
- function valueChange(e,item,key){
- item[key]=e.target.value
- }
- function editTag(item,tag, tagIndex,index) {
- currentNameIndex.value = index;
- currentTagIndex.value = tagIndex;
- state.inputValue=tag;
- nextTick(() => {
- inputRef2.value.focus();
- });
- }
- //显示输入框
- function showInput(item, index) {
- state.inputValue='';
- state.inputVisible = true;
- currentNameIndex.value = index;
- nextTick(() => {
- inputRef.value.focus();
- });
- }
- //路由选项输入框改变事件
- function handleInputChange(e) {
- console.info("change",e)
- console.info("change",e.target.value)
- //state.value = e.target.value;
- //state.tag=true;
- }
- //删除路由条件
- function removePredicate(item, index) {
- item.predicates.splice(index, 1);
- }
- //删除过滤器参数
- function removeFilterParams(item, index) {
- item.args.splice(index, 1);
- }
- //删除过滤器
- function removeFilter(item, index) {
- item.filters.splice(index, 1);
- }
- //添加过滤器参数
- function addFilterParams(item) {
- item.args.push({
- key: 'key' + item.args.length + 1,
- value: '',
- });
- }
- //过滤器添加事件
- function filterHandleMenuClick(e) {
- if (e.key == 0) {
- router.filters.push({
- args: [{
- key: 'name',
- value: 'default',
- }, {
- key: 'fallbackUri',
- value: 'forward:/fallback',
- }],
- name: 'Hystrix',
- title: filterArray[0].name,
- });
- }
- console.info('test', router);
- if (e.key == 1) {
- router.filters.push({
- args: [{
- key: 'key-resolver',
- value: '#{@ipKeyResolver}',
- }, {
- key: 'redis-rate-limiter.replenishRate',
- value: 20,
- }, {
- key: 'redis-rate-limiter.burstCapacity',
- value: 20,
- }],
- name: 'RequestRateLimiter',
- title: filterArray[0].name,
- });
- }
- }
- //输入框确认
- function handleInputConfirm(item) {
- let tags = item.args;
- const inputValue = state.inputValue;
- if (inputValue && tags.indexOf(inputValue) === -1) {
- item.args = [...tags, state.inputValue];
- }
- state.inputVisible=false;
- state.inputValue='';
- currentTagIndex.value = -1;
- currentNameIndex.value = -1;
- }
- //输入框确认
- function handleInputEditConfirm(item, tag, index) {
- const inputValue = state.inputValue;
- if (inputValue) {
- item.args[index] = state.inputValue;
- }
- currentTagIndex.value = -1;
- currentNameIndex.value = -1;
- }
- //关闭弹窗
- function handleCancel() {
- }
- /**
- * 提交
- */
- async function handleSubmit() {
- await formRef.value.validate().then(() => {
- try {
- setDrawerProps({ confirmLoading: true });
- //重新构造表单提交对象,切记不可修改router对象,数组修改为字符串容易造成界面混乱
- let params=Object.assign({},router,{
- predicates:JSON.stringify(router.predicates),
- filters:JSON.stringify(router.filters),
- })
- //提交表单
- saveOrUpdateRoute({ router: params }).then(() => {
- closeDrawer();
- //刷新列表
- emit('success');
- });
- } finally {
- setDrawerProps({ confirmLoading: false });
- }
- });
- }
- </script>
|