feat: 历史记录

main
许宏杰 2 months ago
parent d3bb5df35b
commit 17933649bc

@ -27,6 +27,10 @@
border-bottom: 1px solid #000000 ; border-bottom: 1px solid #000000 ;
} }
.custom-card .n-card__content{
margin: 0 15px !important;
}
.chat-container { .chat-container {

@ -64,21 +64,31 @@
</template> </template>
</n-input> </n-input>
</div> </div>
<div class="chat-history"></div> <div class="chat-history">
<AiHistory @finishInfo="finishInfo"></AiHistory>
</div>
</div> </div>
</n-modal> </n-modal>
</div> </div>
</template> </template>
<script setup> <script setup>
import { onMounted, ref, reactive, nextTick, watch } from 'vue' import { onMounted, ref, nextTick, watch } from 'vue'
import {
import { AiHint, AiTable, AddIssue, IssueQuey, disclaimer, inThinking,initEcharts } from '@/views/AI/components' AiHint,
AiTable,
AddIssue,
IssueQuey,
disclaimer,
inThinking,
initEcharts,
AiHistory
} from '@/views/AI/components'
import userIcon from '@/assets/images/ai/user-icon.png' import userIcon from '@/assets/images/ai/user-icon.png'
import aiIcon from '@/assets/images/ai/ai-icon.png' import aiIcon from '@/assets/images/ai/ai-icon.png'
import { LineChart, BarChart, PieChart } from '@/views/AI/chat/class/index' import { LineChart, BarChart, PieChart } from '@/views/AI/chat/class/index'
import suspensionButton from '../../components/suspensionButton/index.vue' import suspensionButton from '../../components/suspensionButton/index.vue'
import { historyMessageRoomById, getDict } from '@/api/path' import { getDict } from '@/api/path'
import moment from 'moment' import moment from 'moment'
import { getAiMsg } from '@/api/ai.js' import { getAiMsg } from '@/api/ai.js'
@ -98,6 +108,10 @@ let dictList = ref([])
const bodyStyle = { const bodyStyle = {
width: '55%' width: '55%'
} }
const segmented = {
content: 'soft',
footer: 'soft'
}
onMounted(() => { onMounted(() => {
// getDictListist() // getDictListist()
@ -110,6 +124,19 @@ const getDictListist = async () => {
dictList.value = res.data.records dictList.value = res.data.records
} }
/**
* 获取详情后处理数据
* @param e
*/
const finishInfo = res => {
messageList.value = []
res.content.map(item => {
item.chartInstanceActiveIndex = 0
messageList.value.push(item)
initEchart(item, item)
})
}
/** /**
* 问答 * 问答
*/ */
@ -162,38 +189,47 @@ const handleSend = async () => {
}) })
nextTick(() => { nextTick(() => {
const itemData = messageList.value[lastIndex.value] const itemData = messageList.value[lastIndex.value]
initEchart(itemData, res)
})
} catch {
updataMessageItem({
from: 'ai',
type: 'text',
text: '服务器繁忙,请稍后再试。',
time: moment().format('YYYY/MM/DD HH:mm:ss'),
loading: false
})
}
}
/**
*
* @param currentItem
* @param res
*/
const initEchart = (currentItem, res) => {
// //
if (res.type === 'pie') { if (res.type === 'pie') {
itemData.chartInstanceItem = new PieChart(`${res.type}${lastIndex.value}`, { currentItem.chartInstanceItem = new PieChart(`${res.type}${lastIndex.value}`, {
title: res.title, title: res.title,
unit: res.unit, unit: res.unit,
data: res.data data: res.data
}) })
} else if (res.type === 'bar') { } else if (res.type === 'bar') {
itemData.chartInstanceItem = new BarChart(`${res.type}${lastIndex.value}`, { currentItem.chartInstanceItem = new BarChart(`${res.type}${lastIndex.value}`, {
title: res.title, title: res.title,
unit: res.unit, unit: res.unit,
xData: res.xData, xData: res.xData,
data: res.data data: res.data
}) })
} else if (res.type === 'line') { } else if (res.type === 'line') {
itemData.chartInstanceItem = new LineChart(`${res.type}${lastIndex.value}`, { currentItem.chartInstanceItem = new LineChart(`${res.type}${lastIndex.value}`, {
title: res.title, title: res.title,
unit: res.unit, unit: res.unit,
xData: res.xData, xData: res.xData,
data: res.data data: res.data
}) })
} }
})
} catch {
updataMessageItem({
from: 'ai',
type: 'text',
text: '服务器繁忙,请稍后再试。',
time: moment().format('YYYY/MM/DD HH:mm:ss'),
loading: false
})
}
} }
/** /**
@ -239,11 +275,10 @@ const pauseWatching = () => {
stopWatch = null stopWatch = null
} }
} }
// //
const startWatching = () => { const startWatching = () => {
stopWatch = watch( stopWatch = watch(
messageList, messageList.value,
newVal => { newVal => {
nextTick(() => { nextTick(() => {
if (scrollContainer.value) { if (scrollContainer.value) {
@ -256,11 +291,6 @@ const startWatching = () => {
isWatching.value = true isWatching.value = true
} }
const segmented = {
content: 'soft',
footer: 'soft'
}
const openAi = () => { const openAi = () => {
messageList.value = [] messageList.value = []
getDictListist() getDictListist()
@ -302,6 +332,8 @@ const openAi = () => {
} }
.chat-history { .chat-history {
width: 20%; width: 20%;
box-sizing: border-box;
padding: 10px;
} }
} }

@ -1,39 +1,17 @@
<template> <template>
<div class="history-box"> <div class="history-box">
<section v-show="list.length > 0"> <section>
<div class="history-title">聊天历史记录</div> <div class="history-title">历史记录</div>
<div class="history-list"> <div class="history-list" v-if="list.length > 0">
<div class="history-item" v-for="item in list" :key="item.id" @click="getMessageInfo(item.id)"> <div class="history-item" v-for="item in list" :key="item.id" @click="getMessageInfo(item.id)">
<div class="history-row-title">{{ formatFristIssue(item) }}</div> <div class="history-row-title">{{ formatFristIssue(item) }}</div>
<div class="history-row-icon" @click.stop="delMessageItem(item.id)"> <img src="~@/assets/images/ai/icon-delet.png" class="del-icon" alt="" @click.stop="delMessageItem(item.id)" />
<n-icon size="14" color="#F25D44" class="del-icon">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32">
<path d="M12 12h2v12h-2z" fill="currentColor"></path>
<path d="M18 12h2v12h-2z" fill="currentColor"></path>
<path d="M4 6v2h2v20a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8h2V6zm4 22V8h16v20z" fill="currentColor"></path>
<path d="M12 2h8v2h-8z" fill="currentColor"></path>
</svg>
</n-icon>
</div>
</div>
</div>
</section>
<section v-show="boardLsit.length > 0">
<div class="history-title">看板历史记录</div>
<div class="history-list">
<div class="history-item" v-for="item in boardLsit" :key="item.id" @click="getBoardInfo(item.id)">
<div class="history-row-title">{{ item.projectName }}</div>
<div class="history-row-icon" @click.stop="delProjectItem(item.id)">
<n-icon size="14" color="#F25D44" class="del-icon">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32">
<path d="M12 12h2v12h-2z" fill="currentColor"></path>
<path d="M18 12h2v12h-2z" fill="currentColor"></path>
<path d="M4 6v2h2v20a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8h2V6zm4 22V8h16v20z" fill="currentColor"></path>
<path d="M12 2h8v2h-8z" fill="currentColor"></path>
</svg>
</n-icon>
</div> </div>
</div> </div>
<div class="history-list" v-else >
<n-empty description="暂无记录" >
</n-empty>
</div> </div>
</section> </section>
</div> </div>
@ -41,78 +19,75 @@
<script setup> <script setup>
import { onMounted, ref } from 'vue' import { onMounted, ref } from 'vue'
import { projectListApi, deleteProjectApi, historyMessageRoomList, historyMessageRoomDel } from '@/api/path' import { historyMessageRoomList, historyMessageRoomDel, historyMessageRoomById } from '@/api/path'
import { useRouter } from 'vue-router' import { httpErrorHandle } from '@/utils'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
const chartEditStore = useChartEditStore() const emits = defineEmits(['finishInfo'])
let list = ref([]) let list = ref([])
let boardLsit = ref([])
const router = useRouter()
//List
const fetchList = async () => {
const res = await projectListApi({
page: 1,
limit: 100,
status: 1
})
boardLsit.value = res.data
}
//
const delProjectItem = async id => {
await deleteProjectApi({ ids: id })
fetchList()
}
const getBoardInfo = id => {
chartEditStore.setEdit(true)
router.push({path:'/board/' + id})
}
/**
* 过滤出第一条问题作为标题
* @param value
*/
const formatFristIssue = value => { const formatFristIssue = value => {
const data = JSON.parse(value.content) const data = JSON.parse(value.content)
return data[0].text return data[0].text
} }
//list /**
* 获取聊天记录list
*/
const messageList = async () => { const messageList = async () => {
const res = await historyMessageRoomList({ const res = await historyMessageRoomList({
current: 1, current: 1,
size: 100, size: 100
}) })
list.value = res.data.records list.value = res.data.records
} }
// /**
* 删除聊天记录
* @param id
*/
const delMessageItem = async id => { const delMessageItem = async id => {
const res = await historyMessageRoomDel(id) const res = await historyMessageRoomDel(id)
if (res) { if (res && res.code === 200) {
window['$message'].success('删除成功')
messageList() messageList()
return
} }
httpErrorHandle()
} }
const getMessageInfo = id => { /**
router.push('/chat/' + id) * 获取聊天详情
* @param id
*/
const getMessageInfo = async id => {
const res = await historyMessageRoomById(id)
if (res && res.code === 200) {
res.data.content = JSON.parse(res.data.content)
emits('finishInfo', res.data)
return
}
httpErrorHandle()
} }
onMounted(() => { onMounted(() => {
fetchList() messageList()
// messageList()
}) })
defineExpose({ defineExpose({
fetchList, messageList
// messageList
}) })
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.history-box { .history-box {
padding-top: 37px;
} }
.history-title { .history-title {
font-size: 14px; font-size: 14px;
color: #ffffff; color: #ffffff;
font-weight: bold; font-weight: bold;
font-family: 'AlibabaPuHuiTi-Medium';
} }
.history-list { .history-list {
margin: 10px 0; margin: 10px 0;
@ -139,8 +114,13 @@ defineExpose({
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
font-family: 'AlibabaPuHuiTi-Regular';
} }
.del-icon { .del-icon {
display: block;
height: 13px;
width: 13px;
display: none; display: none;
} }
} }

@ -35,6 +35,9 @@ import { goDialog, httpErrorHandle } from '@/utils'
import { openNewWindow, previewPath } from '@/utils' import { openNewWindow, previewPath } from '@/utils'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { projectListApi, deleteProjectApi } from '@/api/path' import { projectListApi, deleteProjectApi } from '@/api/path'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
const chartEditStore = useChartEditStore()
let boardLsit = ref([]) let boardLsit = ref([])
const router = useRouter() const router = useRouter()
@ -90,6 +93,7 @@ const deleteHandle = cardData => {
// //
const editHandle = cardData => { const editHandle = cardData => {
if (!cardData) return if (!cardData) return
chartEditStore.setEdit(true)//
router.push(`/board/` + cardData.id) router.push(`/board/` + cardData.id)
} }
// //

Loading…
Cancel
Save