Merge branch 'main' of ssh://18.167.251.121:10002/aidlab/FiDA_Front

This commit is contained in:
X1627315083@163.com
2026-03-25 17:08:11 +08:00
5 changed files with 75 additions and 39 deletions

View File

@@ -36,7 +36,7 @@ export default {
wechatLogin: 'Sign in with Wechat', wechatLogin: 'Sign in with Wechat',
indexTip: 'A multi-agent canvas for rapid, trend driven design iteration.', indexTip: 'A multi-agent canvas for rapid, trend driven design iteration.',
sendCodeError: 'Send code error', sendCodeError: 'Send code error',
retrievePassword: 'Retrieve password', retrievePassword: 'Retrieve password'
}, },
Nuic: { Nuic: {
hiName: 'Hi, {name}. This is Fiphant.', hiName: 'Hi, {name}. This is Fiphant.',
@@ -51,7 +51,7 @@ export default {
basedIn: 'Based in', basedIn: 'Based in',
role: 'Role', role: 'Role',
allSet: 'All set!', allSet: 'All set!',
loadingTip: 'Were customizing your dashboard.', loadingTip: 'Were customizing your dashboard.'
}, },
Home: { Home: {
creditsNum: 'Credits: {num}', creditsNum: 'Credits: {num}',
@@ -81,9 +81,9 @@ export default {
userAgreement: 'User Agreement', userAgreement: 'User Agreement',
privacyPolicy: 'Privacy Policy', privacyPolicy: 'Privacy Policy',
view: 'View', view: 'View',
remainingNum: 'Remaining number of times to upload profile picture:', remainingNum: 'Remaining number of times to upload profile picture:'
}, },
Country:{ Country: {
unitedStates: 'United States', unitedStates: 'United States',
singapore: 'Singapore', singapore: 'Singapore',
australia: 'Australia', australia: 'Australia',
@@ -93,17 +93,18 @@ export default {
france: 'France', france: 'France',
japan: 'Japan', japan: 'Japan',
canada: 'Canada', canada: 'Canada',
germany: 'Germany', germany: 'Germany'
}, },
Role: { Role: {
designer: 'Designer', designer: 'Designer',
student: 'Student', student: 'Student',
teacher: 'Teacher', teacher: 'Teacher',
parent: 'Parent', parent: 'Parent',
other: 'Other', other: 'Other'
}, },
Input: { Input: {
placeholder: 'Describe the design you want to create... e.g. Modern wooden chair, Bauhaus style', placeholder:
'Describe the design you want to create... e.g. Modern wooden chair, Bauhaus style',
selectPlaceholder: 'Please select', selectPlaceholder: 'Please select',
typePlaceholder: 'Type', typePlaceholder: 'Type',
areaPlaceholder: 'Region', areaPlaceholder: 'Region',
@@ -146,11 +147,12 @@ export default {
france: 'France', france: 'France',
japan: 'Japan', japan: 'Japan',
canada: 'Canada', canada: 'Canada',
germany: 'Germany', germany: 'Germany'
}, },
agent: { agent: {
copySuccess: 'Text copied to clipboard', copySuccess: 'Text copied to clipboard',
copyFaild: 'Copy failed. Your browser may be restricting clipboard access. Please try copying manually.', copyFaild:
'Copy failed. Your browser may be restricting clipboard access. Please try copying manually.',
Download: 'Download', Download: 'Download',
deleteSuccess: 'Successfully deleted', deleteSuccess: 'Successfully deleted',
thinking: 'Thinking...', thinking: 'Thinking...',
@@ -158,6 +160,8 @@ export default {
quote: 'Quote', quote: 'Quote',
delete: 'Delete', delete: 'Delete',
edit: 'Edit', edit: 'Edit',
generatingReport:
'We are generating your report. This may take a few minutes, but you can continue with other tasks while its being generated.'
}, },
// Version Tree // Version Tree
@@ -172,13 +176,13 @@ export default {
restore: 'Restore', restore: 'Restore',
newChat: 'New Chat', newChat: 'New Chat',
delete: 'Delete', delete: 'Delete',
deleteChat:'Delete chat?', deleteChat: 'Delete chat?',
deleteHint:'Once deleted, you wont be able to view this conversation again.', deleteHint: 'Once deleted, you wont be able to view this conversation again.',
restoreChat:'Restore chat?', restoreChat: 'Restore chat?',
restoreHint:'Once deleted, you wont be able to view this conversation again.', restoreHint: 'Once deleted, you wont be able to view this conversation again.',
Cancel: 'Cancel', Cancel: 'Cancel',
Confirm: 'Confirm', Confirm: 'Confirm',
export: 'Export', export: 'Export'
}, },
flowCanvas: { flowCanvas: {
deleteCardConfirm: 'Are you sure you want to delete this function card?', deleteCardConfirm: 'Are you sure you want to delete this function card?',
@@ -187,14 +191,14 @@ export default {
confirmLeave: 'Are you sure you want to leave? You may have unsaved changes.', confirmLeave: 'Are you sure you want to leave? You may have unsaved changes.',
cannotFindSuperiorImage: 'Cannot find the superior image', cannotFindSuperiorImage: 'Cannot find the superior image',
deleteSubordinateCard: 'After deletion, all the function cards will also be deleted.', deleteSubordinateCard: 'After deletion, all the function cards will also be deleted.',
initialNodeProhibited: 'Initial node is prohibited from being deleted.', initialNodeProhibited: 'Initial node is prohibited from being deleted.'
}, },
assistant: { assistant: {
inputPlaceholder: 'Ask anything', inputPlaceholder: 'Ask anything'
}, },
//3d面板 //3d面板
threeModel: { threeModel: {
loading: 'Loading', loading: 'Loading',
download: 'Download', download: 'Download'
} }
} }

View File

@@ -82,7 +82,7 @@ export default {
userAgreement: '用户协议', userAgreement: '用户协议',
privacyPolicy: '隐私政策', privacyPolicy: '隐私政策',
view: '查看', view: '查看',
remainingNum: '剩余上传头像次数:', remainingNum: '剩余上传头像次数:'
}, },
Country: { Country: {
unitedStates: '美国', unitedStates: '美国',
@@ -148,11 +148,12 @@ export default {
'复制失败。您的浏览器可能限制了剪贴板访问,请允许浏览器访问剪贴板或尝试手动复制。', '复制失败。您的浏览器可能限制了剪贴板访问,请允许浏览器访问剪贴板或尝试手动复制。',
Download: '下载', Download: '下载',
deleteSuccess: '删除成功', deleteSuccess: '删除成功',
thinking:'已思考', thinking: '已思考',
thinkComplete: '思考完成。', thinkComplete: '思考完成。',
quote: '引用', quote: '引用',
delete: '删除', delete: '删除',
edit: '编辑', edit: '编辑',
generatingReport:'正在为您生成报告,可能需要几分钟时间,生成期间你可以继续进行其他任务'
}, },
// Version Tree // Version Tree
@@ -173,7 +174,7 @@ export default {
restoreHint: '恢复后将显示该对话。', restoreHint: '恢复后将显示该对话。',
Cancel: '取消', Cancel: '取消',
Confirm: '确认', Confirm: '确认',
export: '导出', export: '导出'
}, },
//generateSketch //generateSketch
generateSketch: { generateSketch: {
@@ -187,7 +188,7 @@ export default {
cancel: '取消', cancel: '取消',
confirmLeave: '您可能有未保存的更改,确定要离开吗?', confirmLeave: '您可能有未保存的更改,确定要离开吗?',
cannotFindSuperiorImage: '找不到上级图片', cannotFindSuperiorImage: '找不到上级图片',
initialNodeProhibited: 'Initial node is prohibited from being deleted.', initialNodeProhibited: 'Initial node is prohibited from being deleted.'
}, },
assistant: { assistant: {
inputPlaceholder: '请输入' inputPlaceholder: '请输入'

View File

@@ -28,6 +28,9 @@
import type { AgentParamsType } from '@/api/agent' import type { AgentParamsType } from '@/api/agent'
import { useUserInfoStore, useProjectStore, useAgentStore } from '@/stores' import { useUserInfoStore, useProjectStore, useAgentStore } from '@/stores'
import MyEvent from '@/utils/myEvent' import MyEvent from '@/utils/myEvent'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const userStore = useUserInfoStore() const userStore = useUserInfoStore()
const agentStore = useAgentStore() const agentStore = useAgentStore()
@@ -267,6 +270,7 @@
hasReportEvent = true hasReportEvent = true
// contentBody += `<slot slot-name="card" title="Report" content="Report"></slot>` // contentBody += `<slot slot-name="card" title="Report" content="Report"></slot>`
hasReportStarted = true hasReportStarted = true
ElMessage.success(t('agent.generatingReport'))
} }
if ( if (
@@ -337,6 +341,7 @@
} }
if (jsonData.title) { if (jsonData.title) {
emits('setTitle', jsonData.title) emits('setTitle', jsonData.title)
MyEvent.emit('newTitle', jsonData.title)
} }
if (hasSketch) { if (hasSketch) {
@@ -460,7 +465,13 @@
} }
// 处理对话列表,将连续的 assistant 消息合并为一条 // 处理对话列表,将连续的 assistant 消息合并为一条
const processDialogue = (dialogue, startIndex, existingImgList, sessionId) => { const processDialogue = (
dialogue,
startIndex,
existingImgList,
sessionId,
firstReportIndex = -1
) => {
if (!dialogue || dialogue.length === 0) return [] if (!dialogue || dialogue.length === 0) return []
const result = [] const result = []
@@ -495,6 +506,11 @@
j++ j++
} }
// 如果 firstReportIndex 在当前合并范围内,则把 slot 追加到末尾
if (firstReportIndex >= i && firstReportIndex < j) {
combinedContent += `<slot slot-name="card" title="Report" content="Report"></slot>`
}
result.push({ result.push({
...item, ...item,
content: combinedContent, content: combinedContent,
@@ -525,13 +541,12 @@
const processSession = (session, imgList, ancestorsList, idCounterRef) => { const processSession = (session, imgList, ancestorsList, idCounterRef) => {
if (!session) return if (!session) return
// 1. 在 dialogue 第一个 report 有值的项的 content 中插入报告卡片 // 1. 找到第一个 report 项的索引,供 processDialogue 使用
let firstReportIndex = -1
if (session.dialogue) { if (session.dialogue) {
for (let i = 0; i < session.dialogue.length; i++) { for (let i = 0; i < session.dialogue.length; i++) {
if (session.dialogue[i].report) { if (session.dialogue[i].report) {
session.dialogue[i].content = firstReportIndex = i
`<slot slot-name="card" title="123" content="123">123</slot>` +
(session.dialogue[i].content || '')
break break
} }
} }
@@ -554,10 +569,11 @@
} }
// 4. 处理 dialogue // 4. 处理 dialogue
const list = processDialogue(session.dialogue, 0, imgList, session.id) const list = processDialogue(session.dialogue, 0, imgList, session.id, firstReportIndex)
list.forEach((el) => { list.forEach((el) => {
el.id = idCounterRef.value++ el.id = idCounterRef.value++
}) })
ancestorsList.push(...list) ancestorsList.push(...list)
} }

View File

@@ -5,7 +5,7 @@
:class="{ 'is-user': content.isUser, 'is-loading': content.loading }" :class="{ 'is-user': content.isUser, 'is-loading': content.loading }"
> >
<div class="thumb"> <div class="thumb">
<img :src="content.isUser ? userThumb : agentThumb" class="thumb-icon" /> <img :src="content.isUser ? userAvatar : agentThumb" class="thumb-icon" />
</div> </div>
<div class="message-context" v-show="!content.loading"> <div class="message-context" v-show="!content.loading">
<div class="img-list flex" v-if="imageList.length > 0"> <div class="img-list flex" v-if="imageList.length > 0">
@@ -120,6 +120,9 @@
import type { CustomAttrs } from '@crazydos/vue-markdown' import type { CustomAttrs } from '@crazydos/vue-markdown'
import rehypeRaw from 'rehype-raw' import rehypeRaw from 'rehype-raw'
import MyEvent from '@/utils/myEvent' import MyEvent from '@/utils/myEvent'
import { useUserInfoStore } from '@/stores'
const userStore = useUserInfoStore()
const { t } = useI18n() const { t } = useI18n()
@@ -128,16 +131,12 @@
isLast: Boolean isLast: Boolean
}>() }>()
// watch(
// () => props,
// (newVal) => {
// console.log('newVal-----', newVal)
// },
// { immediate: true }
// )
const emit = defineEmits(['regenerate']) const emit = defineEmits(['regenerate'])
const userAvatar = computed(() => {
return userStore.state.userInfo?.avatar || userThumb
})
const imageList = computed(() => { const imageList = computed(() => {
const { imageUrls, role } = props.content const { imageUrls, role } = props.content
const list = [] const list = []
@@ -340,6 +339,7 @@
.img-list { .img-list {
column-gap: 1rem; column-gap: 1rem;
margin-bottom: 1.4rem; margin-bottom: 1.4rem;
justify-content: flex-end;
.img-item { .img-item {
width: 6.8rem; width: 6.8rem;
height: 6.8rem; height: 6.8rem;

View File

@@ -84,7 +84,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref, nextTick } from 'vue' import { computed, ref, nextTick, onMounted, onUnmounted } from 'vue'
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { getProjectList, updateProject, deleteProject } from '@/api/agent' import { getProjectList, updateProject, deleteProject } from '@/api/agent'
@@ -93,7 +93,8 @@
const { t: $t } = useI18n() const { t: $t } = useI18n()
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()
import { useGlobalStore } from '@/stores' import { useGlobalStore, useProjectStore } from '@/stores'
const projectStore = useProjectStore()
const id = computed(() => route.params.id) const id = computed(() => route.params.id)
const globalStore = useGlobalStore() const globalStore = useGlobalStore()
const isCollapse = computed(() => globalStore.state.homeLeftNavCollapse) const isCollapse = computed(() => globalStore.state.homeLeftNavCollapse)
@@ -198,8 +199,22 @@
} }
MyEvent.add('updateProjectList', GetProjectList) MyEvent.add('updateProjectList', GetProjectList)
GetProjectList() GetProjectList()
const replaceTitle = (title: string) => {
list.value.forEach((item: any) => {
if (String(item.id) === String(projectStore.state.id)) {
item.name = title
}
})
}
onMounted(() => {
MyEvent.add('newTitle', replaceTitle)
})
onUnmounted(() => {
MyEvent.remove('newTitle', replaceTitle)
})
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.left-nav { .left-nav {
width: var(--left-nav-collapse-width, 30rem); width: var(--left-nav-collapse-width, 30rem);