Merge pull request #25 from maggieyyy/main

fix: router match bugs
This commit is contained in:
maggieyyy
2024-09-02 13:43:54 +08:00
committed by GitHub
12 changed files with 77 additions and 45 deletions
@@ -15,6 +15,7 @@ export interface ConfigField<T> {
renderText?: (value: unknown, record: T) => string;
required?: boolean;
ellipsis?:boolean
unRender?:(form:FormInstance)=>boolean
}
interface EditableTableWithModalProps<T> {
@@ -39,6 +40,7 @@ const EditableTableWithModal = <T extends { _id?: string }>({
const [configurations, setConfigurations] = useState<T[]>(value ||[]);
const [editingConfig, setEditingConfig] = useState<T | null>(null);
const {state} = useGlobalContext()
const [formsValue, setFormsValue] = useState<FormInstance<unknown>>()
const showModal = (config?: T) => {
if (config) {
@@ -111,18 +113,23 @@ const EditableTableWithModal = <T extends { _id?: string }>({
],[state.language, disabled, configFields])
const formItems = configFields.map(({ title,key, component, required }) => {
return (
<Form.Item
label={$t(title as string)}
name={key as string}
rules={[{ required}]}
>
{component}
</Form.Item>
)
const formItems = useMemo(()=>{
return configFields.map(({ title,key, component, required,unRender }) => {
return (
unRender && unRender(formsValue) ? null :
<Form.Item
label={$t(title as string)}
name={key as string}
rules={[{ required}]}
>
{component}
</Form.Item>
)
})
}
);
,[formsValue])
return (
<>
@@ -142,6 +149,9 @@ const EditableTableWithModal = <T extends { _id?: string }>({
<WithPermission access=""><Form form={form} name="editableTableWithModal"
layout="vertical"
scrollToFirstError
onFieldsChange={(()=>{
setFormsValue(form.getFieldsValue())
})}
// labelCol={{ span: 7 }}
// wrapperCol={{ span: 17}}
autoComplete="off">
@@ -195,7 +195,7 @@ export const PublishApprovalModalContent = forwardRef<PublishApprovalModalHandle
</Form.Item>
</>
}
<Row className="mt-mbase pb-[8px] h-[32px] font-bold" ><span >{$t('API 列表')}</span></Row>
<Row className="mt-mbase pb-[8px] h-[32px] font-bold" ><span >{$t('路由列表')}</span></Row>
<Row className="mb-mbase ">
<Table
columns={translatedRouteColumns}
@@ -215,9 +215,9 @@ export const ApprovalStatusColorClass = {
export const ApprovalRouteColumns = [
{
title:('请求方式'),
dataIndex:'method',
dataIndex:'methods',
ellipsis:true,
renderText:(value)=>value.join(',')
render:(value)=>value?.join(', ')
},
{
title:('路径'),
@@ -1,2 +1,3 @@
{
"K4758140d": "路由列表"
}
@@ -1,5 +1,3 @@
{
"K71753476": "是否放行",
"K597435c5": "监控",
"Kde9d6e8e": "开启拦截后,网关会拦截所有该路径的请求,相当于防火墙禁用了特定路径的访问。"
"K4758140d": "路由列表"
}
@@ -72,8 +72,8 @@ export const SYSTEM_I18NEXT_FOR_ENUM = {
export const HTTP_METHOD = ['GET','POST','PUT','DELETE','PATCH','HEAD']
export const API_PROTOCOL = [
{label:'HTTP',value:'http'},
{label:'HTTPS',value:'https'}
{label:'HTTP',value:'HTTP'},
{label:'HTTPS',value:'HTTPS'}
]
@@ -259,6 +259,7 @@ export const MATCH_CONFIG:ConfigField<MatchItem>[] = [
}, {
title:('参数值'),
key: 'pattern',
unRender:(formValue)=>{return formValue?.matchType === 'NULL' || formValue?.matchType==='EXIST' || formValue?.matchType === 'UNEXIST'},
component: <Input className="w-INPUT_NORMAL"/>,
renderText: (value: string) => {
return value
@@ -278,17 +279,17 @@ export const SYSTEM_API_TABLE_COLUMNS: PageProColumns<SystemApiTableListItem>[]
title:('协议'),
dataIndex: 'protocols',
ellipsis:true,
renderText:(value)=>value?.join(',')
renderText:(value)=>value?.join(', ')
},
{
title:('方法'),
dataIndex: 'method',
dataIndex: 'methods',
ellipsis:true,
renderText:(value)=>value?.join(',')
renderText:(value)=>value?.join(', ')
},
{
title:'是否放行',
dataIndex:'isDisabled',
dataIndex:'disable',
ellipsis:true,
filters: true,
onFilter: true,
@@ -95,7 +95,7 @@ export type SystemApiProxyFieldType = {
id:string;
description?:string;
path:string;
method:string[];
methods:string[];
match:MatchItem[]
isDisable?: boolean;
service?:string;
@@ -295,6 +295,7 @@ export type SystemInsideApiProxyProps = {
teamId:string
initProxyValue?:SystemApiProxyType
value?:SystemApiProxyType
type:'add'|'edit'
onChange?: (newConfigItems: SystemApiProxyType) => void; // 当配置项变化时,外部传入的回调函数
}
@@ -9,7 +9,7 @@ import { $t } from "@common/locales";
import { useGlobalContext } from "@common/contexts/GlobalStateContext";
const SystemInsideApiProxy = forwardRef<SystemInsideApiProxyHandle,SystemInsideApiProxyProps>((props,ref)=>{
const {value, onChange, className,initProxyValue} = props
const {value, onChange, className,initProxyValue,type} = props
const {state} = useGlobalContext()
const [form] = Form.useForm();
@@ -51,7 +51,7 @@ const SystemInsideApiProxy = forwardRef<SystemInsideApiProxyHandle,SystemInsideA
label={$t("转发上游路径")}
name={'path'}
>
<Input prefix="/" className="w-INPUT_NORMAL" placeholder={$t(PLACEHOLDER.input)}/>
<Input prefix={type === 'edit' ? null :"/"} className="w-INPUT_NORMAL" placeholder={$t(PLACEHOLDER.input)}/>
</Form.Item>
<Form.Item<SystemApiProxyType>
@@ -25,7 +25,7 @@ const SystemInsideRouterCreate = forwardRef<SystemInsideRouterCreateHandle,Syste
const onFinish = ()=>{
return Promise.all([proxyRef.current?.validate?.(), form.validateFields()]).then(([,formValue])=>{
const body = {...formValue,path:formValue.path.trim(),proxy:{...formValue.proxy,path:formValue.proxy.path ? (formValue.proxy.path.startsWith('/')? formValue.proxy.path: '/'+ formValue.proxy.path) : undefined}}
return fetchData<BasicResponse<null>>('service/router',{method: type === 'add' ? 'POST' : 'PUT',eoBody:(body), eoParams: {service:serviceId,team:teamId, ...(type === 'edit' ? {router:entity?.id}: {})},eoTransformKeys:['matchType','isDisable']}).then(response=>{
return fetchData<BasicResponse<null>>('service/router',{method: type === 'add' ? 'POST' : 'PUT',eoBody:(body), eoParams: {service:serviceId,team:teamId, ...(type === 'edit' ? {router:entity?.id}: {})},eoTransformKeys:['matchType','disable']}).then(response=>{
const {code,msg} = response
if(code === STATUS_CODE.SUCCESS){
message.success(msg || $t(RESPONSE_TIPS.success))
@@ -63,11 +63,11 @@ const SystemInsideRouterCreate = forwardRef<SystemInsideRouterCreateHandle,Syste
const getRouterConfig = ()=>{
setLoading(true)
fetchData<BasicResponse<{router:SystemApiProxyFieldType}>>('service/router/detail',{method:'GET',eoParams:{service:serviceId,team:teamId, router:entity!.id}}).then(response=>{
fetchData<BasicResponse<{router:SystemApiProxyFieldType}>>('service/router/detail',{method:'GET',eoParams:{service:serviceId,team:teamId, router:entity!.id}, eoTransformKeys:['create_time','update_time','match_type','upstream_id','opt_type']}).then(response=>{
const {code,data,msg} = response
if(code === STATUS_CODE.SUCCESS){
const {isDisable, protocols, path, method, description, match, proxy} = data.router
form.setFieldsValue({isDisable, protocols, path, method, description, match,proxy
const {disable, protocols, path, methods, description, match, proxy} = data.router
form.setFieldsValue({disable, protocols, path, methods, description, match,proxy
})
}else{
message.error(msg || $t(RESPONSE_TIPS.error))
@@ -85,7 +85,7 @@ const SystemInsideRouterCreate = forwardRef<SystemInsideRouterCreateHandle,Syste
form.setFieldValue('prefix',apiPrefix)
form.setFieldValue(['proxy','timeout'],10000)
form.setFieldValue(['proxy','retry'],0)
form.setFieldValue('protocols',['http','https'])
form.setFieldValue('protocols',['HTTP','HTTPS'])
break;
case 'copy':
// form.setFieldsValue({
@@ -134,7 +134,7 @@ const SystemInsideRouterCreate = forwardRef<SystemInsideRouterCreateHandle,Syste
<Row className="mb-btnybase" > <Col ><span className="font-bold mr-[13px]">{$t('API 基础信息')}</span></Col></Row>
<Form.Item<SystemApiProxyFieldType>
label={$t("拦截该接口的请求")}
name="isDisable"
name="disable"
extra={$t('开启拦截后,网关会拦截所有该路径的请求,相当于防火墙禁用了特定路径的访问。')}
>
<Switch />
@@ -158,13 +158,13 @@ const SystemInsideRouterCreate = forwardRef<SystemInsideRouterCreateHandle,Syste
}]}
className={styles['form-input-group']}
>
<Input prefix={(prefixForce ? `${apiPrefix}/` :"/")} className="w-INPUT_NORMAL"
<Input prefix={type === 'edit' ? null :(prefixForce ? `${apiPrefix}/` :"/")} className="w-INPUT_NORMAL"
placeholder={$t(PLACEHOLDER.input)}/>
</Form.Item>
<Form.Item<SystemApiProxyFieldType>
label={$t("请求方式")}
name="method"
name="methods"
rules={[{ required: true }]}
>
<Select className="w-INPUT_NORMAL" placeholder={$t(PLACEHOLDER.select)} mode="multiple" options={HTTP_METHOD.map((method:string)=>{
@@ -197,7 +197,7 @@ const SystemInsideRouterCreate = forwardRef<SystemInsideRouterCreateHandle,Syste
className="mb-0 bg-transparent border-none p-0"
name="proxy"
>
<SystemInsideApiProxy serviceId={serviceId!} teamId={teamId!} ref={proxyRef} />
<SystemInsideApiProxy type={type} serviceId={serviceId!} teamId={teamId!} ref={proxyRef} />
</Form.Item>
</>}
</div>
@@ -46,7 +46,7 @@ const SystemInsideRouterList:FC = ()=>{
});
}
return fetchData<BasicResponse<{routers:SystemApiTableListItem}>>('service/routers',{method:'GET',eoParams:{service:serviceId,team:teamId, keyword:searchWord},eoTransformKeys:['request_path','create_time','update_time','is_disable']}).then(response=>{
return fetchData<BasicResponse<{routers:SystemApiTableListItem}>>('service/routers',{method:'GET',eoParams:{service:serviceId,team:teamId, keyword:searchWord},eoTransformKeys:['request_path','create_time','update_time','disable']}).then(response=>{
const {code,data,msg} = response
if(code === STATUS_CODE.SUCCESS){
setTableListDataSource(data.routers)
@@ -171,7 +171,7 @@ const SystemInsideRouterList:FC = ()=>{
x.valueEnum = tmpValueEnum
}
if(x.filters &&((x.dataIndex as string[])?.indexOf('isDisabled') !== -1) ){
if(x.filters &&((x.dataIndex as string[])?.indexOf('disable') !== -1) ){
x.valueEnum = {
true:{text:<span className="text-status_fail">{$t('拦截')}</span>},
false:{text:<span className="text-status_success">{$t('放行')}</span>}
@@ -201,7 +201,7 @@ const SystemInsideRouterList:FC = ()=>{
request={()=>getRoutesList()}
dataSource={tableListDataSource}
addNewBtnTitle={$t('添加路由')}
searchPlaceholder={$t('输入名称、URL 查找路由')}
searchPlaceholder={$t('输入 URL 查找路由')}
onAddNewBtnClick={()=>{openDrawer('add')}}
addNewBtnAccess="team.service.router.add"
tableClickAccess="team.service.router.view"
@@ -1,10 +1,13 @@
import { App, Table } from "antd";
import { App, Table, Tooltip } from "antd";
import { SYSTEM_PUBLISH_ONLINE_COLUMNS } from "../../../const/system/const";
import { useEffect, useState } from "react";
import { useEffect, useMemo, useState } from "react";
import { useFetch } from "@common/hooks/http";
import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from "@common/const/const";
import { BasicResponse, RESPONSE_TIPS, STATUS_CODE, STATUS_COLOR } from "@common/const/const";
import { EntityItem } from "@common/const/type";
import { LoadingOutlined } from "@ant-design/icons";
import { $t } from "@common/locales";
import { useGlobalContext } from "@common/contexts/GlobalStateContext";
type SystemInsidePublishOnlineProps = {
serviceId:string
@@ -23,6 +26,7 @@ export default function SystemInsidePublishOnline(props:SystemInsidePublishOnlin
const [dataSource, setDataSource] = useState<[]>()
const {fetchData} = useFetch()
const [isStopped, setIsStopped] = useState(false);
const { state } = useGlobalContext()
const getOnlineStatus = ()=>{
fetchData<BasicResponse<{publishStatusList:SystemInsidePublishOnlineItems[]}>>('service/publish/status',{method:'GET',eoParams:{service:serviceId,team:teamId, id}, eoTransformKeys:['publish_status_list']}).then(response=>{
@@ -55,11 +59,28 @@ export default function SystemInsidePublishOnline(props:SystemInsidePublishOnlin
};
}, [isStopped]);
const translatedPublishColumns = useMemo(()=>SYSTEM_PUBLISH_ONLINE_COLUMNS.map((x)=>{
if(x.dataIndex === 'status'){
return {...x,title:$t(x.title),
render:(_:unknown,entity:SystemInsidePublishOnlineItems)=>{
switch(entity.status){
case 'done':
return <span className={STATUS_COLOR[entity.status as keyof typeof STATUS_COLOR]}>{$t('成功')}</span>
case 'error':
return <Tooltip title={entity.error || $t('上线失败')}><span className={`${STATUS_COLOR[entity.status as keyof typeof STATUS_COLOR]} truncate block`}>{$t('失败')} {entity.error}</span></Tooltip>
default:
return <LoadingOutlined className="text-theme" spin />
}
}}
}
}),[state.language])
return (
<Table
className="min-h-[100px] h-full"
bordered={true}
columns={[...SYSTEM_PUBLISH_ONLINE_COLUMNS]}
columns={translatedPublishColumns}
size="small"
rowKey="id"
dataSource={dataSource}
@@ -17,7 +17,7 @@ const ServiceHubApiDocument = ({service}:{service:ServiceDetailType})=>{
useEffect(()=>{
if(!service) return
setServiceName(service?.name)
setApiDocument(service.apiDoc)
setApiDocument(service?.apiDoc)
},[service])
useEffect(() => {
@@ -41,7 +41,7 @@ const ServiceHubApiDocument = ({service}:{service:ServiceDetailType})=>{
</div>
</div>
<Drawer
{/* <Drawer
title={serviceName}
maskClosable={false}
width="100%" placement="right" onClose={onClose} open={apiTestDrawOpen}
@@ -51,7 +51,7 @@ const ServiceHubApiDocument = ({service}:{service:ServiceDetailType})=>{
closeIcon={false}
>
<ApiTestGroup apiInfoList={apiDocs} selectedApiId={selectedTestApi}/>
</Drawer>
</Drawer> */}
</>
)
}