Merge branch 'main' of ssh://18.167.251.121:10002/aidlab/FiDA_Front
This commit is contained in:
@@ -101,12 +101,15 @@ export class AISelectboxToolManager {
|
||||
}
|
||||
createIndicatorObject() {
|
||||
this.clearIndicatorObject()
|
||||
var color = 'rgba(0, 255, 0, 0.5)'
|
||||
if (this.toolManager.currentTool.value === OperationType.AISELECT_REMOVE) {
|
||||
color = 'rgba(255, 0, 0, 0.5)'
|
||||
}
|
||||
const rect = new fabric.Rect({
|
||||
left: this.startX,
|
||||
top: this.startY,
|
||||
width: 0,
|
||||
height: 0,
|
||||
fill: 'transparent',
|
||||
fill: color,
|
||||
stroke: '#000',
|
||||
strokeWidth: 1,
|
||||
evented: false,
|
||||
@@ -179,10 +182,10 @@ export class AISelectboxToolManager {
|
||||
mouseMoveEvent(e) {
|
||||
if (!this.targetObject) return;
|
||||
if (!this.isDragging) return;
|
||||
var width = e.absolutePointer.x - this.startX
|
||||
var height = e.absolutePointer.y - this.startY
|
||||
var left = this.startX
|
||||
var top = this.startY
|
||||
let width = e.absolutePointer.x - this.startX
|
||||
let height = e.absolutePointer.y - this.startY
|
||||
let left = this.startX
|
||||
let top = this.startY
|
||||
if (width < 0) {
|
||||
left += width
|
||||
width = -width
|
||||
|
||||
@@ -17,7 +17,7 @@ fabric.Object.prototype.toObject = function () {
|
||||
const arr = [...fabric.Object.prototype.customProperties]
|
||||
args.forEach(v => (Array.isArray(v) ? arr.push(...v) : arr.push(v)))
|
||||
if (this.fill?.source === null) {
|
||||
let image = new Image()
|
||||
const image = new Image()
|
||||
image.crossOrigin = 'anonymous'
|
||||
image.src = this.info?.fill?.source
|
||||
this.fill.source = image
|
||||
@@ -65,17 +65,17 @@ export class CanvasManager {
|
||||
}
|
||||
}
|
||||
setCanvasViewSize(options) {
|
||||
var canvasViewWidth = options.canvasViewWidth || 1920
|
||||
var canvasViewHeight = options.canvasViewHeight || 1080
|
||||
const canvasViewWidth = options.canvasViewWidth || 1920
|
||||
const canvasViewHeight = options.canvasViewHeight || 1080
|
||||
this.canvas.setWidth(canvasViewWidth)
|
||||
this.canvas.setHeight(canvasViewHeight)
|
||||
}
|
||||
/** 初始化画布 */
|
||||
async initCanvas(options: CanvasInitOptions) {
|
||||
this.layerManager = this.stateManager.layerManager
|
||||
var canvasWidth = options.canvasWidth || 750
|
||||
var canvasHeight = options.canvasHeight || 600
|
||||
var image = null;
|
||||
let canvasWidth = options.canvasWidth || 750
|
||||
let canvasHeight = options.canvasHeight || 600
|
||||
let image = null;
|
||||
if (options.url) {
|
||||
await new Promise((resolve) => {
|
||||
fabric.Image.fromURL(options.url, async (img) => {
|
||||
@@ -101,8 +101,6 @@ export class CanvasManager {
|
||||
})
|
||||
}
|
||||
this.canvas = createCanvas(options.canvasRef.value, {
|
||||
preserveObjectStacking: true,
|
||||
enableRetinaScaling: true,
|
||||
backgroundColor: '#fff',
|
||||
})
|
||||
if (image) {
|
||||
@@ -188,8 +186,8 @@ export class CanvasManager {
|
||||
async updateSubLayerClipPath() {
|
||||
const objects = this.getObjects().filter((v: any) => v.type !== "group" && !!v.info?.id);
|
||||
for (let i = 0; i < objects.length; i++) {
|
||||
let object = objects[i]
|
||||
let path = this.getObjectById(object.info.parentId)?.clipPath
|
||||
const object = objects[i]
|
||||
const path = this.getObjectById(object.info.parentId)?.clipPath
|
||||
object.set({ clipPath: path || null })
|
||||
}
|
||||
this.renderAll()
|
||||
@@ -381,7 +379,7 @@ export class CanvasManager {
|
||||
}
|
||||
/** 处理JSON为正常画布 */
|
||||
processCanvasDisUrlJSON(obj: { canvas: string, images: Object }) {
|
||||
var json = obj.canvas;
|
||||
let json = obj.canvas;
|
||||
const images = obj.images || {}
|
||||
for (const key in images) {
|
||||
json = json.replace(new RegExp(key), images[key])
|
||||
|
||||
@@ -64,10 +64,10 @@ export class LayerManager {
|
||||
getLayerById(id) {
|
||||
function call(arr) {
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
let v = arr[i]
|
||||
const v = arr[i]
|
||||
if (v.info.id === id) return v
|
||||
if (v.children) {
|
||||
let layer = call(v.children)
|
||||
const layer = call(v.children)
|
||||
if (layer) return layer
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,8 +220,8 @@ export class ObjectManager {
|
||||
const isWidth = object.hasOwnProperty('width')
|
||||
const isHeight = object.hasOwnProperty('height')
|
||||
if (isWidth || isHeight) {
|
||||
let width = options.width
|
||||
let height = options.height
|
||||
const width = isWidth ? options.width : object.width
|
||||
const height = isHeight ? options.height : object.height
|
||||
if (type === "polygon") {
|
||||
if (object.points.length === 10) {// 五角星
|
||||
options.points = getStarArr(width, height)
|
||||
|
||||
@@ -58,10 +58,10 @@ export class ShapeToolManager {
|
||||
}
|
||||
mouseMoveEvent(e) {
|
||||
if (!this.isDragging) return;
|
||||
var width = e.absolutePointer.x - this.startX
|
||||
var height = e.absolutePointer.y - this.startY
|
||||
var left = this.startX
|
||||
var top = this.startY
|
||||
let width = e.absolutePointer.x - this.startX
|
||||
let height = e.absolutePointer.y - this.startY
|
||||
let left = this.startX
|
||||
let top = this.startY
|
||||
if (width < 0) {
|
||||
left += width
|
||||
width = -width
|
||||
|
||||
@@ -89,7 +89,7 @@ export class StateManager {
|
||||
/** 撤回状态 */
|
||||
undoState() {
|
||||
if (this.running.value) return
|
||||
var index = this.historyIndex.value - 1
|
||||
const index = this.historyIndex.value - 1
|
||||
const state = this.historyList.value[index]
|
||||
if (!state) return
|
||||
this.running.value = true
|
||||
@@ -103,7 +103,7 @@ export class StateManager {
|
||||
/** 重做状态 */
|
||||
redoState() {
|
||||
if (this.running.value) return
|
||||
var index = this.historyIndex.value + 1
|
||||
const index = this.historyIndex.value + 1
|
||||
const state = this.historyList.value[index]
|
||||
if (!state) return
|
||||
this.running.value = true
|
||||
|
||||
@@ -6,8 +6,9 @@ import { fabric } from "fabric-with-all";
|
||||
export const createCanvas = (elementId, options = {}) => {
|
||||
// Create the canvas instance
|
||||
const canvas = new fabric.Canvas(elementId, {
|
||||
enableRetinaScaling: true,
|
||||
renderOnAddRemove: false,
|
||||
controlsAboveOverlay: true,// 控制面板在图层之上
|
||||
enableRetinaScaling: true,// 启用Retina缩放
|
||||
renderOnAddRemove: false,// 不在添加或移除对象时重新渲染
|
||||
preserveObjectStacking: true, // 保持对象堆叠顺序
|
||||
// skipOffscreen: true, // 跳过离屏渲染
|
||||
imageSmoothingEnabled: true, // 启用图像平滑 - 抗锯齿
|
||||
@@ -26,7 +27,7 @@ export const createCanvas = (elementId, options = {}) => {
|
||||
*/
|
||||
export const createStaticCanvas = (elementId, options = {}) => {
|
||||
const canvas = new fabric.StaticCanvas(elementId, {
|
||||
enableRetinaScaling: true,
|
||||
enableRetinaScaling: true,// 启用Retina缩放
|
||||
imageSmoothingEnabled: true, // 启用图像平滑 - 抗锯齿
|
||||
imageSmoothingQuality: "high", // 设置高质量图像平滑
|
||||
skipOffscreen: false, // 不跳过离屏渲染
|
||||
|
||||
@@ -16,8 +16,8 @@ export const initThree = (threeDom)=>{
|
||||
/**
|
||||
* 创建渲染器对象
|
||||
*/
|
||||
let width = threeDom.offsetWidth; //窗口宽度
|
||||
let height = threeDom.offsetHeight; //窗口高度
|
||||
const width = threeDom.offsetWidth; //窗口宽度
|
||||
const height = threeDom.offsetHeight; //窗口高度
|
||||
const renderer = new THREE.WebGLRenderer({
|
||||
antialias: true,
|
||||
logarithmicDepthBuffer: true,//深度缓存 防止模型闪烁重影
|
||||
@@ -35,9 +35,9 @@ export const initThree = (threeDom)=>{
|
||||
|
||||
// 设置渲染器大小
|
||||
//环境光
|
||||
let ambient = new THREE.AmbientLight(0xffffff,.8);
|
||||
const ambient = new THREE.AmbientLight(0xffffff,.8);
|
||||
scene.add(ambient);
|
||||
let controls = new OrbitControls(camera,renderer.domElement)//监听鼠标、键盘事件;
|
||||
const controls = new OrbitControls(camera,renderer.domElement)//监听鼠标、键盘事件;
|
||||
// controls.minDistance = 500; // 设置相机与焦点的最小距离
|
||||
// controls.maxDistance = 4000; // 设置相机与焦点的最大距离
|
||||
controls.mouseButtons = {
|
||||
@@ -166,14 +166,14 @@ export const addModel = async (
|
||||
load: any
|
||||
) => {
|
||||
await new Promise((resolve, reject) => {
|
||||
var fbxLoader = new GLTFLoader();
|
||||
let drac = new DRACOLoader()
|
||||
const fbxLoader = new GLTFLoader();
|
||||
const drac = new DRACOLoader()
|
||||
drac.setDecoderPath('/draco/')
|
||||
fbxLoader.setDRACOLoader(drac)
|
||||
|
||||
fbxLoader.load(url,
|
||||
(obj: any) => {
|
||||
let scene = obj.scene;
|
||||
const scene = obj.scene;
|
||||
scene.traverse((child: any) => {
|
||||
if (child.isMesh) {
|
||||
// 如果是基础材质,转换为标准材质
|
||||
|
||||
@@ -27,13 +27,13 @@ export class GenerateManager {
|
||||
async getTasksIdImg() {
|
||||
clearInterval(this.getTaskIdsImgTime)
|
||||
this.getTaskIdsImgTime = setInterval(()=>{
|
||||
let taskIds = this.taskIds.map((item)=>item.taskId)
|
||||
const taskIds = this.taskIds.map((item)=>item.taskId)
|
||||
getTaskidResult({taskIds}).then((rv:any)=>{
|
||||
//找出成功和失败的任务
|
||||
let returnedTasks = rv.filter((item)=>item.status == 'RETURNED' || item.status == 'FAILED')
|
||||
const returnedTasks = rv.filter((item)=>item.status == 'RETURNED' || item.status == 'FAILED')
|
||||
if(returnedTasks.length == 0)return
|
||||
//剔除调成功的
|
||||
let taskIds_ = JSON.parse(JSON.stringify(this.taskIds))
|
||||
const taskIds_ = JSON.parse(JSON.stringify(this.taskIds))
|
||||
this.taskIds = taskIds_.filter(itemA =>
|
||||
!returnedTasks.some(itemB => itemB.taskId === itemA.taskId)
|
||||
)
|
||||
|
||||
@@ -142,7 +142,7 @@ export class NodeManager {
|
||||
|
||||
copyNodeById(id: string) {
|
||||
const node = this.stateManager.getNodeById(id)
|
||||
let copyNode = JSON.parse(JSON.stringify(node))
|
||||
const copyNode = JSON.parse(JSON.stringify(node))
|
||||
const flowNode = this.stateManager.flowManager.getNodeById(id)
|
||||
if (!node) return console.warn(`${id}找不到对应节点`)
|
||||
if (node.data?.disableCopy) return console.warn(`${id}节点已禁用复制`)
|
||||
|
||||
@@ -276,7 +276,7 @@ export class StateManager {
|
||||
}
|
||||
/** 撤回状态 */
|
||||
undoState() {
|
||||
var index = this.historyIndex.value - 1
|
||||
const index = this.historyIndex.value - 1
|
||||
const state = this.historyList.value[index]
|
||||
if (!state) return
|
||||
this.historyIndex.value = index
|
||||
@@ -285,7 +285,7 @@ export class StateManager {
|
||||
}
|
||||
/** 重做状态 */
|
||||
redoState() {
|
||||
var index = this.historyIndex.value + 1
|
||||
const index = this.historyIndex.value + 1
|
||||
const state = this.historyList.value[index]
|
||||
if (!state) return
|
||||
this.historyIndex.value = index
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
// 定义要忽略的警告关键词列表
|
||||
const ignoredWarnings = [
|
||||
// '`markRaw` or using `shallowRef` instead of `ref`',
|
||||
]
|
||||
|
||||
/** 忽略组件响应式警告 */
|
||||
export default function (app) {
|
||||
// 只忽略组件响应式警告
|
||||
app.config.warnHandler = (msg, instance, trace) => {
|
||||
// 检查是否包含要忽略的关键词
|
||||
const shouldIgnore = ignoredWarnings.some(warning =>
|
||||
msg.includes(warning)
|
||||
)
|
||||
// 如果不应该忽略,才输出警告
|
||||
if (!shouldIgnore) {
|
||||
console.warn(msg, instance, trace)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,10 +16,8 @@ import "./router/router-config" // 路由守卫,做动态路由的地方
|
||||
import ElementPlus from 'element-plus'
|
||||
import 'element-plus/dist/index.css'
|
||||
|
||||
import ignoredWarning from './ignoredWarning'
|
||||
|
||||
const app = createApp(App)
|
||||
ignoredWarning(app)
|
||||
app.use(router)
|
||||
.use(directives)
|
||||
.use(ElementPlus)
|
||||
|
||||
@@ -5,7 +5,6 @@ import { ref, computed } from 'vue'
|
||||
import { removeLocal, setLocal } from '@/utils/local'
|
||||
import MyEvent from '@/utils/myEvent'
|
||||
|
||||
|
||||
// Agent 项目初始数据 store
|
||||
type InitialProjectData = {
|
||||
text: string
|
||||
@@ -13,13 +12,13 @@ type InitialProjectData = {
|
||||
type: string
|
||||
area: string
|
||||
style: string
|
||||
useReport:boolean
|
||||
needSuggestion:boolean
|
||||
useReport: boolean
|
||||
needSuggestion: boolean
|
||||
quoteList: Array<string>
|
||||
tempImages: any[]
|
||||
}
|
||||
export const useAgentStore = defineStore('agent', () => {
|
||||
const initialProjectData = ref<InitialProjectData | null>(null)
|
||||
const initialProjectData = ref<InitialProjectData | null>(null)
|
||||
|
||||
// 保存项目初始数据
|
||||
const setInitialProjectData = (data: InitialProjectData) => {
|
||||
@@ -34,10 +33,94 @@ export const useAgentStore = defineStore('agent', () => {
|
||||
initialProjectData.value = null
|
||||
}
|
||||
|
||||
// 会话缓存管理,最多保存 10 条会话
|
||||
const conversationCache = new Map<string, any>()
|
||||
const MAX_CACHE_ENTRIES = 10
|
||||
const SESSION_KEY_PREFIX = 'agent_session_'
|
||||
|
||||
const pruneCache = () => {
|
||||
const keys = Array.from(conversationCache.keys())
|
||||
const total = conversationCache.size
|
||||
if (total <= MAX_CACHE_ENTRIES) return
|
||||
|
||||
for (let i = 0; i < total - MAX_CACHE_ENTRIES; i++) {
|
||||
conversationCache.delete(keys[i])
|
||||
sessionStorage.removeItem(SESSION_KEY_PREFIX + keys[i])
|
||||
}
|
||||
}
|
||||
|
||||
const saveCacheConversation = (projectId: string, data: any) => {
|
||||
if (!projectId) return
|
||||
|
||||
const finalData = {
|
||||
...data,
|
||||
updatedAt: Date.now()
|
||||
}
|
||||
|
||||
if (conversationCache.has(projectId)) {
|
||||
conversationCache.delete(projectId)
|
||||
}
|
||||
|
||||
conversationCache.set(projectId, finalData)
|
||||
try {
|
||||
sessionStorage.setItem(SESSION_KEY_PREFIX + projectId, JSON.stringify(finalData))
|
||||
} catch (e) {
|
||||
console.warn('saveCacheConversation sessionStorage failed', e)
|
||||
}
|
||||
|
||||
pruneCache()
|
||||
}
|
||||
|
||||
const getCacheConversation = (projectId: string) => {
|
||||
if (!projectId) return null
|
||||
|
||||
let data = conversationCache.get(projectId)
|
||||
if (data) return data
|
||||
|
||||
try {
|
||||
const raw = sessionStorage.getItem(SESSION_KEY_PREFIX + projectId)
|
||||
if (!raw) return null
|
||||
data = JSON.parse(raw)
|
||||
conversationCache.set(projectId, data)
|
||||
return data
|
||||
} catch (e) {
|
||||
console.warn('getCacheConversation failed', e)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
const clearAllCacheConversations = () => {
|
||||
conversationCache.value.clear()
|
||||
for (const key in window.sessionStorage) {
|
||||
if (key.startsWith(SESSION_KEY_PREFIX)) {
|
||||
sessionStorage.removeItem(key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const removeCacheConversation = (projectId: string) => {
|
||||
if (!projectId) return
|
||||
conversationCache.value.delete(projectId)
|
||||
sessionStorage.removeItem(SESSION_KEY_PREFIX + projectId)
|
||||
}
|
||||
|
||||
const getCacheStats = () => {
|
||||
return {
|
||||
total: conversationCache.value.size,
|
||||
keys: Array.from(conversationCache.value.keys())
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
initialProjectData,
|
||||
setInitialProjectData,
|
||||
getInitialProjectData,
|
||||
clearInitialProjectData
|
||||
clearInitialProjectData,
|
||||
conversationCache,
|
||||
saveCacheConversation,
|
||||
getCacheConversation,
|
||||
removeCacheConversation,
|
||||
clearAllCacheConversations,
|
||||
getCacheStats
|
||||
}
|
||||
})
|
||||
|
||||
@@ -19,7 +19,7 @@ export const useVersionTreeStore = defineStore('versionTree', () => {
|
||||
})
|
||||
|
||||
const setNodeDetail = (v: any) => {
|
||||
for(let key in v){
|
||||
for(const key in v){
|
||||
state.value.nodeDetail[key] = v[key]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,8 +114,8 @@ service.interceptors.response.use(
|
||||
return Promise.reject(false)
|
||||
}
|
||||
error.config && removePending(error.config)
|
||||
console.log('err' + error) // for debug
|
||||
ElMessage.error(error.message)
|
||||
// console.log('err', error) // for debug
|
||||
ElMessage.error(error.response?.data?.message || error.message)
|
||||
}
|
||||
return Promise.reject(error)
|
||||
}
|
||||
|
||||
@@ -80,6 +80,71 @@
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
const saveSession = (projectId: string) => {
|
||||
if (!projectId) return
|
||||
agentStore.saveCacheConversation(projectId, {
|
||||
messageList: messageList.value,
|
||||
sketchList: sketchList.value,
|
||||
params: {
|
||||
...params,
|
||||
projectID: projectId
|
||||
},
|
||||
isGenerating: isGenerating.value,
|
||||
isPaused: isPaused.value
|
||||
})
|
||||
}
|
||||
|
||||
const restoreSession = (projectId: string) => {
|
||||
if (!projectId) return false
|
||||
const payload = agentStore.getCacheConversation(projectId)
|
||||
if (!payload) return false
|
||||
|
||||
messageList.value = payload.messageList || []
|
||||
sketchList.value = payload.sketchList || []
|
||||
if (payload.params) {
|
||||
params.projectID = payload.params.projectID || projectId
|
||||
params.message = payload.params.message || ''
|
||||
params.versionID = payload.params.versionID || ''
|
||||
params.configParams = payload.params.configParams || params.configParams
|
||||
params.needSuggestion = payload.params.needSuggestion || false
|
||||
params.useReport = payload.params.useReport || false
|
||||
params.imageUrlList = payload.params.imageUrlList || []
|
||||
params.quotaUrl = payload.params.quotaUrl || []
|
||||
}
|
||||
isGenerating.value = payload.isGenerating || false
|
||||
isPaused.value = payload.isPaused || false
|
||||
return true
|
||||
}
|
||||
|
||||
const clearSession = (projectId: string) => {
|
||||
if (!projectId) return
|
||||
agentStore.removeCacheConversation(projectId)
|
||||
}
|
||||
|
||||
const handleReset = (force = false) => {
|
||||
if (!force && params.projectID) {
|
||||
saveSession(params.projectID)
|
||||
}
|
||||
if (force && params.projectID) {
|
||||
clearSession(params.projectID)
|
||||
}
|
||||
|
||||
messageList.value = []
|
||||
sketchList.value = []
|
||||
params.versionID = ''
|
||||
params.imageUrlList = []
|
||||
params.quotaUrl = []
|
||||
params.needSuggestion = false
|
||||
params.useReport = false
|
||||
params.configParams = {
|
||||
type: '',
|
||||
region: '',
|
||||
style: ''
|
||||
}
|
||||
isGenerating.value = false
|
||||
isPaused.value = false
|
||||
}
|
||||
|
||||
// 每次请求时创建新的 AbortController
|
||||
let abort: AbortController
|
||||
|
||||
@@ -93,10 +158,15 @@
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
if (params.projectID) {
|
||||
saveSession(params.projectID)
|
||||
}
|
||||
abort?.abort()
|
||||
MyEvent.remove('resetAgent', handleReset)
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
MyEvent.add('resetAgent', handleReset)
|
||||
// 检查 store 中是否有初始项目数据
|
||||
// projectStore.setId('1') // 临时设置项目ID为1,实际应用中应根据上下文动态设置
|
||||
const initialData = agentStore.getInitialProjectData
|
||||
@@ -353,10 +423,7 @@
|
||||
})
|
||||
}
|
||||
})
|
||||
// 通知 Preview 有新 sketch 正在加载,传入 sketch 索引
|
||||
MyEvent.emit('loading-sketch', sketchList.value.length - 1)
|
||||
MyEvent.emit('OpenSketch')
|
||||
// contentBody += `<slot slot-name="sketch"></slot>`
|
||||
}
|
||||
if (eventName === 'reportName' || eventName === 'reportTitle') {
|
||||
aiMessage.reportName = jsonData.reportName || jsonData.reportTitle
|
||||
@@ -438,6 +505,9 @@
|
||||
isPaused.value = true
|
||||
isGenerating.value = false
|
||||
abort?.abort()
|
||||
if (params.projectID) {
|
||||
saveSession(params.projectID)
|
||||
}
|
||||
MyEvent.emit('stopChat')
|
||||
}
|
||||
|
||||
@@ -470,13 +540,7 @@
|
||||
}
|
||||
|
||||
// 处理对话列表,将连续的 assistant 消息合并为一条
|
||||
const processDialogue = (
|
||||
dialogue,
|
||||
startIndex,
|
||||
existingImgList,
|
||||
sessionId,
|
||||
firstReportIndex = -1
|
||||
) => {
|
||||
const processDialogue = (dialogue, startIndex, existingImgList, sessionId) => {
|
||||
if (!dialogue || dialogue.length === 0) return []
|
||||
|
||||
const result = []
|
||||
@@ -485,7 +549,6 @@
|
||||
while (i < dialogue.length) {
|
||||
const item = dialogue[i]
|
||||
if (item.role === 'user') {
|
||||
// user 角色直接添加
|
||||
result.push({
|
||||
...item,
|
||||
text: item.content,
|
||||
@@ -495,47 +558,47 @@
|
||||
})
|
||||
i++
|
||||
} else if (item.role === 'assistant') {
|
||||
// assistant 角色,拼接直到下一个 user
|
||||
|
||||
let combinedContent = item.content || ''
|
||||
let combinedThinkingText = item.reasoning || ''
|
||||
let combinedImageUrl = item.image_url || null
|
||||
let reportName = item.reportName || null
|
||||
let webAddress = item.webAddress || null
|
||||
// 继续往后找连续的 assistant 消息
|
||||
let combinedReport = item.report || ''
|
||||
let hasReportSlot = !!item.report
|
||||
let hasUrlSlot = !!item.webAddress
|
||||
|
||||
let j = i + 1
|
||||
while (j < dialogue.length && dialogue[j].role === 'assistant') {
|
||||
combinedContent += dialogue[j].content || ''
|
||||
combinedThinkingText += dialogue[j].reasoning || ''
|
||||
// 如果有 image_url 则保留
|
||||
if (dialogue[j].image_url) {
|
||||
combinedImageUrl = dialogue[j].image_url
|
||||
}
|
||||
if (dialogue[j].reportName) {
|
||||
reportName = dialogue[j].reportName
|
||||
}
|
||||
if (dialogue[j].webAddress) {
|
||||
combinedContent += `<slot slot-name="url"></slot>`
|
||||
webAddress = dialogue[j].webAddress
|
||||
// console.log('webAddress22222222222222', dialogue[j].webAddress)
|
||||
// debugger
|
||||
const next = dialogue[j]
|
||||
combinedContent += next.content || ''
|
||||
combinedThinkingText += next.reasoning || ''
|
||||
combinedReport += next.report || ''
|
||||
if (next.image_url) combinedImageUrl = next.image_url
|
||||
if (next.reportName) reportName = next.reportName
|
||||
if (next.report) hasReportSlot = true
|
||||
if (next.webAddress) {
|
||||
webAddress = next.webAddress
|
||||
hasUrlSlot = true
|
||||
}
|
||||
j++
|
||||
}
|
||||
|
||||
// 如果 firstReportIndex 在当前合并范围内,则把 slot 追加到末尾
|
||||
if (firstReportIndex >= i && firstReportIndex < j) {
|
||||
if (hasUrlSlot) {
|
||||
combinedContent += `<slot slot-name="url"></slot>`
|
||||
}
|
||||
if (hasReportSlot) {
|
||||
combinedContent += `<slot slot-name="card" title="Report" content="Report"></slot>`
|
||||
}
|
||||
|
||||
result.push({
|
||||
...item,
|
||||
reportName,
|
||||
report: combinedReport,
|
||||
content: combinedContent,
|
||||
thinkingText: combinedThinkingText,
|
||||
text: combinedContent,
|
||||
image_url: combinedImageUrl,
|
||||
webAddress: !!webAddress ? JSON.parse(webAddress) : null,
|
||||
webAddress: webAddress ? JSON.parse(webAddress) : null,
|
||||
isUser: false,
|
||||
id: result.length + 1,
|
||||
sessionId: sessionId
|
||||
@@ -543,7 +606,6 @@
|
||||
|
||||
i = j
|
||||
} else {
|
||||
// 其他角色直接添加
|
||||
result.push({
|
||||
...item,
|
||||
text: item.content,
|
||||
@@ -560,35 +622,11 @@
|
||||
const processSession = (session, imgList, ancestorsList, idCounterRef) => {
|
||||
if (!session) return
|
||||
|
||||
// 1. 找到第一个 report 项的索引,供 processDialogue 使用
|
||||
let firstReportIndex = -1
|
||||
if (session.dialogue) {
|
||||
for (let i = 0; i < session.dialogue.length; i++) {
|
||||
if (session.dialogue[i].report) {
|
||||
firstReportIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 收集 report 内容并保存到 sessionStorage
|
||||
let reportStr = ''
|
||||
session.dialogue?.forEach((item) => {
|
||||
if (item.report) {
|
||||
reportStr += item.report
|
||||
}
|
||||
})
|
||||
if (reportStr && session.id) {
|
||||
sessionStorage.setItem(`reportsContent_${session.id}`, reportStr)
|
||||
}
|
||||
|
||||
// 3. 收集 sketchIDAndUrl 到 imgList
|
||||
if (session.sketchIDAndUrl) {
|
||||
imgList.push(session.sketchIDAndUrl)
|
||||
}
|
||||
|
||||
// 4. 处理 dialogue
|
||||
const list = processDialogue(session.dialogue, 0, imgList, session.id, firstReportIndex)
|
||||
const list = processDialogue(session.dialogue, 0, imgList, session.id)
|
||||
list.forEach((el) => {
|
||||
el.id = idCounterRef.value++
|
||||
})
|
||||
@@ -636,6 +674,7 @@
|
||||
item.text += `<slot slot-name="sketch"></slot>`
|
||||
}
|
||||
})
|
||||
console.log('ancestorslist', ancestorsList)
|
||||
messageList.value = [...ancestorsList]
|
||||
params.versionID = current?.id
|
||||
sketchList.value = imgList
|
||||
@@ -643,7 +682,10 @@
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
setChatInfo
|
||||
setChatInfo,
|
||||
saveSession,
|
||||
restoreSession,
|
||||
clearSession
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@@ -161,12 +161,13 @@
|
||||
const quotaList = props.content.image_url ?? []
|
||||
list.push(...quotaList)
|
||||
}
|
||||
|
||||
if (!imageUrls || imageUrls.length === 0) return list
|
||||
imageUrls.forEach((item) => {
|
||||
imageUrls?.forEach((item) => {
|
||||
if (typeof item === 'string') {
|
||||
list.push(item)
|
||||
} else if (typeof item === 'object' && item.url) {
|
||||
list.push(item.url)
|
||||
} else if (typeof item === 'object' && item?.url) {
|
||||
list.push(item?.url)
|
||||
}
|
||||
})
|
||||
return list
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="agent-list flex flex-col flex-1" ref="listContainer">
|
||||
<Item
|
||||
v-for="(message, index) in messageList"
|
||||
:key="message.id"
|
||||
:key="message.id + index"
|
||||
:content="message"
|
||||
:is-last="index === messageList.length - 1"
|
||||
@regenerate="$emit('regenerate', message)"
|
||||
|
||||
@@ -44,10 +44,7 @@
|
||||
<img src="@/assets/images/arrow-top-right.png" />
|
||||
</div>
|
||||
<!-- 已加载完成的 sketch 显示实际图片 -->
|
||||
<img
|
||||
v-img-loading="getImageSrc(item, index)"
|
||||
@load="handleImageLoad(index)"
|
||||
/>
|
||||
<img v-img-loading="getImageSrc(item, index)" @load="handleImageLoad(index)" />
|
||||
<!-- 正在加载的 sketch 显示 loading gif overlay -->
|
||||
<!-- <div v-if="pendingSketchIndexes.includes(index)" class="loading-wrapper">
|
||||
<img src="@/assets/images/sketch-loading.gif" alt="loading" />
|
||||
@@ -118,8 +115,6 @@
|
||||
// 存储每个图片的加载状态
|
||||
const loadedStatus = ref<boolean[]>([])
|
||||
|
||||
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
type: 'sketch' | 'report' | 'url'
|
||||
@@ -187,8 +182,9 @@
|
||||
sessionId.value = id
|
||||
}
|
||||
|
||||
const setReportTitle = (title: string) => {
|
||||
const setReport = (title: string, content: string) => {
|
||||
reportTitle.value = title
|
||||
markdownContent.value = content
|
||||
}
|
||||
|
||||
const setUrls = async (list: string[]) => {
|
||||
@@ -196,14 +192,14 @@
|
||||
const res = await fetchUrlTitle(list)
|
||||
urlList.value = res
|
||||
}
|
||||
watch(
|
||||
() => sessionId.value,
|
||||
(newVal) => {
|
||||
if (newVal) {
|
||||
markdownContent.value = sessionStorage.getItem(`reportsContent_${newVal}`)
|
||||
}
|
||||
}
|
||||
)
|
||||
// watch(
|
||||
// () => sessionId.value,
|
||||
// (newVal) => {
|
||||
// if (newVal) {
|
||||
// markdownContent.value = sessionStorage.getItem(`reportsContent_${newVal}`)
|
||||
// }
|
||||
// }
|
||||
// )
|
||||
|
||||
// 图片加载完成时触发
|
||||
const handleImageLoad = (index: number) => {
|
||||
@@ -264,15 +260,6 @@
|
||||
URL.revokeObjectURL(url)
|
||||
}
|
||||
|
||||
const showLoading = ref(false)
|
||||
const handleLoadingSketch = (sketchIndex?: number) => {
|
||||
showLoading.value = true
|
||||
// 记录正在加载的 sketch 索引
|
||||
// if (sketchIndex !== undefined) {
|
||||
// pendingSketchIndexes.value.push(sketchIndex)
|
||||
// }
|
||||
}
|
||||
|
||||
const handleClickUrl = (item: { url: string; title: string }) => {
|
||||
window.open(item.url, '_blank')
|
||||
}
|
||||
@@ -316,17 +303,11 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
onMounted(() => {
|
||||
MyEvent.add('loading-sketch', handleLoadingSketch)
|
||||
})
|
||||
onUnmounted(() => {
|
||||
MyEvent.remove('loading-sketch', handleLoadingSketch)
|
||||
})
|
||||
|
||||
defineExpose({
|
||||
setSessionId,
|
||||
setUrls,
|
||||
setReportTitle
|
||||
setReport
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@
|
||||
|
||||
const handleOpenReport = (data) => {
|
||||
previewRef.value.setSessionId(data.sessionId)
|
||||
previewRef.value.setReportTitle(data.reportName)
|
||||
previewRef.value.setReport(data.reportName, data.report)
|
||||
previewType.value = 'report'
|
||||
}
|
||||
|
||||
@@ -131,10 +131,25 @@
|
||||
|
||||
watch(
|
||||
() => proJectId.value,
|
||||
(newVal, oldVal) => {
|
||||
async (newVal, oldVal) => {
|
||||
if (oldVal && agentRef.value && typeof agentRef.value.saveSession === 'function') {
|
||||
agentRef.value.saveSession(oldVal as string)
|
||||
}
|
||||
|
||||
projectStore.clearProject()
|
||||
|
||||
if (newVal) {
|
||||
handleGetProjectInfoAndHistory()
|
||||
let restored = false
|
||||
if (agentRef.value && typeof agentRef.value.restoreSession === 'function') {
|
||||
restored = await agentRef.value.restoreSession(newVal as string)
|
||||
}
|
||||
|
||||
if (!restored) {
|
||||
handleGetProjectInfoAndHistory()
|
||||
}
|
||||
|
||||
MyEvent.emit('projectChange')
|
||||
} else {
|
||||
MyEvent.emit('projectChange')
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user