main.ts 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. // Browser-only visual fixture. All /api requests stay in memory; no user data is changed.
  2. import {createApp, defineComponent, h, ref} from 'vue'
  3. import {createPinia} from 'pinia'
  4. import BotSettingsDialog from '@/components/workspace/BotSettingsDialog.vue'
  5. import SettingsCenterDialog from '@/components/app/SettingsCenterDialog.vue'
  6. import {useAuthStore} from '@/stores/auth'
  7. import '@/styles/tokens.css'
  8. import '@/styles/global.css'
  9. const query=new URLSearchParams(location.search)
  10. const names=['测试2','竹儿','测试','瑶儿']
  11. const agents=names.map((name,i)=>({id:`00000000-0000-4000-8000-00000000000${i+1}`,name,profile:'default',nodeId:'local',archived:false}))
  12. const conversations=[{id:'group-a',name:'方案分析团队',kind:'group',memberIds:agents.map(a=>a.id),archived:false},{id:'group-b',name:'内容运营组',kind:'group',memberIds:agents.slice(0,3).map(a=>a.id),archived:false}]
  13. const projects=query.has('empty')?[]:[
  14. {id:'project-a',name:'夭夭产品开发',description:'',memberIds:agents.map(a=>a.id),groupIds:['group-a','group-b'],revision:1,archived:false,createdAt:1,updatedAt:1},
  15. {id:'project-b',name:'内容运营',description:'',memberIds:agents.slice(0,3).map(a=>a.id),groupIds:['group-b'],revision:1,archived:false,createdAt:1,updatedAt:1},
  16. ]
  17. const identity={serverId:'00000000-0000-4000-8000-000000000099',name:'我的工作空间',displayName:'我的工作空间',revision:1}
  18. const realFetch=window.fetch.bind(window)
  19. window.fetch=async(input,init)=>{
  20. const url=new URL(typeof input==='string'?input:input instanceof URL?input.href:input.url,location.href)
  21. if(!url.pathname.startsWith('/api/'))return realFetch(input,init)
  22. const body=typeof init?.body==='string'?JSON.parse(init.body):{}
  23. let data:unknown
  24. if(url.pathname==='/api/app/capabilities')data={features:['bot-file-memory-v1']}
  25. else if(url.pathname==='/api/app/bootstrap')data={csrfToken:'fixture-only',userId:'fixture-user',authRequired:true}
  26. else if(url.pathname==='/api/app/agents')data={agents}
  27. else if(url.pathname==='/api/app/conversations')data={conversations}
  28. else if(url.pathname==='/api/app/workspace/projects'){
  29. if(init?.method==='POST'){
  30. const previous=projects.find(p=>p.id===body.id)
  31. const project={...body,id:body.id??crypto.randomUUID(),revision:(previous?.revision??0)+1,createdAt:1,updatedAt:1}
  32. if(previous)Object.assign(previous,project);else projects.push(project)
  33. data={project}
  34. }else data={projects}
  35. }else if(url.pathname.includes('/memory-jobs'))data={jobs:[]}
  36. else if(url.pathname.includes('/memories'))data={memories:[]}
  37. else if(url.pathname.includes('server-identity'))data=identity
  38. else if(url.pathname==='/api/app/computers')data={computers:[]}
  39. else if(url.pathname==='/api/app/admin/local-vm')data={configured:true,enabled:true,mode:'shared',maxInstances:2,idleStopMinutes:0,runtime:'docker',daemonUp:true,image:true,images:[{key:'standard',ready:true},{key:'cursor',ready:true}],instances:[]}
  40. else return new Response(JSON.stringify({error:{message:'此预览没有连接服务'}}),{status:404,headers:{'content-type':'application/json'}})
  41. return new Response(JSON.stringify(data),{headers:{'content-type':'application/json'}})
  42. }
  43. const theme=ref<'light'|'dark'|'system'>(query.get('theme')==='dark'?'dark':'light')
  44. function setTheme(value:'light'|'dark'|'system'){theme.value=value;document.documentElement.classList.toggle('dark',value==='dark')}
  45. setTheme(theme.value)
  46. const App=defineComponent({setup(){
  47. const auth=useAuthStore()
  48. auth.user={id:'fixture-user',username:'samien',role:query.has('member')?'member':'admin'} as never
  49. auth.status='authenticated';auth.serverIdentity=identity
  50. const opened=ref<'bot'|'personal'|null>(query.get('view')==='appearance'||query.get('view')==='profile'?'personal':'bot')
  51. return()=>h('main',{style:'min-height:100dvh;background:var(--settings-panel);padding:18px;box-sizing:border-box'},[
  52. h('div',{style:'display:flex;gap:12px;align-items:center;font:13px var(--font-ui)'},[
  53. h('span','界面验证 · 示例数据'),h('button',{onClick:()=>opened.value='bot'},'Bot 设置'),h('button',{onClick:()=>opened.value='personal'},'我的设置'),
  54. ]),
  55. opened.value==='bot'?h(BotSettingsDialog,{isAdmin:!query.has('member'),onClose:()=>opened.value=null}):null,
  56. h(SettingsCenterDialog,{open:opened.value==='personal',initialPage:query.get('view')==='profile'?'account-profile':'appearance',isAdmin:!query.has('member'),botMode:true,userName:'samien',theme:theme.value==='dark'?'dark':'light',themePreference:theme.value,profiles:[{name:'default',agentName:'默认机器人',isDefault:true}],activeProfile:{name:'default',agentName:'默认机器人',isDefault:true},onClose:()=>opened.value=null,'onSet-theme':setTheme}),
  57. ])
  58. }})
  59. createApp(App).use(createPinia()).mount('#app')