feat: 对话日志
This commit is contained in:
parent
ce093d7071
commit
c62a12c237
@ -39,10 +39,33 @@ const delChatLog: (
|
|||||||
chat_id: string,
|
chat_id: string,
|
||||||
loading?: Ref<boolean>
|
loading?: Ref<boolean>
|
||||||
) => Promise<Result<boolean>> = (applicaiton_id, chat_id, loading) => {
|
) => Promise<Result<boolean>> = (applicaiton_id, chat_id, loading) => {
|
||||||
return del(`${prefix}/${applicaiton_id}/document/${chat_id}`, {}, loading)
|
return del(`${prefix}/${applicaiton_id}/chat/${chat_id}`, undefined, {}, loading)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日志记录
|
||||||
|
* @param 参数
|
||||||
|
* application_id, chart_id
|
||||||
|
* page {
|
||||||
|
"current_page": "string",
|
||||||
|
"page_size": "string",
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
const getChatRecordLog: (
|
||||||
|
applicaiton_id: String,
|
||||||
|
chart_id: String,
|
||||||
|
page: pageRequest,
|
||||||
|
loading?: Ref<boolean>
|
||||||
|
) => Promise<Result<any>> = (applicaiton_id, chart_id, page, loading) => {
|
||||||
|
return get(
|
||||||
|
`${prefix}/${applicaiton_id}/chat/${chart_id}/chat_record/${page.current_page}/${page.page_size}`,
|
||||||
|
undefined,
|
||||||
|
loading
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
getChatLog,
|
getChatLog,
|
||||||
delChatLog
|
delChatLog,
|
||||||
|
getChatRecordLog
|
||||||
}
|
}
|
||||||
|
|||||||
@ -111,7 +111,7 @@ const deleteModel: (model_id: string, loading?: Ref<boolean>) => Promise<Result<
|
|||||||
model_id,
|
model_id,
|
||||||
loading
|
loading
|
||||||
) => {
|
) => {
|
||||||
return del(`${prefix}/${model_id}`, {}, loading)
|
return del(`${prefix}/${model_id}`, undefined, {}, loading)
|
||||||
}
|
}
|
||||||
export default {
|
export default {
|
||||||
getModel,
|
getModel,
|
||||||
|
|||||||
@ -37,9 +37,15 @@ const getParagraph: (
|
|||||||
const delParagraph: (
|
const delParagraph: (
|
||||||
dataset_id: string,
|
dataset_id: string,
|
||||||
document_id: string,
|
document_id: string,
|
||||||
paragraph_id: string
|
paragraph_id: string,
|
||||||
) => Promise<Result<boolean>> = (dataset_id, document_id, paragraph_id) => {
|
loading?: Ref<boolean>
|
||||||
return del(`${prefix}/${dataset_id}/document/${document_id}/paragraph/${paragraph_id}`)
|
) => Promise<Result<boolean>> = (dataset_id, document_id, paragraph_id, loading) => {
|
||||||
|
return del(
|
||||||
|
`${prefix}/${dataset_id}/document/${document_id}/paragraph/${paragraph_id}`,
|
||||||
|
undefined,
|
||||||
|
{},
|
||||||
|
loading
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -94,7 +94,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
<div class="ai-chat__operate p-24">
|
<div class="ai-chat__operate p-24" v-if="!record">
|
||||||
<div class="operate-textarea flex">
|
<div class="operate-textarea flex">
|
||||||
<el-input
|
<el-input
|
||||||
ref="quickInputRef"
|
ref="quickInputRef"
|
||||||
@ -131,6 +131,7 @@ import applicationApi from '@/api/application'
|
|||||||
import { ChatManagement, type chatType } from '@/api/type/application'
|
import { ChatManagement, type chatType } from '@/api/type/application'
|
||||||
import { randomId } from '@/utils/utils'
|
import { randomId } from '@/utils/utils'
|
||||||
import useStore from '@/stores'
|
import useStore from '@/stores'
|
||||||
|
defineOptions({ name: 'AiChat' })
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const {
|
const {
|
||||||
params: { accessToken }
|
params: { accessToken }
|
||||||
@ -140,7 +141,8 @@ const props = defineProps({
|
|||||||
type: Object,
|
type: Object,
|
||||||
default: () => {}
|
default: () => {}
|
||||||
},
|
},
|
||||||
appId: String
|
appId: String,
|
||||||
|
record: Boolean
|
||||||
})
|
})
|
||||||
const { application } = useStore()
|
const { application } = useStore()
|
||||||
|
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import CommonList from './common-list/index.vue'
|
|||||||
import MarkdownRenderer from './markdown-renderer/index.vue'
|
import MarkdownRenderer from './markdown-renderer/index.vue'
|
||||||
import dynamicsForm from './dynamics-form'
|
import dynamicsForm from './dynamics-form'
|
||||||
import CardCheckbox from './card-checkbox/index.vue'
|
import CardCheckbox from './card-checkbox/index.vue'
|
||||||
|
import AiChat from './ai-chat/index.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
install(app: App) {
|
install(app: App) {
|
||||||
@ -34,5 +35,6 @@ export default {
|
|||||||
app.use(dynamicsForm)
|
app.use(dynamicsForm)
|
||||||
app.component(MarkdownRenderer.name, MarkdownRenderer)
|
app.component(MarkdownRenderer.name, MarkdownRenderer)
|
||||||
app.component(CardCheckbox.name, CardCheckbox)
|
app.component(CardCheckbox.name, CardCheckbox)
|
||||||
|
app.component(AiChat.name, AiChat)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -182,3 +182,16 @@
|
|||||||
.el-tabs__header {
|
.el-tabs__header {
|
||||||
margin: 0 0 12px;
|
margin: 0 0 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.el-drawer {
|
||||||
|
.el-drawer__header {
|
||||||
|
padding: 16px 24px;
|
||||||
|
margin: 0;
|
||||||
|
border-bottom: 1px solid var(--el-border-color);
|
||||||
|
color: var(--app-text-color);
|
||||||
|
}
|
||||||
|
.el-drawer__footer {
|
||||||
|
border-top: 1px solid var(--el-border-color);
|
||||||
|
padding: 16px 24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -181,7 +181,6 @@
|
|||||||
import { reactive, ref, watch, onMounted } from 'vue'
|
import { reactive, ref, watch, onMounted } from 'vue'
|
||||||
import { useRouter, useRoute } from 'vue-router'
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
import { groupBy } from 'lodash'
|
import { groupBy } from 'lodash'
|
||||||
import AiChat from '@/components/ai-chat/index.vue'
|
|
||||||
import AddDatasetDialog from './components/AddDatasetDialog.vue'
|
import AddDatasetDialog from './components/AddDatasetDialog.vue'
|
||||||
import CreateModelDialog from '@/views/template/component/CreateModelDialog.vue'
|
import CreateModelDialog from '@/views/template/component/CreateModelDialog.vue'
|
||||||
import SelectProviderDialog from '@/views/template/component/SelectProviderDialog.vue'
|
import SelectProviderDialog from '@/views/template/component/SelectProviderDialog.vue'
|
||||||
|
|||||||
@ -109,7 +109,8 @@ const noMore = computed(
|
|||||||
() =>
|
() =>
|
||||||
applicationList.value.length > 0 &&
|
applicationList.value.length > 0 &&
|
||||||
applicationList.value.length === pageConfig.total &&
|
applicationList.value.length === pageConfig.total &&
|
||||||
pageConfig.total > 20
|
pageConfig.total > 20 &&
|
||||||
|
!loading.value
|
||||||
)
|
)
|
||||||
const disabledScroll = computed(
|
const disabledScroll = computed(
|
||||||
() => applicationList.value.length > 0 && (loading.value || noMore.value)
|
() => applicationList.value.length > 0 && (loading.value || noMore.value)
|
||||||
@ -144,8 +145,9 @@ function deleteApplication(row: any) {
|
|||||||
applicationApi
|
applicationApi
|
||||||
.delApplication(row.id)
|
.delApplication(row.id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
const index = applicationList.value.findIndex((v) => v.id === row.id)
|
||||||
|
applicationList.value.splice(index, 1)
|
||||||
MsgSuccess('删除成功')
|
MsgSuccess('删除成功')
|
||||||
getList()
|
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
@ -154,7 +156,6 @@ function deleteApplication(row: any) {
|
|||||||
.catch(() => {})
|
.catch(() => {})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function getList() {
|
function getList() {
|
||||||
applicationApi
|
applicationApi
|
||||||
.getApplication(pageConfig, searchValue.value && { name: searchValue.value }, loading)
|
.getApplication(pageConfig, searchValue.value && { name: searchValue.value }, loading)
|
||||||
|
|||||||
@ -14,7 +14,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { reactive, ref, watch, onMounted } from 'vue'
|
import { reactive, ref, watch, onMounted } from 'vue'
|
||||||
import { useRouter, useRoute } from 'vue-router'
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
import AiChat from '@/components/ai-chat/index.vue'
|
|
||||||
import applicationApi from '@/api/application'
|
import applicationApi from '@/api/application'
|
||||||
import useStore from '@/stores'
|
import useStore from '@/stores'
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|||||||
@ -82,7 +82,8 @@ const noMore = computed(
|
|||||||
() =>
|
() =>
|
||||||
datasetList.value.length > 0 &&
|
datasetList.value.length > 0 &&
|
||||||
datasetList.value.length === pageConfig.total &&
|
datasetList.value.length === pageConfig.total &&
|
||||||
pageConfig.total > 20
|
pageConfig.total > 20 &&
|
||||||
|
!loading.value
|
||||||
)
|
)
|
||||||
const disabledScroll = computed(
|
const disabledScroll = computed(
|
||||||
() => datasetList.value.length > 0 && (loading.value || noMore.value)
|
() => datasetList.value.length > 0 && (loading.value || noMore.value)
|
||||||
@ -115,8 +116,9 @@ function deleteDateset(row: any) {
|
|||||||
datasetApi
|
datasetApi
|
||||||
.delDateset(row.id)
|
.delDateset(row.id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
const index = datasetList.value.findIndex((v) => v.id === row.id)
|
||||||
|
datasetList.value.splice(index, 1)
|
||||||
MsgSuccess('删除成功')
|
MsgSuccess('删除成功')
|
||||||
getList()
|
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
|
|||||||
64
ui/src/views/log/component/ChatRecordDrawer.vue
Normal file
64
ui/src/views/log/component/ChatRecordDrawer.vue
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<template>
|
||||||
|
<el-drawer
|
||||||
|
v-model="visible"
|
||||||
|
size="50%"
|
||||||
|
append-to-body
|
||||||
|
@close="closeHandel"
|
||||||
|
class="chat-record-drawer"
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
<h4>应用标题</h4>
|
||||||
|
</template>
|
||||||
|
<AiChat record></AiChat>
|
||||||
|
<template #footer>
|
||||||
|
<div>
|
||||||
|
<el-button>上一条</el-button>
|
||||||
|
<el-button>下一条</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-drawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, reactive } from 'vue'
|
||||||
|
import { useRoute } from 'vue-router'
|
||||||
|
import logApi from '@/api/log'
|
||||||
|
const route = useRoute()
|
||||||
|
const {
|
||||||
|
params: { id }
|
||||||
|
} = route
|
||||||
|
|
||||||
|
const loading = ref(false)
|
||||||
|
const visible = ref(false)
|
||||||
|
|
||||||
|
const paginationConfig = reactive({
|
||||||
|
current_page: 1,
|
||||||
|
page_size: 20,
|
||||||
|
total: 0
|
||||||
|
})
|
||||||
|
|
||||||
|
function closeHandel() {}
|
||||||
|
|
||||||
|
function getChatRecord(chatId) {
|
||||||
|
logApi.getChatRecordLog(id as string, chatId, paginationConfig, loading).then((res) => {
|
||||||
|
// tableData.value = res.data.records
|
||||||
|
paginationConfig.total = res.data.total
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const open = (id) => {
|
||||||
|
getChatRecord(id)
|
||||||
|
visible.value = true
|
||||||
|
}
|
||||||
|
defineExpose({
|
||||||
|
open
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<style lang="scss">
|
||||||
|
.chat-record-drawer {
|
||||||
|
.el-drawer__body {
|
||||||
|
background: var(--app-layout-bg-color);
|
||||||
|
padding: 24px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -62,11 +62,13 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
</app-table>
|
</app-table>
|
||||||
</div>
|
</div>
|
||||||
|
<ChatRecordDrawer ref="ChatRecordRef" />
|
||||||
</LayoutContainer>
|
</LayoutContainer>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted, reactive, computed } from 'vue'
|
import { ref, onMounted, reactive, computed } from 'vue'
|
||||||
import { useRouter, useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
|
import ChatRecordDrawer from './component/ChatRecordDrawer.vue'
|
||||||
import { MsgSuccess, MsgConfirm } from '@/utils/message'
|
import { MsgSuccess, MsgConfirm } from '@/utils/message'
|
||||||
import logApi from '@/api/log'
|
import logApi from '@/api/log'
|
||||||
import { datetimeFormat } from '@/utils/time'
|
import { datetimeFormat } from '@/utils/time'
|
||||||
@ -93,6 +95,8 @@ const dayOptions = [
|
|||||||
label: '过去半年'
|
label: '过去半年'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
const ChatRecordRef = ref()
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const paginationConfig = reactive({
|
const paginationConfig = reactive({
|
||||||
current_page: 1,
|
current_page: 1,
|
||||||
@ -106,6 +110,7 @@ const search = ref('')
|
|||||||
|
|
||||||
function rowClickHandle(row: any) {
|
function rowClickHandle(row: any) {
|
||||||
// router.push({ path: `/dataset/${id}/${row.id}` })
|
// router.push({ path: `/dataset/${id}/${row.id}` })
|
||||||
|
ChatRecordRef.value.open(row.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteLog(row: any) {
|
function deleteLog(row: any) {
|
||||||
|
|||||||
@ -94,8 +94,8 @@ const submitHandle = async () => {
|
|||||||
if (problemId.value) {
|
if (problemId.value) {
|
||||||
paragraph
|
paragraph
|
||||||
.asyncPutParagraph(id, documentId, problemId.value, paragraphFormRef.value?.form)
|
.asyncPutParagraph(id, documentId, problemId.value, paragraphFormRef.value?.form)
|
||||||
.then(() => {
|
.then((res: any) => {
|
||||||
emit('refresh')
|
emit('refresh', res.data)
|
||||||
loading.value = false
|
loading.value = false
|
||||||
isEdit.value = false
|
isEdit.value = false
|
||||||
})
|
})
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
<el-button @click="addParagraph" type="primary" :disabled="loading"> 添加分段 </el-button>
|
<el-button @click="addParagraph" type="primary" :disabled="loading"> 添加分段 </el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<div class="document-detail__main p-16">
|
<div class="document-detail__main p-16" v-loading="pageConfig.current_page === 1 && loading">
|
||||||
<div class="flex-between p-8">
|
<div class="flex-between p-8">
|
||||||
<span>{{ pageConfig.total }} 段落</span>
|
<span>{{ pageConfig.total }} 段落</span>
|
||||||
<el-input
|
<el-input
|
||||||
@ -24,7 +24,7 @@
|
|||||||
</el-input>
|
</el-input>
|
||||||
</div>
|
</div>
|
||||||
<el-scrollbar>
|
<el-scrollbar>
|
||||||
<div class="document-detail-height" v-loading="pageConfig.current_page === 1 && loading">
|
<div class="document-detail-height">
|
||||||
<el-empty v-if="paragraphDetail.length == 0" description="暂无数据" />
|
<el-empty v-if="paragraphDetail.length == 0" description="暂无数据" />
|
||||||
<el-row v-else v-infinite-scroll="loadDataset" :infinite-scroll-disabled="disabledScroll">
|
<el-row v-else v-infinite-scroll="loadDataset" :infinite-scroll-disabled="disabledScroll">
|
||||||
<el-col
|
<el-col
|
||||||
@ -114,7 +114,8 @@ const noMore = computed(
|
|||||||
() =>
|
() =>
|
||||||
paragraphDetail.value.length > 0 &&
|
paragraphDetail.value.length > 0 &&
|
||||||
paragraphDetail.value.length === pageConfig.total &&
|
paragraphDetail.value.length === pageConfig.total &&
|
||||||
pageConfig.total > 20
|
pageConfig.total > 20 &&
|
||||||
|
!loading.value
|
||||||
)
|
)
|
||||||
const disabledScroll = computed(
|
const disabledScroll = computed(
|
||||||
() => paragraphDetail.value.length > 0 && (loading.value || noMore.value)
|
() => paragraphDetail.value.length > 0 && (loading.value || noMore.value)
|
||||||
@ -154,15 +155,10 @@ function deleteParagraph(row: any) {
|
|||||||
confirmButtonClass: 'danger'
|
confirmButtonClass: 'danger'
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
loading.value = true
|
paragraphApi.delParagraph(id, documentId, row.id, loading).then(() => {
|
||||||
paragraphApi
|
const index = paragraphDetail.value.findIndex((v) => v.id === row.id)
|
||||||
.delParagraph(id, documentId, row.id)
|
paragraphDetail.value.splice(index, 1)
|
||||||
.then(() => {
|
|
||||||
MsgSuccess('删除成功')
|
MsgSuccess('删除成功')
|
||||||
getParagraphList()
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
loading.value = false
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.catch(() => {})
|
.catch(() => {})
|
||||||
@ -205,9 +201,16 @@ function getParagraphList() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function refresh() {
|
function refresh(data: any) {
|
||||||
|
if (data) {
|
||||||
|
const index = paragraphDetail.value.findIndex((v) => v.id === data.id)
|
||||||
|
paragraphDetail.value.splice(index, 1, data)
|
||||||
|
} else {
|
||||||
|
pageConfig.current_page = 1
|
||||||
|
paragraphDetail.value = []
|
||||||
getParagraphList()
|
getParagraphList()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getDetail()
|
getDetail()
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user