mirror of
https://github.com/1Panel-dev/MaxKB.git
synced 2025-12-26 18:32:48 +00:00
feat: 对话增加历史记录
This commit is contained in:
parent
dcc7d082af
commit
ebbd1ee601
|
|
@ -53,7 +53,7 @@ const chatButtonHtml=
|
|||
|
||||
const getChatContainerHtml=(protocol,host,token)=>{
|
||||
return `<div id="maxkb-chat-container">
|
||||
<iframe id="maxkb-chat" src=${protocol}://${host}/ui/chat/${token}></iframe>
|
||||
<iframe id="maxkb-chat" src=${protocol}://${host}/ui/chat/${token}?mode=embed></iframe>
|
||||
<div class="maxkb-operate"><div class="maxkb-closeviewport maxkb-viewportnone"><svg style="vertical-align: middle;overflow: hidden;" t="1710214539671" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" fill="rgb(100, 106, 115)" width="16" height="16"><path d="M85.333333 384c25.6 0 42.666667-17.066667 42.666667-42.666667V128h213.333333c25.6 0 42.666667-17.066667 42.666667-42.666667s-17.066667-42.666667-42.666667-42.666666H85.333333c-25.6 0-42.666667 17.066667-42.666666 42.666666v256c0 25.6 17.066667 42.666667 42.666666 42.666667zM938.666667 640c-25.6 0-42.666667 17.066667-42.666667 42.666667v213.333333h-213.333333c-25.6 0-42.666667 17.066667-42.666667 42.666667s17.066667 42.666667 42.666667 42.666666h256c25.6 0 42.666667-17.066667 42.666666-42.666666v-256c0-25.6-17.066667-42.666667-42.666666-42.666667zM601.6 401.066667c4.266667 8.533333 12.8 17.066667 21.333333 21.333333 4.266667 4.266667 12.8 4.266667 17.066667 4.266667h256c25.6 0 42.666667-17.066667 42.666667-42.666667s-17.066667-42.666667-42.666667-42.666667h-153.6l226.133333-226.133333c17.066667-17.066667 17.066667-42.666667 0-59.733333-8.533333-8.533333-17.066667-12.8-29.866666-12.8s-21.333333 4.266667-29.866667 12.8L682.666667 281.6V128c0-25.6-17.066667-42.666667-42.666667-42.666667s-42.666667 17.066667-42.666667 42.666667v256c0 4.266667 0 12.8 4.266667 17.066667zM115.2 968.533333L341.333333 742.4V896c0 25.6 17.066667 42.666667 42.666667 42.666667s42.666667-17.066667 42.666667-42.666667v-256c0-4.266667 0-12.8-4.266667-17.066667-4.266667-8.533333-12.8-17.066667-21.333333-21.333333-4.266667-4.266667-12.8-4.266667-17.066667-4.266667H128c-25.6 0-42.666667 17.066667-42.666667 42.666667s17.066667 42.666667 42.666667 42.666667h153.6l-226.133333 226.133333c-17.066667 17.066667-17.066667 42.666667 0 59.733333s42.666667 17.066667 59.733333 0z" p-id="10189"></path></svg></div>
|
||||
<div class="maxkb-openviewport">
|
||||
<svg t="1710150885892" style="vertical-align: middle;overflow: hidden;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" fill="rgb(100, 106, 115)" width="16" height="16" ><path d="M85.333333 384c25.6 0 42.666667-17.066667 42.666667-42.666667V128h213.333333c25.6 0 42.666667-17.066667 42.666667-42.666667s-17.066667-42.666667-42.666667-42.666666H85.333333c-25.6 0-42.666667 17.066667-42.666666 42.666666v256c0 25.6 17.066667 42.666667 42.666666 42.666667zM938.666667 640c-25.6 0-42.666667 17.066667-42.666667 42.666667v213.333333h-213.333333c-25.6 0-42.666667 17.066667-42.666667 42.666667s17.066667 42.666667 42.666667 42.666666h256c25.6 0 42.666667-17.066667 42.666666-42.666666v-256c0-25.6-17.066667-42.666667-42.666666-42.666667zM977.066667 68.266667c-4.266667-8.533333-12.8-17.066667-21.333334-21.333334-4.266667-4.266667-12.8-4.266667-17.066666-4.266666h-256c-25.6 0-42.666667 17.066667-42.666667 42.666666s17.066667 42.666667 42.666667 42.666667h153.6l-226.133334 226.133333c-17.066667 17.066667-17.066667 42.666667 0 59.733334 8.533333 8.533333 17.066667 12.8 29.866667 12.8s21.333333-4.266667 29.866667-12.8L896 187.733333V341.333333c0 25.6 17.066667 42.666667 42.666667 42.666667s42.666667-17.066667 42.666666-42.666667V85.333333c0-4.266667 0-12.8-4.266666-17.066666zM354.133333 610.133333L128 836.266667V682.666667c0-25.6-17.066667-42.666667-42.666667-42.666667s-42.666667 17.066667-42.666666 42.666667v256c0 4.266667 0 12.8 4.266666 17.066666 4.266667 8.533333 12.8 17.066667 21.333334 21.333334 4.266667 4.266667 12.8 4.266667 17.066666 4.266666h256c25.6 0 42.666667-17.066667 42.666667-42.666666s-17.066667-42.666667-42.666667-42.666667H187.733333l226.133334-226.133333c17.066667-17.066667 17.066667-42.666667 0-59.733334s-42.666667-17.066667-59.733334 0z" p-id="8645"></path></svg>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Result } from '@/request/Result'
|
||||
import { get, post, del, put, exportExcel } from '@/request/index'
|
||||
import { get, del, put, exportExcel } from '@/request/index'
|
||||
import type { pageRequest } from '@/api/type/common'
|
||||
import { type Ref } from 'vue'
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@
|
|||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref, watch, onMounted } from 'vue'
|
||||
import { ref } from 'vue'
|
||||
import { copyClick } from '@/utils/clipboard'
|
||||
import EditContentDialog from '@/views/log/component/EditContentDialog.vue'
|
||||
import EditMarkDialog from '@/views/log/component/EditMarkDialog.vue'
|
||||
|
|
@ -65,7 +65,6 @@ const EditContentDialogRef = ref()
|
|||
const EditMarkDialogRef = ref()
|
||||
|
||||
const buttonData = ref(props.data)
|
||||
const loading = ref(false)
|
||||
|
||||
function editContent(data: any) {
|
||||
EditContentDialogRef.value.open(data)
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@
|
|||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref, watch, onMounted } from 'vue'
|
||||
import { ref } from 'vue'
|
||||
import { copyClick } from '@/utils/clipboard'
|
||||
import applicationApi from '@/api/application'
|
||||
const props = defineProps({
|
||||
|
|
@ -68,7 +68,7 @@ const props = defineProps({
|
|||
type: String,
|
||||
default: ''
|
||||
},
|
||||
chartId: {
|
||||
chatId: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
|
|
@ -86,8 +86,8 @@ function regeneration() {
|
|||
|
||||
function voteHandle(val: string) {
|
||||
applicationApi
|
||||
.putChatVote(props.applicationId, props.chartId, props.data.record_id, val, loading)
|
||||
.then((res) => {
|
||||
.putChatVote(props.applicationId, props.chatId, props.data.record_id, val, loading)
|
||||
.then(() => {
|
||||
buttonData.value['vote_status'] = val
|
||||
emit('update:data', buttonData.value)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<div ref="aiChatRef" class="ai-chat" :class="log ? 'chart-log' : ''">
|
||||
<el-scrollbar ref="scrollDiv" @scroll="handleScrollTop">
|
||||
<div ref="dialogScrollbar" class="ai-chat__content p-24">
|
||||
<div class="item-content mb-16" v-if="!props.available || props.data?.prologue">
|
||||
<div class="item-content mb-16" v-if="!props.available || (props.data?.prologue && !log)">
|
||||
<div class="avatar">
|
||||
<AppAvatar class="avatar-gradient">
|
||||
<img src="@/assets/icon_robot.svg" style="width: 75%" alt="" />
|
||||
|
|
@ -132,7 +132,7 @@
|
|||
<OperationButton
|
||||
:data="item"
|
||||
:applicationId="appId"
|
||||
:chartId="chartOpenId"
|
||||
:chatId="chartOpenId"
|
||||
@regeneration="regenerationChart(item)"
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -187,7 +187,6 @@ import { randomId } from '@/utils/utils'
|
|||
import useStore from '@/stores'
|
||||
import MdRenderer from '@/components/markdown-renderer/MdRenderer.vue'
|
||||
import { MdPreview } from 'md-editor-v3'
|
||||
import { MsgError } from '@/utils/message'
|
||||
import { debounce } from 'lodash'
|
||||
defineOptions({ name: 'AiChat' })
|
||||
const route = useRoute()
|
||||
|
|
@ -260,9 +259,7 @@ watch(
|
|||
watch(
|
||||
() => props.record,
|
||||
(value) => {
|
||||
if (props.log) {
|
||||
chatList.value = value
|
||||
}
|
||||
chatList.value = value
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
|
|
@ -446,7 +443,7 @@ function chatMessage(chat?: any, problem?: string, re_chat?: boolean) {
|
|||
})
|
||||
}
|
||||
if (!chartOpenId.value) {
|
||||
getChartOpenId(chat).catch((e) => {
|
||||
getChartOpenId(chat).catch(() => {
|
||||
errorWrite(chat)
|
||||
})
|
||||
} else {
|
||||
|
|
@ -464,7 +461,7 @@ function chatMessage(chat?: any, problem?: string, re_chat?: boolean) {
|
|||
.then(() => {
|
||||
chatMessage(chat)
|
||||
})
|
||||
.catch((err) => {
|
||||
.catch(() => {
|
||||
errorWrite(chat)
|
||||
})
|
||||
} else if (response.status === 460) {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, watch, useSlots } from 'vue'
|
||||
import { ref, watch } from 'vue'
|
||||
|
||||
defineOptions({ name: 'CommonList' })
|
||||
|
||||
|
|
@ -30,6 +30,8 @@ const props = withDefaults(
|
|||
}
|
||||
)
|
||||
|
||||
const current = ref<Number | String>(0)
|
||||
|
||||
watch(
|
||||
() => props.defaultActive,
|
||||
(val) => {
|
||||
|
|
@ -42,8 +44,6 @@ watch(
|
|||
|
||||
const emit = defineEmits(['click'])
|
||||
|
||||
const current = ref(0)
|
||||
|
||||
function clickHandle(row: any, index: number) {
|
||||
current.value = index
|
||||
emit('click', row)
|
||||
|
|
@ -54,10 +54,12 @@ function clickHandle(row: any, index: number) {
|
|||
.common-list {
|
||||
li {
|
||||
padding: 10px 16px;
|
||||
font-weight: 400;
|
||||
&.active {
|
||||
background: var(--el-color-primary-light-9);
|
||||
border-radius: 4px;
|
||||
color: var(--el-color-primary);
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ const settingRouter = {
|
|||
path: '/setting',
|
||||
name: 'setting',
|
||||
meta: { icon: 'Setting', title: '系统设置', permission: 'SETTING:READ' },
|
||||
redirect: (to: any) => {
|
||||
redirect: () => {
|
||||
if (hasPermission(new Role('ADMIN'), 'AND')) {
|
||||
return '/user'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,23 @@ const useLogStore = defineStore({
|
|||
reject(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
async asyncChatRecordLog(
|
||||
id: string,
|
||||
chatId: string,
|
||||
page: pageRequest,
|
||||
loading?: Ref<boolean>
|
||||
) {
|
||||
return new Promise((resolve, reject) => {
|
||||
logApi
|
||||
.getChatRecordLog(id, chatId, page, loading)
|
||||
.then((data) => {
|
||||
resolve(data)
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
import { h } from 'vue'
|
||||
import { ElMessageBox, ElMessage, ElIcon } from 'element-plus'
|
||||
import { WarningFilled } from '@element-plus/icons-vue'
|
||||
import { ElMessageBox, ElMessage } from 'element-plus'
|
||||
|
||||
export const MsgSuccess = (message: string) => {
|
||||
ElMessage.success({
|
||||
|
|
@ -52,21 +50,3 @@ export const MsgConfirm = (title: string, description: string, options?: any) =>
|
|||
}
|
||||
return ElMessageBox.confirm(description, title, defaultOptions)
|
||||
}
|
||||
|
||||
// export const MsgConfirm = ({ title, description }: any, options?: any) => {
|
||||
// const message: any = h('div', { class: 'app-confirm' }, [
|
||||
// h('h4', { class: 'app-confirm-title flex align-center' }, [
|
||||
// h(ElIcon, { class: 'icon' }, [h(WarningFilled)]),
|
||||
// h('span', { class: 'ml-16' }, title)
|
||||
// ]),
|
||||
// h('div', { class: 'app-confirm-description mt-8' }, description)
|
||||
// ])
|
||||
|
||||
// const defaultOptions: Object = {
|
||||
// showCancelButton: true,
|
||||
// confirmButtonText: '确定',
|
||||
// cancelButtonText: '取消',
|
||||
// ...options
|
||||
// }
|
||||
// return ElMessageBox({ message, ...defaultOptions })
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@
|
|||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, reactive, computed } from 'vue'
|
||||
import { ref, onMounted, reactive } from 'vue'
|
||||
import applicationApi from '@/api/application'
|
||||
import { MsgSuccess, MsgConfirm } from '@/utils/message'
|
||||
import { isAppIcon } from '@/utils/application'
|
||||
|
|
@ -121,7 +121,7 @@ function searchHandle() {
|
|||
}
|
||||
function getAccessToken(id: string) {
|
||||
application.asyncGetAccessToken(id, loading).then((res: any) => {
|
||||
window.open(application.location + res?.data?.access_token)
|
||||
window.open(application.location + res?.data?.access_token + '?mode=pc')
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ const applicationAvailable = ref<boolean>(true)
|
|||
function getAccessToken(token: string) {
|
||||
application
|
||||
.asyncAppAuthentication(token, loading)
|
||||
.then((res) => {
|
||||
.then(() => {
|
||||
getProfile()
|
||||
})
|
||||
.catch(() => {
|
||||
|
|
|
|||
|
|
@ -1,23 +1,23 @@
|
|||
<template>
|
||||
<div class="chat" v-loading="loading">
|
||||
<div class="chat__header">
|
||||
<div class="chat-embed" v-loading="loading">
|
||||
<div class="chat-embed__header">
|
||||
<div class="chat-width">
|
||||
<h2 class="ml-24">{{ applicationDetail?.name }}</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="chat__main chat-width">
|
||||
<div class="chat-embed__main chat-width">
|
||||
<AiChat
|
||||
v-model:data="applicationDetail"
|
||||
:available="applicationAvailable"
|
||||
:appId="applicationDetail?.id"
|
||||
></AiChat>
|
||||
</div>
|
||||
<div class="chat__footer"></div>
|
||||
<!-- <div class="chat__footer"></div> -->
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref, watch, onMounted } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import applicationApi from '@/api/application'
|
||||
import useStore from '@/stores'
|
||||
const route = useRoute()
|
||||
|
|
@ -35,7 +35,7 @@ const chatLogeData = ref<any[]>([])
|
|||
function getAccessToken(token: string) {
|
||||
application
|
||||
.asyncAppAuthentication(token, loading)
|
||||
.then((res) => {
|
||||
.then(() => {
|
||||
getProfile()
|
||||
})
|
||||
.catch(() => {
|
||||
|
|
@ -73,7 +73,7 @@ onMounted(() => {
|
|||
})
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.chat {
|
||||
.chat-embed {
|
||||
background-color: var(--app-layout-bg-color);
|
||||
overflow: hidden;
|
||||
&__header {
|
||||
|
|
|
|||
|
|
@ -1,106 +1,23 @@
|
|||
<template>
|
||||
<div class="chat" v-loading="loading">
|
||||
<div class="chat__header">
|
||||
<div class="chat-width">
|
||||
<h2 class="ml-24">{{ applicationDetail?.name }}</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="chat__main chat-width">
|
||||
<AiChat
|
||||
v-model:data="applicationDetail"
|
||||
:available="applicationAvailable"
|
||||
:appId="applicationDetail?.id"
|
||||
></AiChat>
|
||||
</div>
|
||||
<div class="chat__footer"></div>
|
||||
</div>
|
||||
<component :is="currentTemplate" :key="route.fullPath" />
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { onMounted, computed } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import applicationApi from '@/api/application'
|
||||
import useStore from '@/stores'
|
||||
|
||||
const components: any = import.meta.glob('@/views/chat/**/index.vue', {
|
||||
eager: true
|
||||
})
|
||||
const route = useRoute()
|
||||
const {
|
||||
params: { accessToken }
|
||||
query: { mode }
|
||||
} = route as any
|
||||
|
||||
const { application, user } = useStore()
|
||||
|
||||
const loading = ref(false)
|
||||
const applicationDetail = ref<any>({})
|
||||
const applicationAvailable = ref<boolean>(true)
|
||||
|
||||
function getAccessToken(token: string) {
|
||||
application
|
||||
.asyncAppAuthentication(token, loading)
|
||||
.then((res) => {
|
||||
getProfile()
|
||||
})
|
||||
.catch(() => {
|
||||
applicationAvailable.value = false
|
||||
})
|
||||
}
|
||||
function getProfile() {
|
||||
applicationApi
|
||||
.getProfile(loading)
|
||||
.then((res) => {
|
||||
applicationDetail.value = res.data
|
||||
})
|
||||
.catch(() => {
|
||||
applicationAvailable.value = false
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
user.changeUserType(2)
|
||||
getAccessToken(accessToken)
|
||||
const currentTemplate = computed(() => {
|
||||
const name = `/src/views/chat/${mode || 'pc'}/index.vue`
|
||||
return components[name].default
|
||||
})
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.chat {
|
||||
background-color: var(--app-layout-bg-color);
|
||||
overflow: hidden;
|
||||
&__header {
|
||||
background: var(--app-header-bg-color);
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
height: var(--app-header-height);
|
||||
line-height: var(--app-header-height);
|
||||
box-sizing: border-box;
|
||||
border-bottom: 1px solid var(--el-border-color);
|
||||
}
|
||||
&__main {
|
||||
padding-top: calc(var(--app-header-height) + 24px);
|
||||
height: calc(100vh - var(--app-header-height) - 24px);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
&__footer {
|
||||
background: #f3f7f9;
|
||||
height: 80px;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
border-radius: 8px !important;
|
||||
&:before {
|
||||
background: linear-gradient(0deg, #f3f7f9 0%, rgba(243, 247, 249, 0) 100%);
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
top: -16px;
|
||||
left: 0;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
.chat-width {
|
||||
max-width: var(--app-chat-width, 860px);
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
onMounted(() => {})
|
||||
</script>
|
||||
<style lang="scss"></style>
|
||||
|
|
|
|||
|
|
@ -1,20 +1,26 @@
|
|||
<template>
|
||||
<div class="chat" v-loading="loading">
|
||||
<div class="chat__header">
|
||||
<div class="chat-pc" v-loading="loading">
|
||||
<div class="chat-pc__header">
|
||||
<h4 class="ml-24">{{ applicationDetail?.name }}</h4>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div class="chat__left">
|
||||
<div class="chat-pc__left">
|
||||
<div class="p-24 pb-0">
|
||||
<el-button class="add-button w-full primary">
|
||||
<el-button class="add-button w-full primary" @click="newChat">
|
||||
<el-icon><Plus /></el-icon><span class="ml-4">新建对话</span>
|
||||
</el-button>
|
||||
<p class="mt-20 mb-8">历史记录</p>
|
||||
</div>
|
||||
<div class="chat-list-height pt-0">
|
||||
<div class="left-height pt-0">
|
||||
<el-scrollbar>
|
||||
<div class="p-8 pt-0">
|
||||
<common-list :data="chatLogeData" class="mt-8" v-loading="loading">
|
||||
<common-list
|
||||
:data="chatLogeData"
|
||||
class="mt-8"
|
||||
v-loading="loading"
|
||||
:defaultActive="currentId"
|
||||
@click="clickListHandle"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<auto-tooltip :content="row.abstract">
|
||||
{{ row.abstract }}
|
||||
|
|
@ -26,20 +32,22 @@
|
|||
</el-scrollbar>
|
||||
</div>
|
||||
</div>
|
||||
<div class="chat__right w-full">
|
||||
<AiChat
|
||||
v-model:data="applicationDetail"
|
||||
:available="applicationAvailable"
|
||||
:appId="applicationDetail?.id"
|
||||
></AiChat>
|
||||
<div class="chat-pc__right">
|
||||
<div class="right-height">
|
||||
<AiChat
|
||||
v-model:data="applicationDetail"
|
||||
:available="applicationAvailable"
|
||||
:appId="applicationDetail?.id"
|
||||
:record="currentRecordList"
|
||||
></AiChat>
|
||||
</div>
|
||||
</div>
|
||||
<div class="chat__footer"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref, watch, onMounted } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { reactive, ref, onMounted } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import applicationApi from '@/api/application'
|
||||
import useStore from '@/stores'
|
||||
const route = useRoute()
|
||||
|
|
@ -47,7 +55,6 @@ const route = useRoute()
|
|||
const {
|
||||
params: { accessToken }
|
||||
} = route as any
|
||||
console.log(route)
|
||||
|
||||
const { application, user, log } = useStore()
|
||||
|
||||
|
|
@ -56,10 +63,20 @@ const applicationDetail = ref<any>({})
|
|||
const applicationAvailable = ref<boolean>(true)
|
||||
const chatLogeData = ref<any[]>([])
|
||||
|
||||
const paginationConfig = reactive({
|
||||
current_page: 1,
|
||||
page_size: 20,
|
||||
total: 0
|
||||
})
|
||||
|
||||
const currentChatId = ref('')
|
||||
const currentRecordList = ref<any>([])
|
||||
const currentId = ref('0')
|
||||
|
||||
function getAccessToken(token: string) {
|
||||
application
|
||||
.asyncAppAuthentication(token, loading)
|
||||
.then((res) => {
|
||||
.then(() => {
|
||||
getProfile()
|
||||
})
|
||||
.catch(() => {
|
||||
|
|
@ -78,6 +95,17 @@ function getProfile() {
|
|||
})
|
||||
}
|
||||
|
||||
function newChat() {
|
||||
paginationConfig.current_page = 1
|
||||
currentRecordList.value = []
|
||||
|
||||
chatLogeData.value.unshift({
|
||||
id: 'new',
|
||||
abstract: '新的对话'
|
||||
})
|
||||
currentId.value = 'new'
|
||||
}
|
||||
|
||||
function getChatLog(id: string) {
|
||||
const page = {
|
||||
current_page: 1,
|
||||
|
|
@ -92,13 +120,31 @@ function getChatLog(id: string) {
|
|||
})
|
||||
}
|
||||
|
||||
function getChatRecord() {
|
||||
log
|
||||
.asyncChatRecordLog(applicationDetail.value.id, currentChatId.value, paginationConfig, loading)
|
||||
.then((res: any) => {
|
||||
paginationConfig.total = res.data.total
|
||||
currentRecordList.value = [...currentRecordList.value, ...res.data.records]
|
||||
})
|
||||
}
|
||||
const clickListHandle = (item: any) => {
|
||||
paginationConfig.current_page = 1
|
||||
currentRecordList.value = []
|
||||
currentChatId.value = item.chat_id
|
||||
currentId.value = item.id
|
||||
if (currentChatId.value) {
|
||||
getChatRecord()
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
user.changeUserType(2)
|
||||
getAccessToken(accessToken)
|
||||
})
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.chat {
|
||||
.chat-pc {
|
||||
background-color: var(--app-layout-bg-color);
|
||||
overflow: hidden;
|
||||
&__header {
|
||||
|
|
@ -121,37 +167,21 @@ onMounted(() => {
|
|||
.add-button {
|
||||
border: 1px solid var(--el-color-primary);
|
||||
}
|
||||
.chat-list-height {
|
||||
height: calc(100vh - var(--app-header-height) - 160px);
|
||||
.left-height {
|
||||
height: calc(100vh - var(--app-header-height) - 135px);
|
||||
}
|
||||
}
|
||||
&__right {
|
||||
width: calc(100% - 280px);
|
||||
padding-top: calc(var(--app-header-height) + 24px);
|
||||
height: calc(100vh - var(--app-header-height) - 30px);
|
||||
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
&__footer {
|
||||
background: #f3f7f9;
|
||||
height: 80px;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 280px;
|
||||
width: calc(100% - 280px);
|
||||
box-sizing: border-box;
|
||||
border-radius: 8px !important;
|
||||
&:before {
|
||||
background: linear-gradient(0deg, #f3f7f9 0%, rgba(243, 247, 249, 0) 100%);
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
top: -16px;
|
||||
left: 0;
|
||||
height: 16px;
|
||||
.right-height {
|
||||
height: calc(100vh - var(--app-header-height) - 24px);
|
||||
}
|
||||
}
|
||||
|
||||
.gradient-divider {
|
||||
position: relative;
|
||||
text-align: center;
|
||||
|
|
|
|||
|
|
@ -35,8 +35,6 @@
|
|||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
|
||||
import { MsgSuccess } from '@/utils/message'
|
||||
|
||||
import useStore from '@/stores'
|
||||
const { dataset } = useStore()
|
||||
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@
|
|||
<script setup lang="ts">
|
||||
import { ref, reactive, watch } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import type { FormInstance, FormRules } from 'element-plus'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import documentApi from '@/api/document'
|
||||
import { MsgSuccess } from '@/utils/message'
|
||||
import { hitHandlingMethod } from '../utils'
|
||||
|
|
@ -156,14 +156,14 @@ const open = (row: any, list: Array<string>) => {
|
|||
|
||||
const submit = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
await formEl.validate((valid, fields) => {
|
||||
await formEl.validate((valid) => {
|
||||
if (valid) {
|
||||
if (isImport.value) {
|
||||
const obj = {
|
||||
source_url_list: form.value.source_url.split('\n'),
|
||||
selector: form.value.selector
|
||||
}
|
||||
documentApi.postWebDocument(id, obj, loading).then((res: any) => {
|
||||
documentApi.postWebDocument(id, obj, loading).then(() => {
|
||||
MsgSuccess('导入成功')
|
||||
emit('refresh')
|
||||
dialogVisible.value = false
|
||||
|
|
@ -178,7 +178,7 @@ const submit = async (formEl: FormInstance | undefined) => {
|
|||
selector: form.value.selector
|
||||
}
|
||||
}
|
||||
documentApi.putDocument(id, documentId.value, obj, loading).then((res) => {
|
||||
documentApi.putDocument(id, documentId.value, obj, loading).then(() => {
|
||||
MsgSuccess('设置成功')
|
||||
emit('refresh')
|
||||
dialogVisible.value = false
|
||||
|
|
@ -190,7 +190,7 @@ const submit = async (formEl: FormInstance | undefined) => {
|
|||
directly_return_similarity: form.value.directly_return_similarity || 0.9,
|
||||
id_list: documentList.value
|
||||
}
|
||||
documentApi.batchEditHitHandling(id, obj, loading).then((res: any) => {
|
||||
documentApi.batchEditHitHandling(id, obj, loading).then(() => {
|
||||
MsgSuccess('设置成功')
|
||||
emit('refresh')
|
||||
dialogVisible.value = false
|
||||
|
|
|
|||
|
|
@ -243,11 +243,11 @@ const { common, dataset, document } = useStore()
|
|||
|
||||
const storeKey = 'documents'
|
||||
|
||||
onBeforeRouteUpdate((to: any, from: any) => {
|
||||
onBeforeRouteUpdate(() => {
|
||||
common.savePage(storeKey, null)
|
||||
common.saveCondition(storeKey, null)
|
||||
})
|
||||
onBeforeRouteLeave((to: any, from: any) => {
|
||||
onBeforeRouteLeave((to: any) => {
|
||||
if (to.name !== 'Paragraph') {
|
||||
common.savePage(storeKey, null)
|
||||
common.saveCondition(storeKey, null)
|
||||
|
|
@ -351,7 +351,7 @@ function refreshDocument(row: any) {
|
|||
confirmButtonClass: 'danger'
|
||||
})
|
||||
.then(() => {
|
||||
documentApi.putDocumentRefresh(row.dataset_id, row.id).then((res) => {
|
||||
documentApi.putDocumentRefresh(row.dataset_id, row.id).then(() => {
|
||||
getList()
|
||||
})
|
||||
})
|
||||
|
|
@ -365,7 +365,7 @@ function refreshDocument(row: any) {
|
|||
.catch(() => {})
|
||||
}
|
||||
} else {
|
||||
documentApi.putDocumentRefresh(row.dataset_id, row.id).then((res) => {
|
||||
documentApi.putDocumentRefresh(row.dataset_id, row.id).then(() => {
|
||||
getList()
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, watch } from 'vue'
|
||||
import { ref, reactive, watch } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import logApi from '@/api/log'
|
||||
import { type chatType } from '@/api/type/application'
|
||||
|
|
@ -43,7 +43,7 @@ const props = withDefaults(
|
|||
/**
|
||||
* 对话 记录id
|
||||
*/
|
||||
chartId: string
|
||||
chatId: string
|
||||
currentAbstract: string
|
||||
/**
|
||||
* 下一条
|
||||
|
|
@ -61,7 +61,7 @@ const props = withDefaults(
|
|||
{}
|
||||
)
|
||||
|
||||
const emit = defineEmits(['update:chartId', 'update:currentAbstract', 'refresh'])
|
||||
const emit = defineEmits(['update:chatId', 'update:currentAbstract', 'refresh'])
|
||||
|
||||
const route = useRoute()
|
||||
const {
|
||||
|
|
@ -84,8 +84,8 @@ function closeHandle() {
|
|||
}
|
||||
|
||||
function getChatRecord() {
|
||||
if (props.chartId && visible.value) {
|
||||
logApi.getChatRecordLog(id as string, props.chartId, paginationConfig, loading).then((res) => {
|
||||
if (props.chatId && visible.value) {
|
||||
logApi.getChatRecordLog(id as string, props.chatId, paginationConfig, loading).then((res) => {
|
||||
paginationConfig.total = res.data.total
|
||||
recordList.value = [...recordList.value, ...res.data.records]
|
||||
})
|
||||
|
|
@ -93,7 +93,7 @@ function getChatRecord() {
|
|||
}
|
||||
|
||||
watch(
|
||||
() => props.chartId,
|
||||
() => props.chatId,
|
||||
() => {
|
||||
recordList.value = []
|
||||
paginationConfig.total = 0
|
||||
|
|
@ -104,7 +104,7 @@ watch(
|
|||
|
||||
watch(visible, (bool) => {
|
||||
if (!bool) {
|
||||
emit('update:chartId', '')
|
||||
emit('update:chatId', '')
|
||||
emit('update:currentAbstract', '')
|
||||
emit('refresh')
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,13 +92,6 @@ import useStore from '@/stores'
|
|||
|
||||
const { application, document } = useStore()
|
||||
|
||||
const props = defineProps({
|
||||
chartId: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
|
||||
const route = useRoute()
|
||||
const {
|
||||
params: { id }
|
||||
|
|
@ -147,7 +140,6 @@ watch(dialogVisible, (bool) => {
|
|||
}
|
||||
})
|
||||
|
||||
|
||||
function changeDataset(id: string) {
|
||||
form.value.document_id = ''
|
||||
getDocument(id)
|
||||
|
|
@ -176,7 +168,7 @@ const open = (data: any) => {
|
|||
}
|
||||
const submitForm = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
await formEl.validate((valid, fields) => {
|
||||
await formEl.validate((valid) => {
|
||||
if (valid) {
|
||||
const obj = {
|
||||
title: form.value.title,
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@
|
|||
:next="nextChatRecord"
|
||||
:pre="preChatRecord"
|
||||
ref="ChatRecordRef"
|
||||
v-model:chartId="currentChatId"
|
||||
v-model:chatId="currentChatId"
|
||||
v-model:currentAbstract="currentAbstract"
|
||||
:application="detail"
|
||||
:pre_disable="pre_disable"
|
||||
|
|
@ -131,11 +131,11 @@
|
|||
</LayoutContainer>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, reactive, watch, computed } from 'vue'
|
||||
import { ref, onMounted, reactive, computed } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import ChatRecordDrawer from './component/ChatRecordDrawer.vue'
|
||||
import { MsgSuccess, MsgConfirm, MsgError } from '@/utils/message'
|
||||
import { MsgSuccess, MsgConfirm } from '@/utils/message'
|
||||
import logApi from '@/api/log'
|
||||
import { datetimeFormat } from '@/utils/time'
|
||||
import useStore from '@/stores'
|
||||
|
|
@ -253,7 +253,7 @@ const preChatRecord = () => {
|
|||
return
|
||||
}
|
||||
paginationConfig.current_page = paginationConfig.current_page - 1
|
||||
getList().then((ok) => {
|
||||
getList().then(() => {
|
||||
index = paginationConfig.page_size - 1
|
||||
currentChatId.value = tableData.value[index].id
|
||||
currentAbstract.value = tableData.value[index].abstract
|
||||
|
|
|
|||
|
|
@ -12,16 +12,6 @@
|
|||
<span class="lighter" v-else>{{ form.title || '-' }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="分段内容" prop="content">
|
||||
<!-- <el-input
|
||||
v-if="isEdit"
|
||||
v-model="form.content"
|
||||
placeholder="请输入分段内容"
|
||||
maxlength="4096"
|
||||
show-word-limit
|
||||
:rows="8"
|
||||
type="textarea"
|
||||
>
|
||||
</el-input>-->
|
||||
<MarkdownEditor
|
||||
v-if="isEdit"
|
||||
v-model="form.content"
|
||||
|
|
@ -39,12 +29,11 @@
|
|||
:modelValue="form.content"
|
||||
class="maxkb-md"
|
||||
/>
|
||||
<!-- <span v-else class="break-all lighter">{{ form.content }}</span> -->
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onUnmounted, watch, nextTick } from 'vue'
|
||||
import { ref, reactive, onUnmounted, watch } from 'vue'
|
||||
import type { FormInstance, FormRules } from 'element-plus'
|
||||
import { MdPreview } from 'md-editor-v3'
|
||||
import MarkdownEditor from '@/components/markdown-editor/index.vue'
|
||||
|
|
|
|||
Loading…
Reference in New Issue