feat: Add path match type before api path & Modify Login Page

This commit is contained in:
maggieyyy
2024-10-23 11:58:53 +08:00
parent be5abccd81
commit b74f4adfd8
5 changed files with 135 additions and 43 deletions
+13
View File
@@ -272,3 +272,16 @@ a{
stroke: rgba(255, 255, 255, 0.1);
mask-image: radial-gradient(100% 100% at top right, white, transparent);
}
.login-block{
background-color: rgba(255, 255, 255, 0.1);
.login-input{
color:#fff;
background-color: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.1);
&:hover, &:focus, &.ant-input-status-error, &.ant-input-status-error:hover, &.ant-input-status-error:focus-within{
background-color: rgba(255, 255, 255, 0.2);
border: 1px solid rgba(255, 255, 255, 0.2);
}
}
}
@@ -69,6 +69,11 @@ export const API_PROTOCOL = [
{label:'HTTPS',value:'HTTPS'}
]
export const API_PATH_MATCH_RULES = [
{label:'前缀匹配',value:'prefix'},
{label:'全等匹配',value:'full'}
]
export const ALGORITHM_ITEM = [
{label:'HS256',value:'HS256'},
+10 -13
View File
@@ -139,7 +139,7 @@ const Login:FC = ()=> {
</div>
{/* <div className="w-full border-box text-right pr-[40px]"></div> */}
<div className="w-[410px] mx-auto flex-1 flex flex-col items-center justify-center z-[3]" >
<div className="mx-auto flex-1 flex flex-col items-center justify-center z-[3]" >
<div className="mx-auto">
<span className="flex items-center justify-center">
<img
@@ -149,14 +149,10 @@ const Login:FC = ()=> {
</span>
</div>
<section className="block w-[410px] mx-auto mt-[46px] bg-MAIN_BG p-[30px] box-border rounded-[10px] shadow-[0_5px_20px_0_rgba(0,0,0,5%)]">
<section className="block w-[410px] mx-auto mt-[46px] p-[30px] box-border rounded-[10px] shadow-[0_5px_20px_0_rgba(0,0,0,5%)] login-block">
<div className="h-full">
<div>
<div className="flex justify-center items-center">
<span className="text-[24px] text-[#101010]">{$t('登录')}</span>
</div>
<Form onFinish={login} className="w-[350px] pt-[28px]"
<div className="">
<Form onFinish={login} className="w-[350px]"
ref={formRef}>
<Form.Item
className="p-0 bg-transparent rounded border-none"
@@ -164,7 +160,7 @@ const Login:FC = ()=> {
rules={[{ required: true, message: $t('请输入账号') ,whitespace:true }]}
>
<Input
className="w-[350px] h-[40px]"
className="w-[350px] h-[40px] login-input"
placeholder={$t("账号")}
autoComplete="on"
autoFocus
@@ -172,12 +168,12 @@ const Login:FC = ()=> {
</Form.Item>
<Form.Item
className="p-0 bg-transparent rounded border-none"
className="p-0 bg-transparent rounded border-none "
name="password"
rules={[{ required: true, message: $t('请输入密码') }]}
>
<Input.Password
className="w-[350px] h-[40px]"
className="w-[350px] h-[40px] login-input"
placeholder={$t("密码")}
autoComplete="off"
/>
@@ -209,8 +205,9 @@ const Login:FC = ()=> {
</section>
<section className="flex flex-col items-center mt-[46px] text-SECOND_TEXT">
<p className="leading-[28px]">{$t('Version (0)-(1)',[state.version,state.updateDate])}</p>
<p className="leading-[28px]">{$t(state.powered)}</p>
<p className="leading-[28px]">
{$t('Version (0)-(1)',[state.version,state.updateDate])}, {$t(state.powered)}
</p>
<LanguageSetting mode="light"/>
</section>
</div>
@@ -1,4 +1,4 @@
import {App, Button, Form, Input, InputNumber, Row, Spin, Tag} from "antd";
import {App, Button, Form, Input, InputNumber, Row, Select, Space, Spin, Tag} from "antd";
import { MutableRefObject, useEffect, useRef, useState} from "react";
import {BasicResponse, PLACEHOLDER, RESPONSE_TIPS, STATUS_CODE} from "@common/const/const.tsx";
import {useFetch} from "@common/hooks/http.ts";
@@ -17,6 +17,8 @@ import { DrawerWithFooter } from "@common/components/aoplatform/DrawerWithFooter
import AiServiceRouterModelConfig, { AiServiceRouterModelConfigHandle } from "./AiServiceInsideRouterModelConfig";
import { AiProviderDefaultConfig, AiProviderLlmsItems } from "@core/pages/aiSetting/AiSettingList";
import { EditableFormInstance } from "@ant-design/pro-components";
import { validateUrlSlash } from "@common/utils/validate";
import { API_PATH_MATCH_RULES } from "@core/const/system/const";
type AiServiceRouterField = {
name:string
@@ -62,8 +64,11 @@ const AiServiceInsideRouterCreate = () => {
const onFinish = ()=>{
return variablesTableRef?.current?.validateFields().then(()=>{
return form.validateFields().then((formValue)=>{
const {name, path, description, variables, prompt, timeout, retry} = formValue
const body = {name, path: prefixForce ? `${apiPrefix}/${path}`:path , description,timeout, retry,aiPrompt:{variables:variables, prompt:prompt},aiModel:{id:defaultLlm?.id, provider:defaultLlm?.provider, config:defaultLlm?.config}}
const {name, path, description, variables, prompt, timeout, retry,pathMatch} = formValue
const body = {
name,
path: `${prefixForce ? apiPrefix + '/' : ''}${path.trim()}${pathMatch === 'prefix' ? '/*' : ''}`,
description,timeout, retry,aiPrompt:{variables:variables, prompt:prompt},aiModel:{id:defaultLlm?.id, provider:defaultLlm?.provider, config:defaultLlm?.config}}
return fetchData<BasicResponse<null>>('service/ai-router',{method: routeId ? 'PUT' : 'POST',eoBody:(body), eoParams: {service:serviceId,team:teamId, ...(routeId ? {router:routeId}: {})},eoTransformKeys:['aiPrompt','aiModel']}).then(response=>{
const {code,msg} = response
if(code === STATUS_CODE.SUCCESS){
@@ -92,7 +97,20 @@ const AiServiceInsideRouterCreate = () => {
const {code,data,msg} = response
if(code === STATUS_CODE.SUCCESS){
const {path, aiPrompt,aiModel} = data.api
form.setFieldsValue({...data.api,...aiPrompt, path:prefixForce && path?.startsWith(apiPrefix + '/')? path.slice((apiPrefix?.length || 0) + 1) : path })
let newPath = path
let pathMatch = 'full'
if(prefixForce && path?.startsWith(apiPrefix + '/')){
newPath = path.slice((apiPrefix?.length || 0) + 1)
}
if(newPath.endsWith('/*')){
newPath = newPath.slice(0,-2)
pathMatch = 'prefix'
}
form.setFieldsValue({
...data.api,
...aiPrompt,
path:newPath,
pathMatch})
setVariablesTable(aiPrompt.variables as VariableItems[])
setDefaultLlm(prev => ({...prev, provider: aiModel?.provider, id:aiModel?.id, config:aiModel.config}) as (AiProviderDefaultConfig & { config: string; }))
getDefaultModelConfig(aiModel?.provider)
@@ -141,7 +159,8 @@ const AiServiceInsideRouterCreate = () => {
variables:[{key:'Query',value:'',require:true}],
prompt:'{{Query}}',
retry:0,
timeout:300000
timeout:300000,
pathMatch:'prefix'
})
}
return (form.setFieldsValue({}))
@@ -230,15 +249,38 @@ const AiServiceInsideRouterCreate = () => {
<Input className="w-INPUT_NORMAL" placeholder={$t(PLACEHOLDER.input)}/>
</Form.Item>
<Form.Item<AiServiceRouterField>
className="flex-1"
label={$t("请求路径")}
name="path"
rules={[{ required: true,whitespace:true }]}
>
<Input prefix={prefixForce ? `${apiPrefix}/` :"/"} className="w-INPUT_NORMAL"
placeholder={$t(PLACEHOLDER.input)}/>
</Form.Item>
<Form.Item label={$t("请求路径")}>
<Space.Compact block>
<Form.Item
name="pathMatch"
rules={[{ required: true,whitespace:true },
{
validator: validateUrlSlash,
}]}
noStyle
>
<Select placeholder={$t(PLACEHOLDER.select)} options={API_PATH_MATCH_RULES} className="w-[30%] min-w-[100px]"/>
</Form.Item>
<Form.Item<AiServiceRouterField>
name="path"
rules={[{ required: true,whitespace:true },
{
validator: validateUrlSlash,
}]}
noStyle
>
<Input prefix={(prefixForce ? `${apiPrefix}/` :"/")} className="w-INPUT_NORMAL"
placeholder={$t(PLACEHOLDER.input)} onChange={(e)=>{
if((e.target.value as string).endsWith('/*')){
form.setFieldValue('path',e.target.value.slice(0,-2))
form.setFieldValue('pathMatch','prefix')
}
}}/>
</Form.Item>
</Space.Compact>
</Form.Item>
</Row>
<Form.Item<AiServiceRouterField>
@@ -1,10 +1,10 @@
import {App, Button, Col, Form, Input, Row, Select, Spin, Switch} from "antd";
import {App, Button, Col, Form, Input, Row, Select, Space, Spin, Switch} from "antd";
import {forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState} from "react";
import EditableTableWithModal from "@common/components/aoplatform/EditableTableWithModal.tsx";
import styles from "./SystemInsideApi.module.css"
import {BasicResponse, PLACEHOLDER, RESPONSE_TIPS, STATUS_CODE} from "@common/const/const.tsx";
import {useFetch} from "@common/hooks/http.ts";
import { API_PROTOCOL, HTTP_METHOD, MATCH_CONFIG, MatchPositionEnum, MatchTypeEnum } from "../../../const/system/const.tsx";
import { API_PATH_MATCH_RULES, API_PROTOCOL, HTTP_METHOD, MATCH_CONFIG, MatchPositionEnum, MatchTypeEnum } from "../../../const/system/const.tsx";
import { SystemInsideRouterCreateHandle, SystemInsideRouterCreateProps, SystemApiProxyFieldType, SystemInsideApiProxyHandle } from "../../../const/system/type.ts";
import { MatchItem } from "@common/const/type.ts";
import { validateUrlSlash } from "@common/utils/validate.ts";
@@ -31,7 +31,7 @@ const SystemInsideRouterCreate = forwardRef<SystemInsideRouterCreateHandle,Syste
const onFinish = ()=>{
return Promise.all([proxyRef.current?.validate?.(), form.validateFields()]).then(([,formValue])=>{
const body = {...formValue,
path: prefixForce? `${apiPrefix}/${formValue.path.trim()}` : formValue.path.trim(),
path: `${prefixForce ? apiPrefix + '/' : ''}${formValue.path.trim()}${formValue.pathMatch === 'prefix' ? '/*' : ''}`,
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: routeId ? 'PUT' :'POST' ,eoBody:(body), eoParams: {service:serviceId,team:teamId, router:routeId },eoTransformKeys:['matchType','disable']}).then(response=>{
@@ -77,7 +77,24 @@ const SystemInsideRouterCreate = forwardRef<SystemInsideRouterCreateHandle,Syste
const {code,data,msg} = response
if(code === STATUS_CODE.SUCCESS){
const {disable, protocols, path, methods, description, match, proxy} = data.router
form.setFieldsValue({disable, protocols, path:prefixForce && path?.startsWith(apiPrefix + '/')? path.slice((apiPrefix?.length || 0) + 1) : path, methods, description, match,proxy
let newPath = path
let pathMatch = 'full'
if(prefixForce && path?.startsWith(apiPrefix + '/')){
newPath = path.slice((apiPrefix?.length || 0) + 1)
}
if(newPath.endsWith('/*')){
newPath = newPath.slice(0,-2)
pathMatch = 'prefix'
}
form.setFieldsValue({
disable,
protocols,
path:newPath,
pathMatch,
methods,
description,
match,
proxy
})
}else{
message.error(msg || $t(RESPONSE_TIPS.error))
@@ -94,6 +111,7 @@ const SystemInsideRouterCreate = forwardRef<SystemInsideRouterCreateHandle,Syste
form.setFieldValue(['proxy','timeout'],10000)
form.setFieldValue(['proxy','retry'],0)
form.setFieldValue('protocols',['HTTP','HTTPS'])
form.setFieldValue('pathMatch','prefix')
}
return (form.setFieldsValue({}))
}, []);
@@ -157,18 +175,35 @@ const SystemInsideRouterCreate = forwardRef<SystemInsideRouterCreateHandle,Syste
<Select className="w-INPUT_NORMAL" placeholder={$t(PLACEHOLDER.select)} mode="multiple" options={API_PROTOCOL}>
</Select>
</Form.Item>
<Form.Item<SystemApiProxyFieldType>
label={$t("请求路径")}
name="path"
rules={[{ required: true,whitespace:true },
{
validator: validateUrlSlash,
}]}
className={styles['form-input-group']}
>
<Input prefix={(prefixForce ? `${apiPrefix}/` :"/")} className="w-INPUT_NORMAL"
placeholder={$t(PLACEHOLDER.input)}/>
<Form.Item label={$t("请求路径")}>
<Space.Compact block>
<Form.Item
name="pathMatch"
rules={[{ required: true,whitespace:true },
{
validator: validateUrlSlash,
}]}
noStyle
>
<Select placeholder={$t(PLACEHOLDER.select)} options={API_PATH_MATCH_RULES} className="w-[30%] min-w-[100px]"/>
</Form.Item>
<Form.Item<SystemApiProxyFieldType>
name="path"
rules={[{ required: true,whitespace:true },
{
validator: validateUrlSlash,
}]}
noStyle
>
<Input prefix={(prefixForce ? `${apiPrefix}/` :"/")} className="w-INPUT_NORMAL"
placeholder={$t(PLACEHOLDER.input)} onChange={(e)=>{
if((e.target.value as string).endsWith('/*')){
form.setFieldValue('path',e.target.value.slice(0,-2))
form.setFieldValue('pathMatch','prefix')
}
}}/>
</Form.Item>
</Space.Compact>
</Form.Item>
<Form.Item<SystemApiProxyFieldType>