mirror of
https://gh-proxy.org/https://github.com/klinsmaya/SQLBot.git
synced 2026-11-08 01:06:59 +08:00
perf: Model config page
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
"""019_upgrade_model
|
||||
|
||||
Revision ID: dcaecd481715
|
||||
Revises: 863105882eba
|
||||
Create Date: 2025-07-04 14:45:56.927188
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
import sqlmodel.sql.sqltypes
|
||||
from sqlalchemy.dialects import postgresql
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'dcaecd481715'
|
||||
down_revision = '863105882eba'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.drop_index(op.f('ix_ai_model_id'), table_name='ai_model')
|
||||
op.drop_table('ai_model')
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table('ai_model',
|
||||
sa.Column('id', sa.BigInteger(), nullable=False),
|
||||
sa.Column('api_key', sqlmodel.sql.sqltypes.AutoString(length=255), nullable=True),
|
||||
sa.Column('api_domain', sqlmodel.sql.sqltypes.AutoString(length=255), nullable=False),
|
||||
sa.Column('protocol', sa.Integer(), nullable=False),
|
||||
sa.Column('supplier', sa.Integer(), nullable=False),
|
||||
sa.Column('name', sqlmodel.sql.sqltypes.AutoString(length=255), nullable=False),
|
||||
sa.Column('model_type', sa.Integer(), nullable=False),
|
||||
sa.Column('base_model', sqlmodel.sql.sqltypes.AutoString(length=255), nullable=False),
|
||||
sa.Column('default_model', sa.Boolean(), nullable=False),
|
||||
sa.Column('config', sa.Text(), nullable=False),
|
||||
sa.Column('status', sa.Integer(), nullable=False),
|
||||
sa.Column('create_time', sa.BigInteger(), nullable=False),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_index(op.f('ix_ai_model_id'), 'ai_model', ['id'], unique=False)
|
||||
# ### end Alembic commands ###
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_index(op.f('ix_ai_model_id'), table_name='ai_model')
|
||||
op.drop_table('ai_model')
|
||||
|
||||
op.create_table('ai_model',
|
||||
sa.Column('id', sa.BigInteger(), nullable=False),
|
||||
sa.Column('name', sqlmodel.sql.sqltypes.AutoString(length=255), nullable=False),
|
||||
sa.Column('type', sa.Integer(), nullable=False),
|
||||
sa.Column('api_key', sqlmodel.sql.sqltypes.AutoString(length=255), nullable=True),
|
||||
sa.Column('endpoint', sqlmodel.sql.sqltypes.AutoString(length=255), nullable=False),
|
||||
sa.Column('max_context_window', sa.Integer(), nullable=False),
|
||||
sa.Column('temperature', sa.Float(), nullable=False),
|
||||
sa.Column('status', sa.Boolean(), nullable=False),
|
||||
sa.Column('description', sqlmodel.sql.sqltypes.AutoString(length=255), nullable=True),
|
||||
sa.Column('create_time', sa.BigInteger(), nullable=False),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_index(op.f('ix_ai_model_id'), 'ai_model', ['id'], unique=False)
|
||||
# ### end Alembic commands ###
|
||||
@@ -1,9 +1,12 @@
|
||||
import json
|
||||
from pydantic import BaseModel
|
||||
from typing import Optional, Dict, Any, Type
|
||||
from abc import ABC, abstractmethod
|
||||
from langchain_core.language_models import BaseLLM as LangchainBaseLLM
|
||||
from langchain_openai import ChatOpenAI
|
||||
from sqlmodel import Session, select
|
||||
|
||||
from common.core.db import engine
|
||||
from apps.system.models.system_model import AiModelDetail
|
||||
|
||||
|
||||
@@ -11,6 +14,7 @@ from apps.system.models.system_model import AiModelDetail
|
||||
|
||||
class LLMConfig(BaseModel):
|
||||
"""Base configuration class for large language models"""
|
||||
model_id: Optional[int] = None
|
||||
model_type: str # Model type: openai/tongyi/vllm etc.
|
||||
model_name: str # Specific model name
|
||||
api_key: Optional[str] = None
|
||||
@@ -93,7 +97,7 @@ class LLMFactory:
|
||||
|
||||
|
||||
# todo
|
||||
def get_llm_config(aimodel: AiModelDetail) -> LLMConfig:
|
||||
""" def get_llm_config(aimodel: AiModelDetail) -> LLMConfig:
|
||||
config = LLMConfig(
|
||||
model_type="openai",
|
||||
model_name=aimodel.name,
|
||||
@@ -101,4 +105,31 @@ def get_llm_config(aimodel: AiModelDetail) -> LLMConfig:
|
||||
api_base_url=aimodel.endpoint,
|
||||
additional_params={"temperature": aimodel.temperature}
|
||||
)
|
||||
return config
|
||||
return config """
|
||||
|
||||
def get_default_config() -> LLMConfig:
|
||||
with Session(engine) as session:
|
||||
db_model = session.exec(
|
||||
select(AiModelDetail).where(AiModelDetail.default_model == True)
|
||||
).first()
|
||||
if not db_model:
|
||||
raise ValueError("The system default model has not been set")
|
||||
|
||||
additional_params = {}
|
||||
if db_model.config:
|
||||
try:
|
||||
config_raw = json.loads(db_model.config)
|
||||
additional_params = {item["key"]: item["val"] for item in config_raw if "key" in item and "val" in item}
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# 构造 LLMConfig
|
||||
return LLMConfig(
|
||||
model_id=db_model.id,
|
||||
model_type="openai",
|
||||
model_name=db_model.base_model,
|
||||
api_key=db_model.api_key,
|
||||
api_base_url=db_model.api_domain,
|
||||
additional_params=additional_params
|
||||
)
|
||||
|
||||
@@ -11,7 +11,7 @@ from langchain_core.messages import BaseMessage, SystemMessage, HumanMessage, AI
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.orm import load_only
|
||||
|
||||
from apps.ai_model.model_factory import LLMConfig, LLMFactory, get_llm_config
|
||||
from apps.ai_model.model_factory import LLMConfig, LLMFactory, get_default_config
|
||||
from apps.chat.curd.chat import save_question, save_full_sql_message, save_full_sql_message_and_answer, save_sql, \
|
||||
save_error_message, save_sql_exec_data, save_full_chart_message, save_full_chart_message_and_answer, save_chart, \
|
||||
finish_record, save_full_analysis_message_and_answer, save_full_predict_message_and_answer, save_predict_data, \
|
||||
@@ -21,7 +21,6 @@ from apps.datasource.crud.datasource import get_table_schema
|
||||
from apps.datasource.models.datasource import CoreDatasource
|
||||
from apps.db.db import exec_sql
|
||||
from apps.system.crud.user import get_user_info
|
||||
from apps.system.models.system_model import AiModelDetail
|
||||
from common.core.deps import SessionDep, CurrentUser
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
@@ -58,13 +57,6 @@ class LLMService:
|
||||
|
||||
chat_question.engine = ds.type_name if ds.type != 'excel' else 'PostgreSQL'
|
||||
|
||||
# Get available AI model
|
||||
aimodel = self.session.exec(select(AiModelDetail).where(
|
||||
AiModelDetail.status == True,
|
||||
AiModelDetail.api_key.is_not(None)
|
||||
)).first()
|
||||
if not aimodel and aimodel[0]:
|
||||
raise Exception("No available AI model configuration found")
|
||||
|
||||
history_records: List[ChatRecord] = list(
|
||||
map(lambda x: ChatRecord(**x.model_dump()), filter(lambda r: True if r.first_chat != True else False,
|
||||
@@ -79,8 +71,9 @@ class LLMService:
|
||||
|
||||
self.ds = CoreDatasource(**ds.model_dump()) if ds else None
|
||||
self.chat_question = chat_question
|
||||
self.chat_question.ai_modal_id = aimodel[0].id
|
||||
self.config = get_llm_config(aimodel[0])
|
||||
self.config = get_default_config()
|
||||
self.chat_question.ai_modal_id = self.config.model_id
|
||||
|
||||
|
||||
# Create LLM instance through factory
|
||||
llm_instance = LLMFactory.create_llm(self.config)
|
||||
|
||||
@@ -1,90 +1,90 @@
|
||||
from fastapi import APIRouter
|
||||
from sqlmodel import select
|
||||
import json
|
||||
from typing import List, Union
|
||||
from apps.system.schemas.ai_model_schema import AiModelConfigItem, AiModelCreator, AiModelEditor, AiModelGridItem
|
||||
from fastapi import APIRouter, Query
|
||||
from sqlmodel import func, select
|
||||
|
||||
from apps.system.models.system_model import AiModelDetail
|
||||
from apps.system.schemas.system_schema import model_status
|
||||
from common.core.deps import SessionDep
|
||||
from common.core.pagination import Paginator
|
||||
from common.core.schemas import PaginatedResponse, PaginationParams
|
||||
from common.utils.time import get_timestamp
|
||||
|
||||
router = APIRouter(tags=["system/aimodel"], prefix="/system/aimodel")
|
||||
|
||||
|
||||
@router.get("/pager/{pageNum}/{pageSize}", response_model=PaginatedResponse[AiModelDetail])
|
||||
async def pager(
|
||||
@router.get("", response_model=list[AiModelGridItem])
|
||||
async def query(
|
||||
session: SessionDep,
|
||||
pageNum: int,
|
||||
pageSize: int
|
||||
keyword: Union[str, None] = Query(default=None, max_length=255)
|
||||
):
|
||||
pagination = PaginationParams(page=pageNum, size=pageSize)
|
||||
paginator = Paginator(session)
|
||||
filters = {}
|
||||
return await paginator.get_paginated_response(
|
||||
model=AiModelDetail,
|
||||
pagination=pagination,
|
||||
**filters)
|
||||
statement = select(AiModelDetail.id,
|
||||
AiModelDetail.name,
|
||||
AiModelDetail.model_type,
|
||||
AiModelDetail.base_model,
|
||||
AiModelDetail.supplier,
|
||||
AiModelDetail.default_model)
|
||||
if keyword is not None:
|
||||
statement = statement.where(AiModelDetail.name.like(f"%{keyword}%"))
|
||||
|
||||
items = session.exec(statement).all()
|
||||
return items
|
||||
|
||||
|
||||
@router.get("/{id}", response_model=AiModelDetail)
|
||||
@router.get("/{id}", response_model=AiModelEditor)
|
||||
async def get_model_by_id(
|
||||
session: SessionDep,
|
||||
id: int
|
||||
):
|
||||
term = session.get(AiModelDetail, id)
|
||||
return term
|
||||
db_model = session.get(AiModelDetail, id)
|
||||
if not db_model:
|
||||
raise ValueError(f"AiModelDetail with id {id} not found")
|
||||
|
||||
config_list: List[AiModelConfigItem] = []
|
||||
if db_model.config:
|
||||
try:
|
||||
raw = json.loads(db_model.config)
|
||||
config_list = [AiModelConfigItem(**item) for item in raw]
|
||||
except Exception:
|
||||
pass
|
||||
data = AiModelDetail.model_validate(db_model).model_dump(exclude_unset=True)
|
||||
data.pop("config", None)
|
||||
data["config_list"] = config_list
|
||||
return AiModelEditor(**data)
|
||||
|
||||
@router.post("", response_model=AiModelDetail)
|
||||
@router.post("")
|
||||
async def add_model(
|
||||
session: SessionDep,
|
||||
creator: AiModelDetail
|
||||
creator: AiModelCreator
|
||||
):
|
||||
data = AiModelDetail.model_validate(creator)
|
||||
data.create_time = get_timestamp()
|
||||
session.add(data)
|
||||
data = creator.model_dump(exclude_unset=True)
|
||||
data["config"] = json.dumps([item.model_dump(exclude_unset=True) for item in creator.config_list])
|
||||
data.pop("config_list", None)
|
||||
detail = AiModelDetail.model_validate(data)
|
||||
detail.create_time = get_timestamp()
|
||||
count = session.exec(select(func.count(AiModelDetail.id))).one()
|
||||
if count == 0:
|
||||
detail.default_model = True
|
||||
session.add(detail)
|
||||
session.commit()
|
||||
return creator
|
||||
|
||||
|
||||
@router.put("", response_model=AiModelDetail)
|
||||
async def update_terminology(
|
||||
@router.put("")
|
||||
async def update_model(
|
||||
session: SessionDep,
|
||||
model: AiModelDetail
|
||||
editor: AiModelEditor
|
||||
):
|
||||
model.id = int(model.id)
|
||||
term = session.exec(select(AiModelDetail).where(AiModelDetail.id == model.id)).first()
|
||||
update_data = model.model_dump(exclude_unset=True)
|
||||
for field, value in update_data.items():
|
||||
setattr(term, field, value)
|
||||
session.add(term)
|
||||
id = int(editor.id)
|
||||
data = editor.model_dump(exclude_unset=True)
|
||||
data["config"] = json.dumps([item.model_dump(exclude_unset=True) for item in editor.config_list])
|
||||
data.pop("config_list", None)
|
||||
db_model = session.get(AiModelDetail, id)
|
||||
update_data = AiModelDetail.model_validate(data)
|
||||
db_model.sqlmodel_update(update_data)
|
||||
session.add(db_model)
|
||||
session.commit()
|
||||
return model
|
||||
|
||||
|
||||
@router.delete("/{id}", response_model=AiModelDetail)
|
||||
async def delete_terminology(
|
||||
@router.delete("/{id}")
|
||||
async def delete_model(
|
||||
session: SessionDep,
|
||||
id: int
|
||||
):
|
||||
term = session.exec(select(AiModelDetail).where(AiModelDetail.id == id)).first()
|
||||
session.delete(term)
|
||||
item = session.get(AiModelDetail, id)
|
||||
session.delete(item)
|
||||
session.commit()
|
||||
return {
|
||||
"message": f"AiModel with ID {id} deleted successfully."
|
||||
}
|
||||
|
||||
|
||||
@router.patch("/status", response_model=dict)
|
||||
async def status(session: SessionDep, dto: model_status):
|
||||
ids = dto.ids
|
||||
status = dto.status
|
||||
if not ids:
|
||||
return {"message": "ids is empty"}
|
||||
statement = select(AiModelDetail).where(AiModelDetail.id.in_(ids))
|
||||
terms = session.exec(statement).all()
|
||||
for term in terms:
|
||||
term.status = status
|
||||
session.add(term)
|
||||
session.commit()
|
||||
return {"message": f"AiModel with IDs {ids} updated successfully."}
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
|
||||
from sqlmodel import BigInteger, Field, SQLModel
|
||||
|
||||
from sqlmodel import BigInteger, Field, Text, SQLModel
|
||||
from common.core.models import SnowflakeBase
|
||||
|
||||
|
||||
class AiModelBase:
|
||||
supplier: int = Field(nullable=False)
|
||||
name: str = Field(max_length=255, nullable=False)
|
||||
type: int = Field(nullable=False)
|
||||
model_type: int = Field(nullable=False)
|
||||
base_model: str = Field(max_length = 255, nullable=False)
|
||||
default_model: bool = Field(default=False, nullable=False)
|
||||
|
||||
class AiModelDetail(AiModelBase, SnowflakeBase, table=True):
|
||||
class AiModelDetail(SnowflakeBase, AiModelBase, table=True):
|
||||
__tablename__ = "ai_model"
|
||||
api_key: str | None = Field(max_length=255, nullable=True)
|
||||
endpoint: str = Field(max_length=255, nullable=False)
|
||||
max_context_window: int = Field(default=0)
|
||||
temperature: float = Field(default=0.0)
|
||||
status: bool = Field(default=True)
|
||||
description: str | None = Field(max_length=255, nullable=True)
|
||||
api_domain: str = Field(max_length=255, nullable=False)
|
||||
protocol: int = Field(nullable=False, default = 1)
|
||||
config: str = Field(sa_type = Text())
|
||||
status: int = Field(nullable=False, default = 1)
|
||||
create_time: int = Field(default=0, sa_type=BigInteger())
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
from typing import List
|
||||
from pydantic import BaseModel
|
||||
|
||||
from common.core.schemas import BaseCreatorDTO
|
||||
|
||||
class AiModelItem(BaseModel):
|
||||
name: str
|
||||
model_type: int
|
||||
base_model: str
|
||||
supplier: int
|
||||
default_model: bool = False
|
||||
|
||||
class AiModelGridItem(AiModelItem, BaseCreatorDTO):
|
||||
pass
|
||||
|
||||
class AiModelConfigItem(BaseModel):
|
||||
key: str
|
||||
val: object
|
||||
name: str
|
||||
|
||||
class AiModelCreator(AiModelItem):
|
||||
api_domain: str
|
||||
api_key: str
|
||||
config_list: List[AiModelConfigItem]
|
||||
|
||||
class AiModelEditor(AiModelCreator, BaseCreatorDTO):
|
||||
pass
|
||||
@@ -4,7 +4,7 @@ from starlette.middleware.base import BaseHTTPMiddleware
|
||||
from starlette.responses import JSONResponse
|
||||
from starlette.exceptions import HTTPException
|
||||
from starlette.requests import Request
|
||||
|
||||
from common.core.config import settings
|
||||
class ResponseMiddleware(BaseHTTPMiddleware):
|
||||
def __init__(self, app):
|
||||
super().__init__(app)
|
||||
@@ -12,7 +12,7 @@ class ResponseMiddleware(BaseHTTPMiddleware):
|
||||
async def dispatch(self, request, call_next):
|
||||
response = await call_next(request)
|
||||
|
||||
if isinstance(response, JSONResponse):
|
||||
if isinstance(response, JSONResponse) or request.url.path == f"{settings.API_V1_STR}/openapi.json":
|
||||
return response
|
||||
|
||||
if response.headers.get("content-type") == "application/json":
|
||||
|
||||
@@ -46,4 +46,12 @@ class PaginatedResponse(BaseModel, Generic[T]):
|
||||
total: int
|
||||
page: int
|
||||
size: int
|
||||
total_pages: int
|
||||
total_pages: int
|
||||
|
||||
|
||||
class BaseCreatorDTO(BaseModel):
|
||||
id: int
|
||||
class Config:
|
||||
json_encoders = {
|
||||
int: lambda v: str(v) if isinstance(v, int) and v > (2**53 - 1) else v
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
import { request } from '@/utils/request'
|
||||
|
||||
export const modelApi = {
|
||||
pager: (pageNumber: number, pageSize: number) =>
|
||||
request.get(`/system/aimodel/pager/${pageNumber}/${pageSize}`),
|
||||
queryAll: (keyword?: string) =>
|
||||
request.get('/system/aimodel', { params: keyword ? { keyword } : {} }),
|
||||
add: (data: any) => request.post('/system/aimodel', data),
|
||||
edit: (data: any) => request.put('/system/aimodel', data),
|
||||
delete: (id: number) => request.delete(`/system/aimodel/${id}`),
|
||||
|
||||
@@ -4,7 +4,7 @@ export interface SelectOption {
|
||||
}
|
||||
|
||||
export const modelTypeOptions: SelectOption[] = [
|
||||
{ label: 'OpenAI', value: 0 },
|
||||
{ label: '大语言模型', value: 0 },
|
||||
/* { label: 'Anthropic', value: 1 },
|
||||
{ label: 'Baidu', value: 2 },
|
||||
{ label: 'iFLYTEK', value: 3 },
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
import icon_alybl_colorful from '@/assets/model/icon_alybl_colorful.png'
|
||||
import icon_bdyzn_colorful from '@/assets/model/icon_bdyzn_colorful.png'
|
||||
import icon_deepseek_colorful from '@/assets/model/icon_deepseek_colorful.png'
|
||||
type ModelConfig = Record<number, { api_domain: string; model_options: string[] }>
|
||||
|
||||
export const supplierList: Array<{
|
||||
id: number
|
||||
name: string
|
||||
icon: any
|
||||
model_config: ModelConfig
|
||||
}> = [
|
||||
{
|
||||
id: 1,
|
||||
name: '阿里云百炼',
|
||||
icon: icon_alybl_colorful,
|
||||
model_config: {
|
||||
0: {
|
||||
api_domain: 'https://dashscope.aliyuncs.com/compatible-mode/v1',
|
||||
model_options: ['qwen-plus'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '千帆大模型I',
|
||||
icon: icon_bdyzn_colorful,
|
||||
model_config: {
|
||||
0: {
|
||||
api_domain: 'https://qianfan.baidubce.com/v2/',
|
||||
model_options: ['ernie-x1-turbo-32k'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'DeepSeek',
|
||||
icon: icon_deepseek_colorful,
|
||||
model_config: {
|
||||
0: {
|
||||
api_domain: 'https://api.deepseek.com',
|
||||
model_options: ['deepseek-chat'],
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const base_model_options = (supplier_id: number, model_type?: number) => {
|
||||
const supplier = get_supplier(supplier_id)
|
||||
return supplier?.model_config[model_type || 0].model_options
|
||||
}
|
||||
|
||||
export const get_supplier = (supplier_id: number) => {
|
||||
return supplierList.find((item: any) => item.id === supplier_id)
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
<script lang="ts" setup>
|
||||
import azure from '@/assets/model/icon_Azure_OpenAI_colorful.png'
|
||||
import delIcon from '@/assets/svg/icon_delete.svg'
|
||||
import edit from '@/assets/svg/icon_edit_outlined.svg'
|
||||
|
||||
import { get_supplier } from '@/entity/supplier'
|
||||
import { computed } from 'vue'
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
name: string
|
||||
@@ -10,6 +10,7 @@ const props = withDefaults(
|
||||
baseModle: string
|
||||
id?: string
|
||||
isDefault?: boolean
|
||||
supplier?: number
|
||||
}>(),
|
||||
{
|
||||
name: '-',
|
||||
@@ -17,9 +18,15 @@ const props = withDefaults(
|
||||
baseModle: '-',
|
||||
id: '-',
|
||||
isDefault: false,
|
||||
supplier: 0,
|
||||
}
|
||||
)
|
||||
|
||||
const current_supplier = computed(() => {
|
||||
if (!props.supplier) {
|
||||
return null
|
||||
}
|
||||
return get_supplier(props.supplier)
|
||||
})
|
||||
const emits = defineEmits(['edit', 'del'])
|
||||
|
||||
const handleEdit = () => {
|
||||
@@ -27,16 +34,16 @@ const handleEdit = () => {
|
||||
}
|
||||
|
||||
const handleDel = () => {
|
||||
emits('del', props.id)
|
||||
emits('del', { id: props.id, name: props.name, default_model: props.isDefault })
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="card">
|
||||
<div class="name-icon">
|
||||
<img :src="azure" width="32px" height="32px" />
|
||||
<img :src="current_supplier?.icon" width="32px" height="32px" />
|
||||
<span class="name">{{ name }}</span>
|
||||
<span class="default">{{ $t('model.default_model') }}</span>
|
||||
<span v-if="isDefault" class="default">{{ $t('model.default_model') }}</span>
|
||||
</div>
|
||||
<div class="type-value">
|
||||
<span class="type">{{ $t('model.model_type') }}</span>
|
||||
|
||||
@@ -5,7 +5,6 @@ import icon_searchOutline_outlined from '@/assets/svg/icon_search-outline_outlin
|
||||
import icon_admin_outlined from '@/assets/svg/icon_admin_outlined.svg'
|
||||
import icon_add_outlined from '@/assets/svg/icon_add_outlined.svg'
|
||||
import EmptyBackground from '@/views/dashboard/common/EmptyBackground.vue'
|
||||
import icon_Azure_OpenAI_colorful from '@/assets/model/icon_Azure_OpenAI_colorful.png'
|
||||
import icon_done_outlined from '@/assets/svg/icon_done_outlined.svg'
|
||||
import icon_close_outlined from '@/assets/svg/operate/ope-close.svg'
|
||||
import ModelList from './ModelList.vue'
|
||||
@@ -15,12 +14,15 @@ import { modelApi } from '@/api/system'
|
||||
import Card from './Card.vue'
|
||||
import { getModelTypeName } from '@/entity/CommonEntity.ts'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { get_supplier } from '@/entity/supplier'
|
||||
|
||||
interface Model {
|
||||
name: string
|
||||
type: string
|
||||
baseModle: string
|
||||
model_type: string
|
||||
base_model: string
|
||||
id?: string
|
||||
default_model: boolean
|
||||
supplier: number
|
||||
}
|
||||
|
||||
const { t } = useI18n()
|
||||
@@ -32,34 +34,18 @@ const activeStep = ref(0)
|
||||
const activeName = ref('')
|
||||
const modelFormRef = ref()
|
||||
|
||||
const state = reactive({
|
||||
reactive({
|
||||
form: {
|
||||
id: '',
|
||||
name: '',
|
||||
type: 0,
|
||||
model_type: 0,
|
||||
api_key: '',
|
||||
endpoint: '',
|
||||
max_context_window: 0,
|
||||
temperature: 0,
|
||||
status: false,
|
||||
description: '',
|
||||
},
|
||||
pageInfo: {
|
||||
currentPage: 1,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
api_domain: '',
|
||||
},
|
||||
selectedIds: [],
|
||||
})
|
||||
const modelList = shallowRef([] as Model[])
|
||||
const defaultModelList = shallowRef([
|
||||
{
|
||||
img: icon_Azure_OpenAI_colorful,
|
||||
name: '千帆大模型-chinese',
|
||||
},
|
||||
] as (Model & { img: string })[])
|
||||
|
||||
const currentDefaultModel = ref('')
|
||||
const modelListWithSearch = computed(() => {
|
||||
if (!keywords.value) return modelList.value
|
||||
return modelList.value.filter((ele) =>
|
||||
@@ -68,32 +54,37 @@ const modelListWithSearch = computed(() => {
|
||||
})
|
||||
const beforeClose = () => {
|
||||
modelConfigvVisible.value = false
|
||||
ElMessage.success(t('model.set_successfully'))
|
||||
// ElMessageBox.confirm(t('model.system_default_model', { msg: msg}), {
|
||||
// confirmButtonType: 'primary',
|
||||
// tip: t('model.operate_with_caution'),
|
||||
// confirmButtonText: t('datasource.confirm'),
|
||||
// cancelButtonText: t('common.cancel'),
|
||||
// customClass: 'confirm-no_icon',
|
||||
// autofocus: false,
|
||||
// })
|
||||
// ElMessageBox.confirm(t('model.system_default_model', { msg: msg}), {
|
||||
// confirmButtonType: 'danger',
|
||||
// confirmButtonText: t('dashboard.delete'),
|
||||
// cancelButtonText: t('common.cancel'),
|
||||
// customClass: 'confirm-no_icon',
|
||||
// autofocus: false,
|
||||
// })
|
||||
}
|
||||
const defaultModelListWithSearch = computed(() => {
|
||||
if (!defaultModelKeywords.value) return defaultModelList.value
|
||||
return defaultModelList.value.filter((ele) =>
|
||||
ele.name.toLowerCase().includes(defaultModelKeywords.value.toLowerCase())
|
||||
)
|
||||
let tempModelList = modelList.value
|
||||
if (defaultModelKeywords.value) {
|
||||
tempModelList = tempModelList.filter((ele) =>
|
||||
ele.name.toLowerCase().includes(defaultModelKeywords.value.toLowerCase())
|
||||
)
|
||||
}
|
||||
return tempModelList.map((item: any) => {
|
||||
item['supplier_item'] = get_supplier(item.supplier)
|
||||
return item
|
||||
})
|
||||
})
|
||||
|
||||
const handleDefaultModelChange = (item: any) => {
|
||||
currentDefaultModel.value = item.name
|
||||
ElMessageBox.confirm(`是否设置 ${item.name} 为系统默认模型?`, {
|
||||
confirmButtonType: 'primary',
|
||||
tip: '系统默认模型被替换后,智能问数的结果将会受到影响,请谨慎操作。',
|
||||
confirmButtonText: t('datasource.confirm'),
|
||||
cancelButtonText: t('common.cancel'),
|
||||
customClass: 'confirm-no_icon',
|
||||
autofocus: false,
|
||||
callback: (val: string) => {
|
||||
if (val === 'confirm') {
|
||||
modelList.value.forEach((ele: any) => {
|
||||
ele.default_model = ele.id === item.id
|
||||
})
|
||||
ElMessage.success('设置成功')
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const formatKeywords = (item: string) => {
|
||||
@@ -103,47 +94,66 @@ const formatKeywords = (item: string) => {
|
||||
`<span class="isSearch">${defaultModelKeywords.value}</span>`
|
||||
)
|
||||
}
|
||||
|
||||
const handleAddModel = () => {
|
||||
activeStep.value = 0
|
||||
modelConfigvVisible.value = true
|
||||
}
|
||||
const handleEditModel = (id: any) => {
|
||||
activeStep.value = 1
|
||||
modelApi.query(id).then((res: any) => {
|
||||
modelConfigvVisible.value = true
|
||||
nextTick(() => {
|
||||
modelFormRef.value.initForm({ ...res, temperature: res.temperature * 100 })
|
||||
modelFormRef.value.initForm({ ...res })
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const deleteHandler = (id: any) => {
|
||||
ElMessageBox.confirm('Are you sure to delete?', 'Warning', {
|
||||
confirmButtonText: 'OK',
|
||||
cancelButtonText: 'Cancel',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(() => {
|
||||
modelApi.delete(id).then(() => {
|
||||
ElMessage({
|
||||
type: 'success',
|
||||
message: 'Delete completed',
|
||||
const deleteHandler = (item: any) => {
|
||||
if (item.default_model) {
|
||||
ElMessageBox.confirm(`无法删除模型:${item.name}?`, {
|
||||
confirmButtonType: 'primary',
|
||||
tip: '该模型为系统默认模型,请先设置其他模型为系统默认模型,再删除此模型。',
|
||||
showConfirmButton: false,
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '知道了',
|
||||
customClass: 'confirm-no_icon',
|
||||
autofocus: false,
|
||||
callback: (val: string) => {
|
||||
console.log(val)
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
ElMessageBox.confirm(`是否删除模型:${item.name}?`, {
|
||||
confirmButtonType: 'danger',
|
||||
confirmButtonText: '删除',
|
||||
cancelButtonText: '取消',
|
||||
customClass: 'confirm-no_icon',
|
||||
autofocus: false,
|
||||
callback: (value: string) => {
|
||||
if (value === 'confirm') {
|
||||
modelApi.delete(item.id).then(() => {
|
||||
ElMessage({
|
||||
type: 'success',
|
||||
message: '删除成功',
|
||||
})
|
||||
search()
|
||||
})
|
||||
search()
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
ElMessage({
|
||||
type: 'info',
|
||||
message: 'Delete canceled',
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const clickModel = (ele: any) => {
|
||||
activeStep.value = 1
|
||||
activeName.value = ele.name
|
||||
supplierChang(ele)
|
||||
}
|
||||
|
||||
const clickModelSide = (ele: any) => {
|
||||
const supplierChang = (ele: any) => {
|
||||
activeName.value = ele.name
|
||||
nextTick(() => {
|
||||
modelFormRef.value.supplierChang({ ...ele })
|
||||
})
|
||||
}
|
||||
|
||||
const cancel = () => {
|
||||
@@ -155,13 +165,12 @@ const preStep = () => {
|
||||
}
|
||||
|
||||
const saveModel = () => {
|
||||
modelFormRef.value.submit()
|
||||
modelFormRef.value.submitModle()
|
||||
}
|
||||
|
||||
const search = () => {
|
||||
modelApi.pager(state.pageInfo.currentPage, state.pageInfo.pageSize).then((res: any) => {
|
||||
modelList.value = res.items
|
||||
state.pageInfo.total = res.total
|
||||
modelApi.queryAll().then((res: any) => {
|
||||
modelList.value = res
|
||||
})
|
||||
}
|
||||
search()
|
||||
@@ -234,10 +243,10 @@ const submit = (item: any) => {
|
||||
v-for="ele in defaultModelListWithSearch"
|
||||
:key="ele.name"
|
||||
class="popover-item"
|
||||
:class="currentDefaultModel === ele.name && 'isActive'"
|
||||
:class="ele.default_model && 'isActive'"
|
||||
@click="handleDefaultModelChange(ele)"
|
||||
>
|
||||
<img :src="ele.img" width="24px" height="24px" />
|
||||
<img :src="ele.supplier_item.icon" width="24px" height="24px" />
|
||||
<div class="model-name" v-html="formatKeywords(ele.name)"></div>
|
||||
<el-icon size="16" class="done">
|
||||
<icon_done_outlined></icon_done_outlined>
|
||||
@@ -250,7 +259,7 @@ const submit = (item: any) => {
|
||||
</div>
|
||||
</el-popover>
|
||||
|
||||
<el-button type="primary">
|
||||
<el-button type="primary" @click="handleAddModel">
|
||||
<template #icon>
|
||||
<icon_add_outlined></icon_add_outlined>
|
||||
</template>
|
||||
@@ -265,16 +274,18 @@ const submit = (item: any) => {
|
||||
/>
|
||||
|
||||
<div v-else class="card-content">
|
||||
<Card
|
||||
<card
|
||||
v-for="ele in modelListWithSearch"
|
||||
:id="ele.id"
|
||||
:key="ele.id"
|
||||
:name="ele.name"
|
||||
:modle-type="getModelTypeName(ele.type)"
|
||||
:base-modle="ele.baseModle"
|
||||
:supplier="ele.supplier"
|
||||
:modle-type="getModelTypeName(ele['model_type'])"
|
||||
:base-modle="ele['base_model']"
|
||||
:is-default="ele['default_model']"
|
||||
@edit="handleEditModel"
|
||||
@del="deleteHandler"
|
||||
></Card>
|
||||
></card>
|
||||
</div>
|
||||
<el-drawer
|
||||
v-model="modelConfigvVisible"
|
||||
@@ -305,7 +316,7 @@ const submit = (item: any) => {
|
||||
<ModelListSide
|
||||
v-if="activeStep === 1"
|
||||
:active-name="activeName"
|
||||
@click-model="clickModelSide"
|
||||
@click-model="supplierChang"
|
||||
></ModelListSide>
|
||||
<ModelForm
|
||||
v-if="activeStep === 1"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, onMounted, nextTick } from 'vue'
|
||||
import { ref, reactive, onMounted, nextTick, computed } from 'vue'
|
||||
import arrow_down from '@/assets/svg/arrow-down.svg'
|
||||
import dashboard_info from '@/assets/svg/dashboard-info.svg'
|
||||
import icon_edit_outlined from '@/assets/svg/icon_edit_outlined.svg'
|
||||
@@ -7,6 +7,7 @@ import icon_delete from '@/assets/svg/icon_delete.svg'
|
||||
import icon_add_outlined from '@/assets/svg/icon_add_outlined.svg'
|
||||
import ParamsForm from './ParamsForm.vue'
|
||||
import { modelTypeOptions } from '@/entity/CommonEntity.ts'
|
||||
import { base_model_options } from '@/entity/supplier'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
withDefaults(
|
||||
@@ -18,36 +19,37 @@ withDefaults(
|
||||
}
|
||||
)
|
||||
|
||||
interface Options {
|
||||
label: string
|
||||
value: string
|
||||
}
|
||||
|
||||
interface Form {
|
||||
name: string
|
||||
id: string
|
||||
interface ParamsFormData {
|
||||
key?: string
|
||||
val?: string
|
||||
name?: string
|
||||
id?: string
|
||||
}
|
||||
const { t } = useI18n()
|
||||
|
||||
const modelForm = reactive({
|
||||
id: '',
|
||||
supplier: 0,
|
||||
name: '',
|
||||
type: 0,
|
||||
model_type: 0,
|
||||
base_model: '',
|
||||
api_key: '',
|
||||
endpoint: '',
|
||||
max_context_window: 0,
|
||||
temperature: 0,
|
||||
status: false,
|
||||
description: '',
|
||||
api_domain: '',
|
||||
config_list: [],
|
||||
})
|
||||
let isCreate = false
|
||||
const modelRef = ref()
|
||||
const paramsFormRef = ref()
|
||||
const advancedSetting = ref([] as Form[])
|
||||
const modelList = ref([] as Options[])
|
||||
const advancedSetting = ref([] as ParamsFormData[])
|
||||
const paramsFormDrawer = ref(false)
|
||||
const advancedSettingExpand = ref(false)
|
||||
const configExpand = ref(false)
|
||||
|
||||
const modelList = computed(() => {
|
||||
if (!modelForm.supplier) {
|
||||
return []
|
||||
}
|
||||
return base_model_options(modelForm.supplier, modelForm.model_type)
|
||||
})
|
||||
const handleParamsEdite = (ele?: any) => {
|
||||
isCreate = false
|
||||
paramsFormDrawer.value = true
|
||||
@@ -65,19 +67,19 @@ const handleParamsCreate = () => {
|
||||
}
|
||||
|
||||
const handleParamsDel = (item: any) => {
|
||||
advancedSetting.value = advancedSetting.value.filter((ele) => ele.name !== item.name)
|
||||
advancedSetting.value = advancedSetting.value.filter((ele) => ele.key !== item.key)
|
||||
}
|
||||
|
||||
const rules = {
|
||||
type: [
|
||||
model_type: [
|
||||
{
|
||||
required: true,
|
||||
message: 'type',
|
||||
trigger: 'change',
|
||||
},
|
||||
],
|
||||
endpoint: [{ required: true, message: 'endpoint', trigger: 'blur' }],
|
||||
modelName: [{ required: true, message: t('model.the_basic_model_de'), trigger: 'blur' }],
|
||||
api_domain: [{ required: true, message: 'api_domain', trigger: 'blur' }],
|
||||
base_model: [{ required: true, message: t('model.the_basic_model_de'), trigger: 'blur' }],
|
||||
name: [{ required: true, message: t('model.the_basic_model'), trigger: 'blur' }],
|
||||
api_key: [{ required: true, message: 'api_key', trigger: 'blur' }],
|
||||
}
|
||||
@@ -111,11 +113,23 @@ const submit = (item: any) => {
|
||||
const cancel = () => {
|
||||
paramsFormDrawer.value = false
|
||||
}
|
||||
|
||||
const initForm = (item: any) => {
|
||||
const supplierChang = (supplier: any) => {
|
||||
modelForm.supplier = supplier.id
|
||||
const config = supplier.model_config[modelForm.model_type || 0]
|
||||
modelForm.api_domain = config.api_domain
|
||||
if (!modelForm.id) {
|
||||
modelForm.name = supplier.name
|
||||
}
|
||||
}
|
||||
const initForm = (item?: any) => {
|
||||
modelForm.id = ''
|
||||
modelRef.value.clearValidate()
|
||||
Object.assign(modelForm, { ...item })
|
||||
if (item) {
|
||||
Object.assign(modelForm, { ...item })
|
||||
if (item?.config_list?.length) {
|
||||
advancedSetting.value = item.config_list
|
||||
}
|
||||
}
|
||||
}
|
||||
const emits = defineEmits(['submit'])
|
||||
|
||||
@@ -124,8 +138,7 @@ const submitModle = () => {
|
||||
if (res) {
|
||||
emits('submit', {
|
||||
...modelForm,
|
||||
temperature: modelForm.temperature / 100,
|
||||
advancedSetting: [...advancedSetting.value],
|
||||
config_list: [...advancedSetting.value],
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -134,6 +147,7 @@ const submitModle = () => {
|
||||
defineExpose({
|
||||
initForm,
|
||||
submitModle,
|
||||
supplierChang,
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -160,7 +174,7 @@ defineExpose({
|
||||
<el-input v-model="modelForm.name" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="type" :label="t('model.model_type')">
|
||||
<el-select v-model="modelForm.type" style="width: 100%">
|
||||
<el-select v-model="modelForm.model_type" style="width: 100%">
|
||||
<el-option
|
||||
v-for="item in modelTypeOptions"
|
||||
:key="item.value"
|
||||
@@ -174,18 +188,13 @@ defineExpose({
|
||||
><span class="custom-require_danger">{{ t('model.basic_model') }}</span>
|
||||
<span class="enter">{{ t('model.enter_to_add') }}</span>
|
||||
</template>
|
||||
<el-select v-model="modelForm.type" style="width: 100%">
|
||||
<el-option
|
||||
v-for="item in modelList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
<el-select v-model="modelForm['base_model']" style="width: 100%">
|
||||
<el-option v-for="item in modelList" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item prop="endpoint" :label="t('model.api_domain_name')">
|
||||
<el-form-item prop="api_domain" :label="t('model.api_domain_name')">
|
||||
<el-input
|
||||
v-model="modelForm.endpoint"
|
||||
v-model="modelForm.api_domain"
|
||||
:placeholder="
|
||||
$t('datasource.please_enter') + $t('common.empty') + $t('model.api_domain_name')
|
||||
"
|
||||
@@ -202,15 +211,15 @@ defineExpose({
|
||||
</el-form>
|
||||
<div
|
||||
class="advance-setting"
|
||||
:class="advancedSettingExpand && 'expand'"
|
||||
@click="advancedSettingExpand = !advancedSettingExpand"
|
||||
:class="configExpand && 'expand'"
|
||||
@click="configExpand = !configExpand"
|
||||
>
|
||||
{{ t('model.advanced_settings') }}
|
||||
<el-icon size="16">
|
||||
<arrow_down></arrow_down>
|
||||
</el-icon>
|
||||
</div>
|
||||
<div v-if="advancedSettingExpand" class="model-params">
|
||||
<div v-if="configExpand" class="model-params">
|
||||
{{ t('model.model_parameters') }}
|
||||
<span class="add" @click="handleParamsCreate">
|
||||
<el-icon size="16">
|
||||
@@ -220,11 +229,11 @@ defineExpose({
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div v-if="advancedSettingExpand" class="params-table">
|
||||
<div v-if="configExpand" class="params-table">
|
||||
<el-table :data="advancedSetting" style="width: 100%">
|
||||
<el-table-column prop="params" :label="t('model.parameters')" width="280" />
|
||||
<el-table-column prop="key" :label="t('model.parameters')" width="280" />
|
||||
<el-table-column prop="name" :label="t('model.display_name')" width="280" />
|
||||
<el-table-column prop="value" :label="t('model.parameter_value')" />
|
||||
<el-table-column prop="val" :label="t('model.parameter_value')" />
|
||||
<el-table-column
|
||||
fixed="right"
|
||||
width="80"
|
||||
|
||||
@@ -1,30 +1,14 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, shallowRef, computed } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import icon_searchOutline_outlined from '@/assets/svg/icon_search-outline_outlined.svg'
|
||||
import EmptyBackground from '@/views/dashboard/common/EmptyBackground.vue'
|
||||
import icon_Azure_OpenAI_colorful from '@/assets/model/icon_Azure_OpenAI_colorful.png'
|
||||
interface Model {
|
||||
name: string
|
||||
modleType: string
|
||||
baseModle: string
|
||||
img?: string
|
||||
}
|
||||
import { supplierList } from '@/entity/supplier'
|
||||
|
||||
const keywords = ref('')
|
||||
const modelList = shallowRef([
|
||||
{
|
||||
img: icon_Azure_OpenAI_colorful,
|
||||
name: '千帆大模型-chinese',
|
||||
},
|
||||
{
|
||||
img: icon_Azure_OpenAI_colorful,
|
||||
name: '千帆大模-chinese',
|
||||
},
|
||||
] as Model[])
|
||||
|
||||
const modelListWithSearch = computed(() => {
|
||||
if (!keywords.value) return modelList.value
|
||||
return modelList.value.filter((ele) =>
|
||||
ele.name.toLowerCase().includes(keywords.value.toLowerCase())
|
||||
)
|
||||
if (!keywords.value) return supplierList
|
||||
return supplierList.filter((ele) => ele.name.toLowerCase().includes(keywords.value.toLowerCase()))
|
||||
})
|
||||
const emits = defineEmits(['clickModel'])
|
||||
const handleModelClick = (item: any) => {
|
||||
@@ -54,7 +38,7 @@ const handleModelClick = (item: any) => {
|
||||
class="model"
|
||||
@click="handleModelClick(ele)"
|
||||
>
|
||||
<img width="32px" height="32px" :src="ele.img" />
|
||||
<img width="32px" height="32px" :src="ele.icon" />
|
||||
<span class="name">{{ ele.name }}</span>
|
||||
</div>
|
||||
<EmptyBackground
|
||||
@@ -85,7 +69,7 @@ const handleModelClick = (item: any) => {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
height: calc(100% - 40px);
|
||||
|
||||
gap: 16px;
|
||||
.model:nth-child(odd) {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, shallowRef, computed } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import icon_searchOutline_outlined from '@/assets/svg/icon_search-outline_outlined.svg'
|
||||
import EmptyBackground from '@/views/dashboard/common/EmptyBackground.vue'
|
||||
import icon_Azure_OpenAI_colorful from '@/assets/model/icon_Azure_OpenAI_colorful.png'
|
||||
interface Model {
|
||||
name: string
|
||||
modleType: string
|
||||
baseModle: string
|
||||
img?: string
|
||||
}
|
||||
import { supplierList } from '@/entity/supplier'
|
||||
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
activeName: string
|
||||
@@ -18,21 +13,10 @@ withDefaults(
|
||||
}
|
||||
)
|
||||
const keywords = ref('')
|
||||
const modelList = shallowRef([
|
||||
{
|
||||
img: icon_Azure_OpenAI_colorful,
|
||||
name: '千帆大模型-chinese',
|
||||
},
|
||||
{
|
||||
img: icon_Azure_OpenAI_colorful,
|
||||
name: '千帆大模-chinese',
|
||||
},
|
||||
] as Model[])
|
||||
|
||||
const modelListWithSearch = computed(() => {
|
||||
if (!keywords.value) return modelList.value
|
||||
return modelList.value.filter((ele) =>
|
||||
ele.name.toLowerCase().includes(keywords.value.toLowerCase())
|
||||
)
|
||||
if (!keywords.value) return supplierList
|
||||
return supplierList.filter((ele) => ele.name.toLowerCase().includes(keywords.value.toLowerCase()))
|
||||
})
|
||||
const emits = defineEmits(['clickModel'])
|
||||
const handleModelClick = (item: any) => {
|
||||
@@ -62,7 +46,7 @@ const handleModelClick = (item: any) => {
|
||||
:class="activeName === ele.name && 'isActive'"
|
||||
@click="handleModelClick(ele)"
|
||||
>
|
||||
<img width="32px" height="32px" :src="ele.img" />
|
||||
<img width="32px" height="32px" :src="ele.icon" />
|
||||
<span class="name">{{ ele.name }}</span>
|
||||
</div>
|
||||
<EmptyBackground
|
||||
|
||||
@@ -6,9 +6,8 @@ const { t } = useI18n()
|
||||
const paramsRef = ref()
|
||||
const paramsForm = reactive({
|
||||
name: '',
|
||||
params: '',
|
||||
value: null,
|
||||
type: 0,
|
||||
key: '',
|
||||
val: '',
|
||||
})
|
||||
|
||||
const rules = {
|
||||
@@ -19,14 +18,14 @@ const rules = {
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
params: [
|
||||
key: [
|
||||
{
|
||||
required: true,
|
||||
message: t('datasource.please_enter') + t('common.empty') + t('model.parameters'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
value: [
|
||||
val: [
|
||||
{
|
||||
required: true,
|
||||
message: t('datasource.please_enter') + t('common.empty') + t('model.parameter_value'),
|
||||
@@ -66,9 +65,9 @@ defineExpose({
|
||||
:model="paramsForm"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-form-item prop="params" :label="$t('model.parameters')">
|
||||
<el-form-item prop="key" :label="$t('model.parameters')">
|
||||
<el-input
|
||||
v-model="paramsForm.params"
|
||||
v-model="paramsForm.key"
|
||||
:placeholder="$t('datasource.please_enter') + $t('common.empty') + $t('model.parameters')"
|
||||
/>
|
||||
</el-form-item>
|
||||
@@ -80,9 +79,9 @@ defineExpose({
|
||||
"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item prop="value" :label="$t('model.parameter_value')">
|
||||
<el-form-item prop="val" :label="$t('model.parameter_value')">
|
||||
<el-input
|
||||
v-model="paramsForm.value"
|
||||
v-model="paramsForm.val"
|
||||
:placeholder="
|
||||
$t('datasource.please_enter') + $t('common.empty') + $t('model.parameter_value')
|
||||
"
|
||||
|
||||
@@ -265,10 +265,10 @@ const onFormClose = () => {
|
||||
}
|
||||
|
||||
const search = () => {
|
||||
modelApi.pager(state.pageInfo.currentPage, state.pageInfo.pageSize).then((res: any) => {
|
||||
/* modelApi.pager(state.pageInfo.currentPage, state.pageInfo.pageSize).then((res: any) => {
|
||||
state.tableData = res.items
|
||||
state.pageInfo.total = res.total
|
||||
})
|
||||
}) */
|
||||
}
|
||||
const addTerm = () => {
|
||||
const param: any = {
|
||||
|
||||
Reference in New Issue
Block a user