mirror of
https://gh-proxy.org/https://github.com/klinsmaya/SQLBot.git
synced 2026-11-08 01:06:59 +08:00
@@ -29,10 +29,12 @@ router = APIRouter(tags=["SQL Examples"], prefix="/system/data-training")
|
||||
@router.get("/page/{current_page}/{page_size}", summary=f"{PLACEHOLDER_PREFIX}get_dt_page")
|
||||
@require_permissions(permission=SqlbotPermission(role=['ws_admin']))
|
||||
async def pager(session: SessionDep, current_user: CurrentUser, current_page: int, page_size: int,
|
||||
question: Optional[str] = Query(None, description="搜索问题(可选)")):
|
||||
question: Optional[str] = Query(None, description="搜索问题(可选)"),
|
||||
ds_list: Optional[list[int]] = Query(None, description="数据集ID集合(可选)"),
|
||||
adv_list: Optional[list[int]] = Query(None, description="高级应用ID集合(可选)")):
|
||||
current_page, page_size, total_count, total_pages, _list = page_data_training(session, current_page, page_size,
|
||||
question,
|
||||
current_user.oid)
|
||||
current_user.oid, ds_list, adv_list)
|
||||
|
||||
return {
|
||||
"current_page": current_page,
|
||||
|
||||
@@ -37,12 +37,32 @@ def get_data_training_base_query(oid: int, name: Optional[str] = None):
|
||||
|
||||
|
||||
def build_data_training_query(session: SessionDep, oid: int, name: Optional[str] = None,
|
||||
paginate: bool = True, current_page: int = 1, page_size: int = 10):
|
||||
paginate: bool = True, current_page: int = 1, page_size: int = 10,
|
||||
ds_list: Optional[list[int]] = None, adv_list: Optional[list[int]] = None):
|
||||
"""
|
||||
构建数据训练查询的通用方法
|
||||
"""
|
||||
parent_ids_subquery = get_data_training_base_query(oid, name)
|
||||
|
||||
# 添加数据源/高级应用筛选条件(ds_list 与 adv_list 为或的关系)
|
||||
ds_filter_condition = None
|
||||
adv_filter_condition = None
|
||||
|
||||
if ds_list is not None and len(ds_list) > 0:
|
||||
ds_filter_condition = DataTraining.datasource.in_(ds_list)
|
||||
|
||||
if adv_list is not None and len(adv_list) > 0:
|
||||
adv_filter_condition = DataTraining.advanced_application.in_(adv_list)
|
||||
|
||||
if ds_filter_condition is not None and adv_filter_condition is not None:
|
||||
parent_ids_subquery = parent_ids_subquery.where(
|
||||
or_(ds_filter_condition, adv_filter_condition)
|
||||
)
|
||||
elif ds_filter_condition is not None:
|
||||
parent_ids_subquery = parent_ids_subquery.where(ds_filter_condition)
|
||||
elif adv_filter_condition is not None:
|
||||
parent_ids_subquery = parent_ids_subquery.where(adv_filter_condition)
|
||||
|
||||
# 计算总数
|
||||
count_stmt = select(func.count()).select_from(parent_ids_subquery.subquery())
|
||||
total_count = session.execute(count_stmt).scalar()
|
||||
@@ -121,12 +141,13 @@ def execute_data_training_query(session: SessionDep, stmt) -> List[DataTrainingI
|
||||
|
||||
|
||||
def page_data_training(session: SessionDep, current_page: int = 1, page_size: int = 10,
|
||||
name: Optional[str] = None, oid: Optional[int] = 1):
|
||||
name: Optional[str] = None, oid: Optional[int] = 1, ds_list: Optional[list[int]] = None,
|
||||
adv_list: Optional[list[int]] = None):
|
||||
"""
|
||||
分页查询数据训练(原方法保持不变)
|
||||
"""
|
||||
stmt, total_count, total_pages, current_page, page_size = build_data_training_query(
|
||||
session, oid, name, True, current_page, page_size
|
||||
session, oid, name, True, current_page, page_size, ds_list, adv_list
|
||||
)
|
||||
_list = execute_data_training_query(session, stmt)
|
||||
|
||||
@@ -305,7 +326,8 @@ def batch_create_training(session: SessionDep, info_list: List[DataTrainingInfo]
|
||||
|
||||
assistant_name_to_id = {}
|
||||
|
||||
assistant_stmt = select(AssistantModel.id, AssistantModel.name).where(and_(AssistantModel.type == 1, AssistantModel.oid == oid))
|
||||
assistant_stmt = select(AssistantModel.id, AssistantModel.name).where(
|
||||
and_(AssistantModel.type == 1, AssistantModel.oid == oid))
|
||||
assistant_result = session.execute(assistant_stmt).all()
|
||||
for assistant in assistant_result:
|
||||
assistant_name_to_id[assistant.name.strip()] = assistant.id
|
||||
|
||||
@@ -29,9 +29,10 @@ router = APIRouter(tags=["Terminology"], prefix="/system/terminology")
|
||||
@require_permissions(permission=SqlbotPermission(role=['ws_admin']))
|
||||
async def pager(session: SessionDep, current_user: CurrentUser, current_page: int, page_size: int,
|
||||
word: Optional[str] = Query(None, description="搜索术语(可选)"),
|
||||
dslist: Optional[list[int]] = Query(None, description="数据集ID集合(可选)")):
|
||||
ds_list: Optional[list[int]] = Query(None, description="数据集ID集合(可选)"),
|
||||
adv_list: Optional[list[int]] = Query(None, description="高级应用ID集合(可选)")):
|
||||
current_page, page_size, total_count, total_pages, _list = page_terminology(session, current_page, page_size, word,
|
||||
current_user.oid, dslist)
|
||||
current_user.oid, ds_list, adv_list)
|
||||
|
||||
return {
|
||||
"current_page": current_page,
|
||||
|
||||
@@ -57,30 +57,42 @@ def get_terminology_base_query(oid: int, name: Optional[str] = None):
|
||||
|
||||
def build_terminology_query(session: SessionDep, oid: int, name: Optional[str] = None,
|
||||
paginate: bool = True, current_page: int = 1, page_size: int = 10,
|
||||
dslist: Optional[list[int]] = None):
|
||||
ds_list: Optional[list[int]] = None, adv_list: Optional[list[int]] = None):
|
||||
"""
|
||||
构建术语查询的通用方法
|
||||
"""
|
||||
parent_ids_subquery, child = get_terminology_base_query(oid, name)
|
||||
|
||||
# 添加数据源筛选条件
|
||||
if dslist is not None and len(dslist) > 0:
|
||||
# 添加数据源/高级应用筛选条件(ds_list 与 adv_list 为或的关系)
|
||||
ds_filter_condition = None
|
||||
adv_filter_condition = None
|
||||
|
||||
if ds_list is not None and len(ds_list) > 0:
|
||||
datasource_conditions = []
|
||||
# datasource_ids 与 dslist 中的任一元素有交集
|
||||
for ds_id in dslist:
|
||||
# 使用 JSONB 包含操作符,但需要确保类型正确
|
||||
for ds_id in ds_list:
|
||||
datasource_conditions.append(
|
||||
Terminology.datasource_ids.contains([ds_id])
|
||||
)
|
||||
|
||||
# datasource_ids 为空数组
|
||||
empty_array_condition = Terminology.datasource_ids == []
|
||||
|
||||
ds_filter_condition = or_(
|
||||
*datasource_conditions,
|
||||
empty_array_condition
|
||||
Terminology.specific_ds == False,
|
||||
and_(
|
||||
Terminology.specific_ds == True,
|
||||
*datasource_conditions
|
||||
)
|
||||
)
|
||||
|
||||
if adv_list is not None and len(adv_list) > 0:
|
||||
adv_filter_condition = Terminology.advanced_application.in_(adv_list)
|
||||
|
||||
if ds_filter_condition is not None and adv_filter_condition is not None:
|
||||
parent_ids_subquery = parent_ids_subquery.where(
|
||||
or_(ds_filter_condition, adv_filter_condition)
|
||||
)
|
||||
elif ds_filter_condition is not None:
|
||||
parent_ids_subquery = parent_ids_subquery.where(ds_filter_condition)
|
||||
elif adv_filter_condition is not None:
|
||||
parent_ids_subquery = parent_ids_subquery.where(adv_filter_condition)
|
||||
|
||||
# 计算总数
|
||||
count_stmt = select(func.count()).select_from(parent_ids_subquery.subquery())
|
||||
@@ -205,12 +217,13 @@ def execute_terminology_query(session: SessionDep, stmt) -> List[TerminologyInfo
|
||||
|
||||
|
||||
def page_terminology(session: SessionDep, current_page: int = 1, page_size: int = 10,
|
||||
name: Optional[str] = None, oid: Optional[int] = 1, dslist: Optional[list[int]] = None):
|
||||
name: Optional[str] = None, oid: Optional[int] = 1, ds_list: Optional[list[int]] = None,
|
||||
adv_list: Optional[list[int]] = None):
|
||||
"""
|
||||
分页查询术语(原方法保持不变)
|
||||
"""
|
||||
stmt, total_count, total_pages, current_page, page_size = build_terminology_query(
|
||||
session, oid, name, True, current_page, page_size, dslist
|
||||
session, oid, name, True, current_page, page_size, ds_list, adv_list
|
||||
)
|
||||
_list = execute_terminology_query(session, stmt)
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ dependencies = [
|
||||
"pyyaml (>=6.0.2,<7.0.0)",
|
||||
"fastapi-mcp (>=0.3.4,<0.4.0)",
|
||||
"tabulate>=0.9.0",
|
||||
"sqlbot-xpack>=0.0.5.32,<0.0.6.0",
|
||||
"sqlbot-xpack>=0.0.5.33,<0.0.6.0",
|
||||
"fastapi-cache2>=0.2.2",
|
||||
"sqlparse>=0.5.3",
|
||||
"redis>=6.2.0",
|
||||
|
||||
@@ -2,7 +2,7 @@ import { request } from '@/utils/request'
|
||||
|
||||
export const promptApi = {
|
||||
getList: (pageNum: any, pageSize: any, type: any, params: any) =>
|
||||
request.get(`/system/custom_prompt/${type}/page/${pageNum}/${pageSize}${params}`),
|
||||
request.post(`/system/custom_prompt/${type}/page/${pageNum}/${pageSize}`, params),
|
||||
updateEmbedded: (data: any) => request.put(`/system/custom_prompt`, data),
|
||||
deleteEmbedded: (params: any) => request.delete('/system/custom_prompt', { data: params }),
|
||||
getOne: (id: any) => request.get(`/system/custom_prompt/${id}`),
|
||||
|
||||
@@ -2,9 +2,7 @@ import { request } from '@/utils/request'
|
||||
|
||||
export const trainingApi = {
|
||||
getList: (pageNum: any, pageSize: any, params: any) =>
|
||||
request.get(`/system/data-training/page/${pageNum}/${pageSize}`, {
|
||||
params,
|
||||
}),
|
||||
request.get(`/system/data-training/page/${pageNum}/${pageSize}${params}`),
|
||||
updateEmbedded: (data: any) => request.put('/system/data-training', data),
|
||||
deleteEmbedded: (params: any) => request.delete('/system/data-training', { data: params }),
|
||||
getOne: (id: any) => request.get(`/system/data-training/${id}`),
|
||||
|
||||
@@ -46,6 +46,7 @@ onMounted(() => {
|
||||
})
|
||||
getAdvancedApplicationList().then((res: any) => {
|
||||
adv_options.value = res || []
|
||||
filterOption.value[1].option = [...adv_options.value]
|
||||
})
|
||||
search()
|
||||
})
|
||||
@@ -381,11 +382,19 @@ const filterOption = ref<any[]>([
|
||||
{
|
||||
type: 'select',
|
||||
option: [],
|
||||
field: 'dslist',
|
||||
field: 'ds_list',
|
||||
title: t('ds.title'),
|
||||
operate: 'in',
|
||||
property: { placeholder: t('common.empty') + t('ds.title') },
|
||||
},
|
||||
{
|
||||
type: 'select',
|
||||
option: [],
|
||||
field: 'adv_list',
|
||||
title: t('embedded.advanced_application'),
|
||||
operate: 'in',
|
||||
property: { placeholder: t('common.empty') + t('embedded.advanced_application') },
|
||||
},
|
||||
])
|
||||
|
||||
const fillFilterText = () => {
|
||||
|
||||
@@ -55,6 +55,7 @@ onMounted(() => {
|
||||
})
|
||||
getAdvancedApplicationList().then((res: any) => {
|
||||
adv_options.value = res || []
|
||||
filterOption.value[1].option = [...adv_options.value]
|
||||
})
|
||||
search()
|
||||
})
|
||||
@@ -389,31 +390,36 @@ const typeChange = (val: any) => {
|
||||
}
|
||||
|
||||
const configParams = () => {
|
||||
let str = ''
|
||||
let _data: any = {}
|
||||
if (keywords.value) {
|
||||
str += `name=${keywords.value}`
|
||||
_data['name'] = keywords.value
|
||||
}
|
||||
|
||||
console.log(state.conditions)
|
||||
|
||||
state.conditions.forEach((ele: any) => {
|
||||
ele.value.forEach((itx: any) => {
|
||||
str += str ? `_${itx}` : `${ele.field}=${itx}`
|
||||
})
|
||||
_data[ele.field] = ele.value
|
||||
})
|
||||
|
||||
if (str.length) {
|
||||
str = `?${str}`
|
||||
}
|
||||
return str
|
||||
return _data
|
||||
}
|
||||
const filterOption = ref<any[]>([
|
||||
{
|
||||
type: 'select',
|
||||
option: [],
|
||||
field: 'dslist',
|
||||
field: 'ds_list',
|
||||
title: t('ds.title'),
|
||||
operate: 'in',
|
||||
property: { placeholder: t('common.empty') + t('ds.title') },
|
||||
},
|
||||
{
|
||||
type: 'select',
|
||||
option: [],
|
||||
field: 'adv_list',
|
||||
title: t('embedded.advanced_application'),
|
||||
operate: 'in',
|
||||
property: { placeholder: t('common.empty') + t('embedded.advanced_application') },
|
||||
},
|
||||
])
|
||||
|
||||
const fillFilterText = () => {
|
||||
|
||||
@@ -15,6 +15,9 @@ import { useI18n } from 'vue-i18n'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import { getAdvancedApplicationList } from '@/api/embedded.ts'
|
||||
import Uploader from '@/views/system/excel-upload/Uploader.vue'
|
||||
import { convertFilterText, FilterText } from '@/components/filter-text'
|
||||
import { DrawerMain } from '@/components/drawer-main'
|
||||
import iconFilter from '@/assets/svg/icon-filter_outlined.svg'
|
||||
|
||||
interface Form {
|
||||
id?: string | null
|
||||
@@ -37,6 +40,13 @@ const selectable = () => {
|
||||
return true
|
||||
}
|
||||
onMounted(() => {
|
||||
datasourceApi.list().then((res) => {
|
||||
filterOption.value[0].option = [...res]
|
||||
})
|
||||
getAdvancedApplicationList().then((res: any) => {
|
||||
adv_options.value = res || []
|
||||
filterOption.value[1].option = [...adv_options.value]
|
||||
})
|
||||
search()
|
||||
})
|
||||
|
||||
@@ -210,6 +220,81 @@ const handleToggleRowSelection = (check: boolean = true) => {
|
||||
isIndeterminate.value = !(i === 0 || i === arr.length)
|
||||
}
|
||||
|
||||
const drawerMainRef = ref()
|
||||
|
||||
const filterOption = ref<any[]>([
|
||||
{
|
||||
type: 'select',
|
||||
option: [],
|
||||
field: 'ds_list',
|
||||
title: t('ds.title'),
|
||||
operate: 'in',
|
||||
property: { placeholder: t('common.empty') + t('ds.title') },
|
||||
},
|
||||
{
|
||||
type: 'select',
|
||||
option: [],
|
||||
field: 'adv_list',
|
||||
title: t('embedded.advanced_application'),
|
||||
operate: 'in',
|
||||
property: { placeholder: t('common.empty') + t('embedded.advanced_application') },
|
||||
},
|
||||
])
|
||||
|
||||
const state = reactive<any>({
|
||||
conditions: [],
|
||||
filterTexts: [],
|
||||
})
|
||||
|
||||
const searchCondition = (conditions: any) => {
|
||||
state.conditions = conditions
|
||||
fillFilterText()
|
||||
search()
|
||||
drawerMainClose()
|
||||
}
|
||||
const clearFilter = (params?: number) => {
|
||||
let index = params ? params : 0
|
||||
if (isNaN(index)) {
|
||||
state.filterTexts = []
|
||||
} else {
|
||||
state.filterTexts.splice(index, 1)
|
||||
}
|
||||
drawerMainRef.value.clearFilter(index)
|
||||
}
|
||||
const drawerMainOpen = async () => {
|
||||
drawerMainRef.value.init()
|
||||
}
|
||||
|
||||
const drawerMainClose = () => {
|
||||
drawerMainRef.value.close()
|
||||
}
|
||||
|
||||
const fillFilterText = () => {
|
||||
const textArray = state.conditions?.length
|
||||
? convertFilterText(state.conditions, filterOption.value)
|
||||
: []
|
||||
state.filterTexts = [...textArray]
|
||||
Object.assign(state.filterTexts, textArray)
|
||||
}
|
||||
|
||||
const configParams = () => {
|
||||
let str = ''
|
||||
if (keywords.value) {
|
||||
str += `question=${keywords.value}`
|
||||
}
|
||||
|
||||
state.conditions.forEach((ele: any) => {
|
||||
ele.value.forEach((itx: any) => {
|
||||
str += str ? `&${ele.field}=${itx}` : `${ele.field}=${itx}`
|
||||
})
|
||||
})
|
||||
|
||||
if (str.length) {
|
||||
str = `?${str}`
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
const search = ($event: any = {}) => {
|
||||
if ($event?.isComposing) {
|
||||
return
|
||||
@@ -217,11 +302,7 @@ const search = ($event: any = {}) => {
|
||||
searchLoading.value = true
|
||||
oldKeywords.value = keywords.value
|
||||
trainingApi
|
||||
.getList(
|
||||
pageInfo.currentPage,
|
||||
pageInfo.pageSize,
|
||||
keywords.value ? { question: keywords.value } : {}
|
||||
)
|
||||
.getList(pageInfo.currentPage, pageInfo.pageSize, configParams())
|
||||
.then((res) => {
|
||||
toggleRowLoading.value = true
|
||||
fieldList.value = res.data
|
||||
@@ -383,6 +464,12 @@ const onRowFormClose = () => {
|
||||
:template-name="`${t('training.data_training')}.xlsx`"
|
||||
@upload-finished="search"
|
||||
/>
|
||||
<el-button class="no-margin" secondary @click="drawerMainOpen">
|
||||
<template #icon>
|
||||
<iconFilter></iconFilter>
|
||||
</template>
|
||||
{{ $t('user.filter') }}
|
||||
</el-button>
|
||||
<el-button class="no-margin" type="primary" @click="editHandler(null)">
|
||||
<template #icon>
|
||||
<icon_add_outlined></icon_add_outlined>
|
||||
@@ -396,6 +483,11 @@ const onRowFormClose = () => {
|
||||
class="table-content"
|
||||
:class="multipleSelectionAll?.length ? 'show-pagination_height' : ''"
|
||||
>
|
||||
<filter-text
|
||||
:total="pageInfo.total"
|
||||
:filter-texts="state.filterTexts"
|
||||
@clear-filter="clearFilter"
|
||||
/>
|
||||
<div class="preview-or-schema">
|
||||
<el-table
|
||||
ref="multipleTableRef"
|
||||
@@ -647,6 +739,11 @@ const onRowFormClose = () => {
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-drawer>
|
||||
<drawer-main
|
||||
ref="drawerMainRef"
|
||||
:filter-options="filterOption"
|
||||
@trigger-filter="searchCondition"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
Reference in New Issue
Block a user