mirror of
https://github.com/1Panel-dev/MaxKB.git
synced 2025-12-26 10:12:51 +00:00
feat: 对话日志
This commit is contained in:
parent
717cf97758
commit
eb0b630fbb
|
|
@ -25,7 +25,7 @@ const listSplitPattern: (
|
|||
}
|
||||
|
||||
/**
|
||||
* 文档列表
|
||||
* 文档分页列表
|
||||
* @param 参数 dataset_id,
|
||||
* page {
|
||||
"current_page": "string",
|
||||
|
|
@ -49,6 +49,13 @@ const getDocument: (
|
|||
)
|
||||
}
|
||||
|
||||
const getAllDocument: (dataset_id: string, loading?: Ref<boolean>) => Promise<Result<any>> = (
|
||||
dataset_id,
|
||||
loading
|
||||
) => {
|
||||
return get(`${prefix}/${dataset_id}/document`, undefined, loading)
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建批量文档
|
||||
* @param 参数
|
||||
|
|
@ -117,6 +124,7 @@ const getDocumentDetail: (dataset_id: string, document_id: string) => Promise<Re
|
|||
export default {
|
||||
postSplitDocument,
|
||||
getDocument,
|
||||
getAllDocument,
|
||||
postDocument,
|
||||
putDocument,
|
||||
delDocument,
|
||||
|
|
|
|||
|
|
@ -64,8 +64,43 @@ const getChatRecordLog: (
|
|||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改日志内容
|
||||
* @param 参数
|
||||
* application_id, chart_id, chart_record_id, dataset_id, document_id
|
||||
* data {
|
||||
"title": "string",
|
||||
"content": "string",
|
||||
}
|
||||
*/
|
||||
const putChatRecordLog: (
|
||||
applicaiton_id: String,
|
||||
chart_id: String,
|
||||
chart_record_id: String,
|
||||
dataset_id: String,
|
||||
document_id: String,
|
||||
data: any,
|
||||
loading?: Ref<boolean>
|
||||
) => Promise<Result<any>> = (
|
||||
applicaiton_id,
|
||||
chart_id,
|
||||
chart_record_id,
|
||||
dataset_id,
|
||||
document_id,
|
||||
data,
|
||||
loading
|
||||
) => {
|
||||
return put(
|
||||
`${prefix}/${applicaiton_id}/chat/${chart_id}/chat_record/${chart_record_id}/dataset/${dataset_id}/document_id/${document_id}/improve`,
|
||||
data,
|
||||
undefined,
|
||||
loading
|
||||
)
|
||||
}
|
||||
|
||||
export default {
|
||||
getChatLog,
|
||||
delChatLog,
|
||||
getChatRecordLog
|
||||
getChatRecordLog,
|
||||
putChatRecordLog
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ interface chatType {
|
|||
*/
|
||||
is_stop?: boolean
|
||||
record_id: string
|
||||
vote_status: string
|
||||
vote_status: string,
|
||||
}
|
||||
|
||||
export class ChatRecordManage {
|
||||
|
|
|
|||
|
|
@ -1 +1,19 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 261.76 226.69"><path d="M161.096.001l-30.225 52.351L100.647.001H-.005l130.877 226.688L261.749.001z" fill="#41b883"/><path d="M161.096.001l-30.225 52.351L100.647.001H52.346l78.526 136.01L209.398.001z" fill="#34495e"/></svg>
|
||||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M17.5 2.5H12.5V6.25H13.75V8.75H6.875C5.49429 8.75 4.375 9.86929 4.375 11.25V25C4.375 26.3807 5.49429 27.5 6.875 27.5H23.125C24.5057 27.5 25.625 26.3807 25.625 25V11.25C25.625 9.86929 24.5057 8.75 23.125 8.75H16.25V6.25H17.5V2.5ZM8.75 16.25H12.5V20H8.75V16.25ZM21.25 16.25V20H17.5V16.25H21.25Z" fill="url(#paint0_linear_1514_13484)"/>
|
||||
<path d="M2.5 15H0V21.25H2.5V15Z" fill="url(#paint1_linear_1514_13484)"/>
|
||||
<path d="M27.5 15H30V21.25H27.5V15Z" fill="url(#paint2_linear_1514_13484)"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_1514_13484" x1="15" y1="2.5" x2="15" y2="27.5" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#3370FF"/>
|
||||
<stop offset="1" stop-color="#7F3BF5"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_1514_13484" x1="15" y1="2.5" x2="15" y2="27.5" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#3370FF"/>
|
||||
<stop offset="1" stop-color="#7F3BF5"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_1514_13484" x1="15" y1="2.5" x2="15" y2="27.5" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#3370FF"/>
|
||||
<stop offset="1" stop-color="#7F3BF5"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 276 B After Width: | Height: | Size: 1.2 KiB |
|
|
@ -0,0 +1,65 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-tooltip effect="dark" content="修改内容" placement="top">
|
||||
<el-button text @click="editContent(data)">
|
||||
<el-icon><EditPen /></el-icon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
<el-divider direction="vertical" />
|
||||
<el-tooltip effect="dark" content="复制" placement="top">
|
||||
<el-button text @click="copyClick(data?.answer_text)">
|
||||
<AppIcon iconName="app-copy"></AppIcon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
<el-divider direction="vertical" v-if="buttonData?.vote_status !== '-1'" />
|
||||
<el-button text disabled v-if="buttonData?.vote_status === '0'">
|
||||
<AppIcon iconName="app-like-color"></AppIcon>
|
||||
</el-button>
|
||||
|
||||
<el-button text disabled v-if="buttonData?.vote_status === '1'">
|
||||
<AppIcon iconName="app-oppose-color"></AppIcon>
|
||||
</el-button>
|
||||
<EditContentDialog
|
||||
ref="EditContentDialogRef"
|
||||
:chartId="chartId"
|
||||
@updateContent="updateContent"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref, watch, onMounted } from 'vue'
|
||||
import { copyClick } from '@/utils/clipboard'
|
||||
import EditContentDialog from '@/views/log/component/EditContentDialog.vue'
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
applicationId: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
chartId: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
log: Boolean
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:data'])
|
||||
|
||||
const EditContentDialogRef = ref()
|
||||
|
||||
const buttonData = ref(props.data)
|
||||
const loading = ref(false)
|
||||
|
||||
function editContent(data: any) {
|
||||
EditContentDialogRef.value.open(data)
|
||||
}
|
||||
|
||||
function updateContent(data: any) {
|
||||
emit('update:data', data)
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
|
|
@ -71,7 +71,8 @@ const props = defineProps({
|
|||
chartId: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
log: Boolean
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:data', 'regeneration'])
|
||||
|
|
@ -79,7 +80,7 @@ const emit = defineEmits(['update:data', 'regeneration'])
|
|||
const buttonData = ref(props.data)
|
||||
const loading = ref(false)
|
||||
|
||||
function regeneration() {
|
||||
function regeneration() {
|
||||
emit('regeneration')
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@
|
|||
<template v-for="(item, index) in data?.example" :key="index">
|
||||
<div
|
||||
@click="quickProblemHandel(item)"
|
||||
class="problem-button cursor ellipsis-2"
|
||||
class="problem-button ellipsis-2"
|
||||
:class="log ? 'disabled' : 'cursor'"
|
||||
v-if="item"
|
||||
>
|
||||
<el-icon><EditPen /></el-icon>
|
||||
|
|
@ -66,7 +67,14 @@
|
|||
:inner_suffix="false"
|
||||
></MarkdownRenderer>
|
||||
</el-card>
|
||||
<div class="flex-between mt-8">
|
||||
<div class="flex-between mt-8" v-if="log">
|
||||
<el-text type="info">
|
||||
消耗 {{ item?.message_tokens + item?.answer_tokens }} tokens
|
||||
</el-text>
|
||||
<LogOperationButton :data="item" :applicationId="appId" :chartId="item.id" />
|
||||
</div>
|
||||
|
||||
<div class="flex-between mt-8" v-else>
|
||||
<div>
|
||||
<el-button
|
||||
type="primary"
|
||||
|
|
@ -94,7 +102,7 @@
|
|||
</template>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
<div class="ai-chat__operate p-24" v-if="!record">
|
||||
<div class="ai-chat__operate p-24" v-if="!log">
|
||||
<div class="operate-textarea flex">
|
||||
<el-input
|
||||
ref="quickInputRef"
|
||||
|
|
@ -124,8 +132,9 @@
|
|||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, nextTick, onUpdated, computed } from 'vue'
|
||||
import { ref, nextTick, onUpdated, computed, watch } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import LogOperationButton from './LogOperationButton.vue'
|
||||
import OperationButton from './OperationButton.vue'
|
||||
import applicationApi from '@/api/application'
|
||||
import { ChatManagement, type chatType } from '@/api/type/application'
|
||||
|
|
@ -142,7 +151,11 @@ const props = defineProps({
|
|||
default: () => {}
|
||||
},
|
||||
appId: String,
|
||||
record: Boolean
|
||||
log: Boolean,
|
||||
record: {
|
||||
type: Array<chatType[]>,
|
||||
default: () => []
|
||||
}
|
||||
})
|
||||
const { application } = useStore()
|
||||
|
||||
|
|
@ -152,17 +165,31 @@ const dialogScrollbar = ref()
|
|||
const loading = ref(false)
|
||||
const inputValue = ref('')
|
||||
const chartOpenId = ref('')
|
||||
const chatList = ref<chatType[]>([])
|
||||
const chatList = ref<any[]>([])
|
||||
|
||||
const isDisabledChart = computed(
|
||||
() => !(inputValue.value && (props.appId || (props.data?.name && props.data?.model_id)))
|
||||
)
|
||||
|
||||
watch(
|
||||
() => props.record,
|
||||
(value) => {
|
||||
if (props.log) {
|
||||
chatList.value = value
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
|
||||
function quickProblemHandel(val: string) {
|
||||
inputValue.value = val
|
||||
nextTick(() => {
|
||||
quickInputRef.value?.focus()
|
||||
})
|
||||
if (!props.log) {
|
||||
inputValue.value = val
|
||||
nextTick(() => {
|
||||
quickInputRef.value?.focus()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function sendChatHandle(event: any) {
|
||||
|
|
@ -286,7 +313,9 @@ function handleScrollBottom() {
|
|||
}
|
||||
|
||||
onUpdated(() => {
|
||||
handleScrollBottom()
|
||||
if (!props.log) {
|
||||
handleScrollBottom()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
|
@ -330,6 +359,11 @@ onUpdated(() => {
|
|||
&:hover {
|
||||
background: var(--el-color-primary-light-9);
|
||||
}
|
||||
&.disabled {
|
||||
&:hover {
|
||||
background: var(--app-layout-bg-color);
|
||||
}
|
||||
}
|
||||
:deep(.el-icon) {
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,9 @@
|
|||
<div class="flex-center h-full">
|
||||
<div class="app-title-container flex-center">
|
||||
<div class="app-title-icon"></div>
|
||||
<div class="app-title-text app-logo-font">{{ defaultTitle }}</div>
|
||||
<div class="app-title-text app-logo-font ml-4">
|
||||
{{ defaultTitle }}
|
||||
</div>
|
||||
</div>
|
||||
<TopMenu></TopMenu>
|
||||
</div>
|
||||
|
|
@ -26,10 +28,11 @@ const defaultTitle = import.meta.env.VITE_APP_TITLE
|
|||
.app-title-container {
|
||||
margin-right: 45px;
|
||||
.app-title-icon {
|
||||
background-image: url('@/assets/logo.png');
|
||||
background-image: url('@/assets/logo.svg');
|
||||
background-size: 100% 100%;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
background-position: center -1px;
|
||||
}
|
||||
|
||||
.app-title-text {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import useDatasetStore from './modules/dataset'
|
|||
import useParagraphStore from './modules/paragraph'
|
||||
import useModelStore from './modules/model'
|
||||
import useApplicationStore from './modules/application'
|
||||
import useDocumentStore from './modules/document'
|
||||
|
||||
const useStore = () => ({
|
||||
common: useCommonStore(),
|
||||
|
|
@ -14,7 +15,8 @@ const useStore = () => ({
|
|||
dataset: useDatasetStore(),
|
||||
paragraph: useParagraphStore(),
|
||||
model: useModelStore(),
|
||||
application: useApplicationStore()
|
||||
application: useApplicationStore(),
|
||||
document: useDocumentStore()
|
||||
})
|
||||
|
||||
export default useStore
|
||||
|
|
|
|||
|
|
@ -34,6 +34,19 @@ const useApplicationStore = defineStore({
|
|||
})
|
||||
},
|
||||
|
||||
async asyncGetApplicationDataset(id: string, loading?: Ref<boolean>) {
|
||||
return new Promise((resolve, reject) => {
|
||||
applicationApi
|
||||
.getApplicationDataset(id, loading)
|
||||
.then((data) => {
|
||||
resolve(data)
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
async asyncGetAccessToken(id: string, loading?: Ref<boolean>) {
|
||||
return new Promise((resolve, reject) => {
|
||||
applicationApi
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
import { defineStore } from 'pinia'
|
||||
import documentApi from '@/api/document'
|
||||
import { type Ref } from 'vue'
|
||||
|
||||
const useDocumentStore = defineStore({
|
||||
id: 'documents',
|
||||
state: () => ({}),
|
||||
actions: {
|
||||
async asyncGetAllDocument(id: string, loading?: Ref<boolean>) {
|
||||
return new Promise((resolve, reject) => {
|
||||
documentApi
|
||||
.getAllDocument(id, loading)
|
||||
.then((res) => {
|
||||
resolve(res)
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export default useDocumentStore
|
||||
|
|
@ -195,3 +195,11 @@
|
|||
padding: 16px 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.el-cascader-node {
|
||||
padding-left: 2px;
|
||||
}
|
||||
.el-cascader-node__prefix {
|
||||
right: 10px;
|
||||
left: auto;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ import type { Provider } from '@/api/type/model'
|
|||
import { realatedObject } from '@/utils/utils'
|
||||
import { MsgSuccess } from '@/utils/message'
|
||||
import useStore from '@/stores'
|
||||
import type Result from '@/request/Result'
|
||||
|
||||
const { model, dataset, application, user } = useStore()
|
||||
|
||||
const router = useRouter()
|
||||
|
|
@ -293,12 +293,12 @@ function getDetail() {
|
|||
|
||||
function getDataset() {
|
||||
if (id) {
|
||||
applicationApi.getApplicationDataset(id, datasetLoading).then((res) => {
|
||||
application.asyncGetApplicationDataset(id, datasetLoading).then((res: any) => {
|
||||
datasetList.value = res.data
|
||||
})
|
||||
} else {
|
||||
dataset.asyncGetAllDateset(datasetLoading).then((res:any) => {
|
||||
datasetList.value = res.data?.filter((v:any) => v.user_id === user.userInfo?.id)
|
||||
dataset.asyncGetAllDateset(datasetLoading).then((res: any) => {
|
||||
datasetList.value = res.data?.filter((v: any) => v.user_id === user.userInfo?.id)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,29 +7,51 @@
|
|||
class="chat-record-drawer"
|
||||
>
|
||||
<template #header>
|
||||
<h4>应用标题</h4>
|
||||
<h4>{{ data?.name }}</h4>
|
||||
</template>
|
||||
<AiChat record></AiChat>
|
||||
<div v-loading="paginationConfig.current_page === 1 && loading">
|
||||
<div v-infinite-scroll="loadDataset" :infinite-scroll-disabled="disabledScroll">
|
||||
<AiChat :data="data" :record="recordList" log></AiChat>
|
||||
</div>
|
||||
<div style="padding: 16px 10px">
|
||||
<el-divider class="custom-divider" v-if="recordList.length > 0 && loading">
|
||||
<el-text type="info"> 加载中...</el-text>
|
||||
</el-divider>
|
||||
<el-divider class="custom-divider" v-if="noMore">
|
||||
<el-text type="info"> 到底啦!</el-text>
|
||||
</el-divider>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div>
|
||||
<el-button>上一条</el-button>
|
||||
<el-button>下一条</el-button>
|
||||
<el-button :disabled="loading">上一条</el-button>
|
||||
<el-button :disabled="loading">下一条</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive } from 'vue'
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import logApi from '@/api/log'
|
||||
import { type chatType } from '@/api/type/application'
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
})
|
||||
|
||||
const route = useRoute()
|
||||
const {
|
||||
params: { id }
|
||||
} = route
|
||||
|
||||
const loading = ref(false)
|
||||
const visible = ref(false)
|
||||
const recordList = ref<chatType[]>([])
|
||||
const currentChatId = ref('')
|
||||
|
||||
const paginationConfig = reactive({
|
||||
current_page: 1,
|
||||
|
|
@ -37,17 +59,43 @@ const paginationConfig = reactive({
|
|||
total: 0
|
||||
})
|
||||
|
||||
function closeHandel() {}
|
||||
const noMore = computed(
|
||||
() =>
|
||||
recordList.value.length > 0 &&
|
||||
recordList.value.length === paginationConfig.total &&
|
||||
paginationConfig.total > 20 &&
|
||||
!loading.value
|
||||
)
|
||||
const disabledScroll = computed(
|
||||
() => recordList.value.length > 0 && (loading.value || noMore.value)
|
||||
)
|
||||
|
||||
function getChatRecord(chatId:string) {
|
||||
logApi.getChatRecordLog(id as string, chatId, paginationConfig, loading).then((res) => {
|
||||
// tableData.value = res.data.records
|
||||
paginationConfig.total = res.data.total
|
||||
})
|
||||
function closeHandel() {
|
||||
recordList.value = []
|
||||
currentChatId.value = ''
|
||||
paginationConfig.total = 0
|
||||
paginationConfig.current_page = 1
|
||||
}
|
||||
|
||||
const open = (id:string) => {
|
||||
getChatRecord(id)
|
||||
function loadDataset() {
|
||||
if (paginationConfig.total > paginationConfig.page_size) {
|
||||
paginationConfig.current_page += 1
|
||||
getChatRecord()
|
||||
}
|
||||
}
|
||||
|
||||
function getChatRecord() {
|
||||
logApi
|
||||
.getChatRecordLog(id as string, currentChatId.value, paginationConfig, loading)
|
||||
.then((res) => {
|
||||
paginationConfig.total = res.data.total
|
||||
recordList.value = [...recordList.value, ...res.data.records]
|
||||
})
|
||||
}
|
||||
|
||||
const open = (id: string) => {
|
||||
currentChatId.value = id
|
||||
getChatRecord()
|
||||
visible.value = true
|
||||
}
|
||||
defineExpose({
|
||||
|
|
|
|||
|
|
@ -0,0 +1,172 @@
|
|||
<template>
|
||||
<el-dialog title="修改内容" v-model="dialogVisible" width="600">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
label-position="top"
|
||||
require-asterisk-position="right"
|
||||
:rules="rules"
|
||||
@submit.prevent
|
||||
>
|
||||
<el-form-item label="关联问题">
|
||||
<span>{{ form.problem_text }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="内容" prop="content">
|
||||
<el-input
|
||||
v-model="form.content"
|
||||
placeholder="请输入内容"
|
||||
maxlength="1024"
|
||||
show-word-limit
|
||||
:rows="8"
|
||||
type="textarea"
|
||||
>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="标题">
|
||||
<el-input v-model="form.title" placeholder="请给当前内容设置一个标题,以便管理查看">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="保存至文档" prop="document">
|
||||
<el-cascader v-model="form.document" :props="LoadDocument" placeholder="请选择文档">
|
||||
<template #default="{ node, data }">
|
||||
<span class="flex align-center">
|
||||
<AppAvatar v-if="!node.isLeaf" class="mr-12" shape="square" :size="24">
|
||||
<img src="@/assets/icon_document.svg" style="width: 58%" alt="" />
|
||||
</AppAvatar>
|
||||
{{ data.name }}
|
||||
</span>
|
||||
</template>
|
||||
</el-cascader>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click.prevent="dialogVisible = false"> 取消 </el-button>
|
||||
<el-button type="primary" @click="submitForm(formRef)"> 保存 </el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, watch, reactive } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import type { FormInstance, FormRules } from 'element-plus'
|
||||
import logApi from '@/api/log'
|
||||
import type { CascaderProps } from 'element-plus'
|
||||
|
||||
import useStore from '@/stores'
|
||||
|
||||
const { application, document } = useStore()
|
||||
|
||||
const props = defineProps({
|
||||
chartId: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
|
||||
const route = useRoute()
|
||||
const {
|
||||
params: { id }
|
||||
} = route as any
|
||||
|
||||
const emit = defineEmits(['updateContent'])
|
||||
|
||||
const formRef = ref()
|
||||
|
||||
const dialogVisible = ref<boolean>(false)
|
||||
const loading = ref(false)
|
||||
|
||||
const form = ref<any>({
|
||||
record_id: '',
|
||||
problem_text: '',
|
||||
title: '',
|
||||
content: '',
|
||||
document: []
|
||||
})
|
||||
|
||||
const rules = reactive<FormRules>({
|
||||
content: [{ required: true, message: '请输入内容', trigger: 'blur' }],
|
||||
document: [{ type: 'array', required: true, message: '请选择文档', trigger: 'change' }]
|
||||
})
|
||||
|
||||
const datasetList = ref([])
|
||||
|
||||
watch(dialogVisible, (bool) => {
|
||||
if (!bool) {
|
||||
form.value = {
|
||||
record_id: '',
|
||||
problem_text: '',
|
||||
title: '',
|
||||
content: '',
|
||||
document: []
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const LoadDocument: CascaderProps = {
|
||||
lazy: true,
|
||||
value: 'id',
|
||||
label: 'name',
|
||||
leaf: 'dataset_id',
|
||||
lazyLoad(node, resolve: any) {
|
||||
const { level, data } = node
|
||||
if (data?.id) {
|
||||
getDocument(data?.id as string, resolve)
|
||||
} else {
|
||||
getDataset(resolve)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getDocument(id: string, resolve: any) {
|
||||
document.asyncGetAllDocument(id, loading).then((res: any) => {
|
||||
datasetList.value = res.data
|
||||
resolve(datasetList.value)
|
||||
})
|
||||
}
|
||||
|
||||
function getDataset(resolve: any) {
|
||||
application.asyncGetApplicationDataset(id, loading).then((res: any) => {
|
||||
datasetList.value = res.data
|
||||
resolve(datasetList.value)
|
||||
})
|
||||
}
|
||||
|
||||
const open = (data: any) => {
|
||||
form.value.record_id = data.id
|
||||
form.value.problem_text = data.problem_text
|
||||
form.value.content = data.answer_text
|
||||
dialogVisible.value = true
|
||||
}
|
||||
const submitForm = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
await formEl.validate((valid, fields) => {
|
||||
if (valid) {
|
||||
const obj = {
|
||||
title: form.value.title,
|
||||
content: form.value.content
|
||||
}
|
||||
logApi
|
||||
.putChatRecordLog(
|
||||
id,
|
||||
props.chartId,
|
||||
form.value.record_id,
|
||||
form.value.document[0],
|
||||
form.value.document[1],
|
||||
obj,
|
||||
loading
|
||||
)
|
||||
.then((res: any) => {
|
||||
emit('updateContent', res.data)
|
||||
loading.value = false
|
||||
})
|
||||
} else {
|
||||
console.log('error submit!', fields)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({ open })
|
||||
</script>
|
||||
<style lang="scss" scope></style>
|
||||
|
|
@ -62,7 +62,7 @@
|
|||
</el-table-column>
|
||||
</app-table>
|
||||
</div>
|
||||
<ChatRecordDrawer ref="ChatRecordRef" />
|
||||
<ChatRecordDrawer ref="ChatRecordRef" :data="detail" />
|
||||
</LayoutContainer>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
|
|
@ -72,6 +72,8 @@ import ChatRecordDrawer from './component/ChatRecordDrawer.vue'
|
|||
import { MsgSuccess, MsgConfirm } from '@/utils/message'
|
||||
import logApi from '@/api/log'
|
||||
import { datetimeFormat } from '@/utils/time'
|
||||
import useStore from '@/stores'
|
||||
const { application } = useStore()
|
||||
const route = useRoute()
|
||||
const {
|
||||
params: { id }
|
||||
|
|
@ -107,6 +109,7 @@ const tableData = ref([])
|
|||
|
||||
const history_day = ref(7)
|
||||
const search = ref('')
|
||||
const detail = ref<any>(null)
|
||||
|
||||
function rowClickHandle(row: any) {
|
||||
// router.push({ path: `/dataset/${id}/${row.id}` })
|
||||
|
|
@ -152,8 +155,15 @@ function getList() {
|
|||
})
|
||||
}
|
||||
|
||||
function getDetail() {
|
||||
application.asyncGetApplicationDetail(id as string, loading).then((res: any) => {
|
||||
detail.value = res.data
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getList()
|
||||
getDetail()
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
|
|
|
|||
Loading…
Reference in New Issue