feat:Recommended questions support user configuration. (#487)

This commit is contained in:
王嘉豪
2025-11-25 13:54:40 +08:00
committed by GitHub
parent 85b19fb40b
commit 9d494345b2
13 changed files with 264 additions and 4 deletions
+7
View File
@@ -0,0 +1,7 @@
import { request } from '@/utils/request'
export const recommendedApi = {
get_recommended_problem: (dsId: any) =>
request.get(`/recommended_problem/get_datasource_recommended/${dsId}`),
save_recommended_problem: (data: any) => request.post(`/recommended_problem/save`, data),
}
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1763971949643" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8822" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M0 0v1024h1024V0H0z m907.636364 907.636364H116.363636V116.363636h791.272728v791.272728z" p-id="8823"></path><path d="M449.163636 572.509091h116.363637v109.381818h-116.363637zM509.672727 351.418182c25.6 2.327273 37.236364 11.636364 39.563637 32.581818 0 13.963636-11.636364 27.927273-34.909091 37.236364-44.218182 20.945455-62.836364 55.854545-58.181818 109.381818H558.545455c-4.654545-20.945455 11.636364-41.890909 46.545454-60.509091 39.563636-23.272727 62.836364-53.527273 62.836364-88.436364-4.654545-72.145455-53.527273-109.381818-151.272728-114.036363-100.072727 4.654545-151.272727 46.545455-158.254545 128h116.363636c-2.327273-27.927273 9.309091-41.890909 34.909091-44.218182z" p-id="8824"></path></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

+6
View File
@@ -308,6 +308,12 @@
}
},
"datasource": {
"recommended_problem_configuration": "Recommended Problem Configuration",
"problem_generation_method": "Problem Generation Method",
"ai_automatic_generation": "AI Automatic Generation",
"user_defined": "User Defined",
"question_tips": "Please enter recommended questions",
"add_question": "Add Question",
"data_source_yet": "No data source yet",
"search_by_name": "Search by Name",
"search": "Search",
+6
View File
@@ -308,6 +308,12 @@
}
},
"datasource": {
"recommended_problem_configuration": "추천 문제 구성",
"problem_generation_method": "문제 생성 방식",
"ai_automatic_generation": "AI 자동 생성",
"user_defined": "사용자 정의",
"question_tips": "추천 문제를 입력해 주세요",
"add_question": "문제 추가",
"data_source_yet": "데이터 소스가 없습니다",
"search_by_name": "이름으로 검색",
"search": "검색",
+6
View File
@@ -308,6 +308,12 @@
}
},
"datasource": {
"recommended_problem_configuration": "推荐问题配置",
"problem_generation_method": "问题生成方式",
"ai_automatic_generation": "AI 自动生成",
"user_defined": "用户自定义",
"question_tips": "请输入推荐问题",
"add_question": "添加问题",
"data_source_yet": "暂无数据源",
"search_by_name": "通过名称搜索",
"search": "搜索",
+19 -1
View File
@@ -7,6 +7,7 @@ import { computed, ref, unref } from 'vue'
import { ClickOutside as vClickOutside } from 'element-plus-secondary'
import { dsTypeWithImg } from './js/ds-type'
import edit from '@/assets/svg/icon_edit_outlined.svg'
import icon_recommended_problem from '@/assets/svg/icon_recommended_problem.svg'
import { datasourceApi } from '@/api/datasource.ts'
const props = withDefaults(
@@ -27,7 +28,14 @@ const props = withDefaults(
}
)
const emits = defineEmits(['edit', 'del', 'question', 'dataTableDetail', 'showTable'])
const emits = defineEmits([
'edit',
'del',
'question',
'dataTableDetail',
'showTable',
'recommendation',
])
const icon = computed(() => {
return (dsTypeWithImg.find((ele) => props.type === ele.type) || {}).img
})
@@ -35,6 +43,10 @@ const handleEdit = () => {
emits('edit')
}
const handleRecommendation = () => {
emits('recommendation')
}
const handleDel = () => {
emits('del')
}
@@ -124,6 +136,12 @@ const onClickOutside = () => {
</el-icon>
{{ $t('datasource.edit') }}
</div>
<div class="item" style="display: none" @click.stop="handleRecommendation">
<el-icon size="16">
<icon_recommended_problem></icon_recommended_problem>
</el-icon>
{{ $t('datasource.recommended_problem_configuration') }}
</div>
<div class="item" @click.stop="handleDel">
<el-icon size="16">
<delIcon></delIcon>
+13 -2
View File
@@ -17,8 +17,11 @@ import { dsTypeWithImg } from './js/ds-type'
import { useI18n } from 'vue-i18n'
import { useUserStore } from '@/stores/user'
import { chatApi } from '@/api/chat'
import RecommendedProblemConfigDialog from '@/views/ds/RecommendedProblemConfigDialog.vue'
const userStore = useUserStore()
interface Datasource {
const recommendedProblemConfigRef = ref()
export interface Datasource {
name: string
num: string
type_name: string
@@ -26,6 +29,7 @@ interface Datasource {
img: string
description: string
id?: string
recommended_config?: string
}
const router = useRouter()
@@ -77,6 +81,10 @@ const handleEditDatasource = (res: any) => {
addDrawerRef.value.handleEditDatasource(res)
}
const handleRecommendation = (res: Datasource) => {
recommendedProblemConfigRef.value?.init(res)
}
const handleQuestion = async (id: string) => {
try {
await chatApi.checkLLMModel()
@@ -295,6 +303,7 @@ useEmitt({
:description="ele.description"
@question="handleQuestion"
@edit="handleEditDatasource(ele)"
@recommendation="handleRecommendation(ele)"
@del="deleteHandler(ele)"
@data-table-detail="dataTableDetail(ele)"
></Card>
@@ -317,7 +326,9 @@ useEmitt({
</el-button>
</div>
</template>
<RecommendedProblemConfigDialog
ref="recommendedProblemConfigRef"
></RecommendedProblemConfigDialog>
<AddDrawer ref="addDrawerRef" @search="search"></AddDrawer>
</div>
<DataTable
@@ -0,0 +1,130 @@
<script setup lang="ts">
import { reactive, ref } from 'vue'
import { recommendedApi } from '@/api/recommendedApi.ts'
interface RecommendedProblem {
id?: number
question: string
datasourceId?: any | undefined
sort: number
}
const dialogShow = ref(false)
const state = reactive({
dsId: null,
recommended: {
recommendedConfig: 1,
recommendedProblemList: [] as RecommendedProblem[],
},
})
const init = (params: any) => {
dialogShow.value = true
state.recommended.recommendedConfig = params.recommendedConfig
state.dsId = params.id
recommendedApi.get_recommended_problem(state.dsId).then((res: any) => {
state.recommended.recommendedProblemList = res
})
}
const addRecommendedProblem = (): void => {
state.recommended.recommendedProblemList.push({
question: '',
datasourceId: state.dsId,
} as RecommendedProblem)
}
const closeDialog = () => {
dialogShow.value = false
state.recommended = {
recommendedConfig: 1,
recommendedProblemList: [] as RecommendedProblem[],
}
}
const save = () => {
recommendedApi.save_recommended_problem(state.recommended.recommendedProblemList)
closeDialog()
}
const form = ref<any>({
id: null,
question: '',
sort: null,
})
defineExpose({
init,
})
</script>
<template>
<el-dialog
v-model="dialogShow"
:title="$t('datasource.recommended_problem_configuration')"
width="600"
modal-class="add-question_dialog"
destroy-on-close
:close-on-click-modal="false"
@before-closed="closeDialog"
>
<el-form-item :label="$t('datasource.problem_generation_method')" prop="mode">
<el-radio-group v-model="form.mode">
<el-radio value="1">{{ $t('datasource.ai_automatic_generation') }}</el-radio>
<el-radio value="2">{{ $t('datasource.user_defined') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
v-for="(recommendedItem, index) in state.recommended.recommendedProblemList"
:key="index"
prop="mode"
>
<el-input
v-model="recommendedItem.question"
clearable
:placeholder="$t('datasource.question_tips')"
>
</el-input>
</el-form-item>
<div>
<el-button text @click="addRecommendedProblem">
{{ $t('datasource.add_question') }}</el-button
>
</div>
<div style="display: flex; justify-content: flex-end; margin-top: 20px">
<el-button secondary @click="closeDialog">{{ $t('common.cancel') }}</el-button>
<el-button type="primary" @click="save">{{ $t('model.add') }}</el-button>
</div>
</el-dialog>
</template>
<style scoped lang="less">
.add-question_dialog {
.ed-input-group__append {
background-color: #fff;
padding: 0 12px;
}
.value-input {
.ed-input-group__append {
color: #1f2329;
position: relative;
&:hover {
&::after {
content: '';
position: absolute;
left: -1px;
top: 0;
width: calc(100% - 1px);
height: calc(100% - 2px);
background: var(--ed-color-primary-1a, #1cba901a);
border: 1px solid var(--ed-color-primary);
border-bottom-right-radius: 6px;
border-top-right-radius: 6px;
pointer-events: none;
}
}
}
}
}
</style>