| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- <template>
- <Modal :visible="visible" :width="720" :closeButton="true" @update:visible="val => emit('update:visible', val)">
- <div class="sddd_box">
- <template v-for="(item,index) in messageList" :key="item.id">
- <div v-if="item.messages.length">
- <div class="messageNode">
- <div class="mn_title">节点{{ index+1 }}</div>
- <div class="mn_content">
- <template v-for="(item2,index2) in item.messages" :key="`${index}-${index2}`">
- <div>
- <div class="na_m_item" v-if="item2.role == 'user' && item2.content">
- <div class="na_m_i_name">
- {{ item2.sender }}
- </div>
- <div class="na_m_i_content" v-html="item2.content"></div>
- </div>
- <div class="na_m_item" v-if="item2.role == 'assistant' && item2.content">
- <div class="na_m_i_name aiName">
- {{ item2.sender }}
- </div>
- <div class="na_m_i_content" v-html="item2.content"></div>
- </div>
- </div>
- </template>
- </div>
- </div>
- </div>
- </template>
- </div>
- </Modal>
- </template>
- <script lang="ts" setup>
- import { computed, watch, ref} from 'vue'
- import Modal from '@/components/Modal.vue'
- import MarkdownIt from 'markdown-it'
- import useImport from '@/hooks/useImport'
- // md.render(_addText)
- const props = defineProps<{
- visible: boolean
- work: any
- }>()
- const emit = defineEmits<{
- (e: 'update:visible', v: boolean): void
- }>()
- const md = new MarkdownIt()
- const { getFile } = useImport()
- const visible = computed({
- get: () => props.visible,
- set: (v: boolean) => emit('update:visible', v)
- })
- // 存储解析后的内容
- const messageList = ref<any[]>([])
- // 判断是否是 URL 链接
- const isUrl = (str: string): boolean => {
- try {
- const url = new URL(str)
- return url.protocol === 'http:' || url.protocol === 'https:'
- }
- catch {
- return false
- }
- }
- // 从链接获取文件内容
- const loadContentFromUrl = async (url: string): Promise<string> => {
- try {
- const fileData = await getFile(url)
- if (fileData && fileData.data) {
- // 将 ArrayBuffer 转为字符串
- const uint8Array = new Uint8Array(fileData.data)
- const jsonStr = new TextDecoder('utf-8').decode(uint8Array)
- return jsonStr
- }
- return ''
- }
- catch (error) {
- console.error('获取文件内容失败:', error)
- return ''
- }
- }
- // 处理内容
- const processContent = async (content: string) => {
- let contentToParse = content
-
- // 如果是链接,先获取文件内容
- if (isUrl(content)) {
- contentToParse = await loadContentFromUrl(content)
- }
-
- if (!contentToParse) {
- return []
- }
-
- try {
- const messageListRaw = JSON.parse(contentToParse)
- messageListRaw.forEach((item:any) => {
- if (item.messages && item.messages.length) {
- item.messages.forEach((item2: any) => {
- // 如果已经包含html标签则不再渲染
- if (!/^(\s*<[^>]+>.*<\/[^>]+>\s*|<[^>]+\/>\s*)$/s.test(item2.content.trim())) {
- item2.content = md.render(item2.content)
- }
- })
- }
- })
- return messageListRaw
- }
- catch (error) {
- console.error('解析内容失败:', error)
- return []
- }
- }
- // 监听 work 和 visible 变化
- watch(
- () => [props.work, props.visible],
- async () => {
- if (props.work && props.visible) {
- messageList.value = await processContent(props.work.content)
- }
- else {
- messageList.value = []
- }
- },
- { immediate: true }
- )
- // watch(() => props.visible, () => {
- // if (props.work && props.visible) {
- // const messageListRaw = JSON.parse(props.work.content)
- // console.log(messageListRaw)
- // const messages: any[] = messageListRaw
- // messageList.value = messages
- // }
- // })
- </script>
- <style scoped>
- .sddd_box {
- width: 100%;
- height: 60vh;
- overflow: auto;
- background-color: #f4f4f4;
- box-sizing: border-box;
- padding: 10px;
- gap: 20px;
- }
- .sddd_bottom {
- display: flex;
- margin-top: 20px;
- justify-content: flex-end;
- }
- .na_m_item {
- width: 100%;
- height: auto;
- margin: 10px 0;
- }
- .na_m_i_name {
- width: fit-content;
- max-width: 100%;
- height: auto;
- box-sizing: border-box;
- padding: 10px 10px;
- display: flex;
- align-items: center;
- border-radius: 10px 10px 0 0;
- background-color: #9747ff;
- color: #fff;
- text-overflow: ellipsis;
- overflow: hidden;
- white-space: nowrap;
- }
- .aiName {
- background-color: #0560fc;
- }
- .na_m_i_content {
- padding: 10px;
- border: solid 1px #e7e7e7;
- box-shadow: 0 4px 20px 0 rgba(0, 0, 0, 0.1);
- border-radius: 0 0 12px 12px;
- background-color: #fff;
- }
- .messageNode{
- width: 100%;
- height: auto;
- box-sizing: border-box;
- padding: 10px 10px;
- border: .5px solid #e7e7e7;
- border-radius: 12px;
- gap: 10px;
- margin-top: 20px;
- }
- </style>
|