dsh-sa-workbench 0.1.28 → 0.1.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,7 +4,9 @@
4
4
 
5
5
  需求总览、版本计划、业务资料上传、需求/高阶方案/PRD/原型、节点 Skill、文档历史和交付归档在一个包里同步更新。复用 DSH 的模型、会话、权限和工具,不包含模型凭据或业务资料。
6
6
 
7
- 首次打开 SA 工作台会进入目录设置。选择资料工作目录,保存后按提示完整重启 DSH。默认提供的目录也可以直接确认。插件更新、回退和卸载保留工作目录及配置。
7
+ 首次打开 SA 工作台会进入目录设置。确认默认目录后直接进入需求总览;选择其他工作目录后,按提示完整退出并重新打开 DSH。新用户默认亮色,用户主动选择的暗色偏好保留。插件更新、回退和卸载保留工作目录及配置。
8
+
9
+ 工作台统一提供需求、知识库、归档库与工作方法导航。需求总览支持表格和看板;详情页以阶段图标和分段连线导航,未生成时展示交付预览及开始操作。助手按需展开,复用原需求会话。文档尚未保存时切换顶部页面,会提示继续编辑或放弃修改后离开。
8
10
 
9
11
  需要 Node 24.9+ 运行时与 DSH 0.2.2-rc.1 系列;当前实机验证版本以发布验收文档为准,版本范围不代表所有未来宿主均已测试。
10
12
 
package/client.js CHANGED
@@ -36,7 +36,7 @@ window.__ModuleLoader__.load({
36
36
  return function(){if(previousShell===undefined)delete root.dataset.saShell;else root.dataset.saShell=previousShell;if(previousAppearance===undefined)delete root.dataset.saAppearance;else root.dataset.saAppearance=previousAppearance}
37
37
  }
38
38
  function toggleSaAppearance(){var next=(pmBus.state.appearance || saAppearance())==='dark'?'light':'dark';try{localStorage.setItem('sa-workbench-appearance',next)}catch(err){}pmBus.set({appearance:next})}
39
- var CLIENT_VERSION = '0.1.28'
39
+ var CLIENT_VERSION = '0.1.29'
40
40
 
41
41
  // A session may disappear or fail to open after selection. Keep failures
42
42
  // inside the conversation pane, and release even a rejected/pending ref.
@@ -1788,6 +1788,7 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
1788
1788
  edit: 'M12 20H4V12M9 15l3-.5L21 6l-3-3-8.5 9z', list: 'M8 5h13M8 12h13M8 19h13M3 5h.01M3 12h.01M3 19h.01',
1789
1789
  chat: 'M4 4h16v12H9l-5 4z', expand: 'M8 3H3v5M16 3h5v5M21 16v5h-5M3 16v5h5', focus: 'M4 4h16v16H4zM15 4v16', history: 'M3 10a9 9 0 1 1 2 9M3 3v7h7M12 7v5l3 2',
1790
1790
  check: 'M5 12l4 4L19 6', link: 'M10 13a5 5 0 0 0 7 0l4-4a5 5 0 0 0-7-7l-2 2M14 11a5 5 0 0 0-7 0l-4 4a5 5 0 0 0 7 7l2-2',
1791
+ users: 'M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2M9 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8M22 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75',
1791
1792
  settings: 'M12 8a4 4 0 1 0 0 8 4 4 0 0 0 0-8M10 3h4l1 3 3 1 3 3v4l-3 1-1 3-3 3h-4l-1-3-3-1-3-3v-4l3-1 1-3z',
1792
1793
  folder: 'M3 7V5a2 2 0 0 1 2-2h5l2 3h7a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z',
1793
1794
  route: 'M4 5h16M4 12h16M4 19h16M7 3v4M12 10v4M17 17v4',
@@ -1967,8 +1968,10 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
1967
1968
  var progressGradientId=useState(function(){return 'pmw-progress-blue-'+(++overviewGradientSequence)})[0]
1968
1969
  var planServiceReady=!!(props.releases && Array.isArray(props.releases.plans))
1969
1970
  var rs=useState(props.releases || {currentVersion:null,plans:[],fingerprint:null}),releases=rs[0],setReleases=rs[1]
1970
- var versionSt=useState(function(){return props.releases && props.releases.currentVersion || '*'}),version=versionSt[0],setVersion=versionSt[1]
1971
- var statusSt=useState('all'),status=statusSt[0],setStatus=statusSt[1],querySt=useState(''),query=querySt[0],setQuery=querySt[1]
1971
+ var versionSt=useState(function(){return pmBus.overviewContext ? pmBus.overviewContext.version : props.releases && props.releases.currentVersion || '*'}),version=versionSt[0],setVersion=versionSt[1]
1972
+ var statusSt=useState(pmBus.overviewContext && pmBus.overviewContext.status || 'all'),status=statusSt[0],setStatus=statusSt[1],querySt=useState(pmBus.overviewContext && pmBus.overviewContext.query || ''),query=querySt[0],setQuery=querySt[1]
1973
+ var presentationSt=useState(pmBus.overviewContext && pmBus.overviewContext.presentation || 'table'),presentation=presentationSt[0],setPresentation=presentationSt[1]
1974
+ useEffect(function(){pmBus.overviewContext={version:version,status:status,query:query,presentation:presentation}},[version,status,query,presentation])
1972
1975
  var sortSt=useState('updated'),sort=sortSt[0],setSort=sortSt[1],choiceSt=useState(false),choice=choiceSt[0],setChoice=choiceSt[1]
1973
1976
  var infoSt=useState(null),info=infoSt[0],setInfo=infoSt[1],pickerRef=React.useRef(null),pickerButton=React.useRef(null)
1974
1977
  var hs=useState(null),help=hs[0],setHelp=hs[1],helpRef=React.useRef(null),ims=useState(false),importOpen=ims[0],setImportOpen=ims[1]
@@ -2020,10 +2023,10 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
2020
2023
  e('section',{className:'pmw-summary','aria-label':'本版需求统计'},e('div',{className:'pmw-summary__metrics'},statistic('total','需求总数',model.total),statistic('done','已完成',model.completed),statistic('running','进行中',model.running),statistic('waiting','待启动',model.waiting))),
2021
2024
  e('div',{className:'pmw-overview__panels'},train),
2022
2025
  e('section',{className:'pmw-overview__tablepanel','aria-label':'需求列表'},
2023
- e('div',{className:'pmw-overview__boardhead'},e('span',{className:'pmw-panel-icon'},e(UiIcon,{name:'list'})),e('h2',null,'需求地图'),e('span',{role:'status'},model.rows.length)),
2026
+ e('div',{className:'pmw-overview__boardhead'},e('span',{className:'pmw-panel-icon'},e(UiIcon,{name:'list'})),e('h2',null,'需求地图'),e('span',{role:'status'},model.rows.length),e('div',{className:'sa-presentation',role:'group','aria-label':'需求展示方式'},[['table','表格'],['board','看板']].map(function(p){return e('button',{key:p[0],'aria-pressed':presentation===p[0],onClick:function(){setPresentation(p[0])}},p[1])}))),
2024
2027
  e('div',{className:'pmw-overview__tools'},e('div',{className:'pmw-overview__views',role:'group','aria-label':'按需求状态筛选'},tabs.map(function(t){return e('button',{key:t.id,'aria-pressed':status===t.id,onClick:function(){setStatus(t.id)}},t.title,e('span',null,t.count))})),e('label',{className:'pmw-overview__search'},e(UiIcon,{name:'search'}),e('input',{'aria-label':'搜索需求、编码、负责人或应用',placeholder:'搜索需求、负责人或应用',value:query,onChange:function(ev){setQuery(ev.target.value)}}),query && e('button',{'aria-label':'清除总览搜索',onClick:function(){setQuery('')}},e(UiIcon,{name:'close'})))),
2025
2028
  props.requirements.length===0?e('div',{className:'pmw-overview__empty'},e(UiIcon,{name:'grid'}),e('h2',null,'新建第一条需求'),e('button',{className:'pmw-btn pmw-btn--primary',onClick:props.onCreate},'新建需求')):model.rows.length===0?e('div',{className:'pmw-overview__empty'},e(UiIcon,{name:'search'}),e('h2',null,'当前范围没有需求'),e('button',{className:'pmw-btn',onClick:function(){setStatus('all');setQuery('')}},'清除状态与搜索筛选')):
2026
- e('div',{className:'pmw-requirements-scroll'},e('table',{className:'pmw-requirements'},e('thead',null,e('tr',null,['需求','状态','业务方','SA','前端开发','后端开发','测试','外部应用','操作'].map(function(label){return e('th',{key:label,scope:'col'},label)}))),e('tbody',null,model.rows.map(card))))),
2029
+ presentation==='board'?e(RequirementKanban,{requirements:model.rows,onOpen:function(req){setInfo({requirement:req,editing:false})}}):e('div',{className:'pmw-requirements-scroll'},e('table',{className:'pmw-requirements'},e('thead',null,e('tr',null,['需求','状态','业务方','SA','前端开发','后端开发','测试','外部应用','操作'].map(function(label){return e('th',{key:label,scope:'col'},label)}))),e('tbody',null,model.rows.map(card))))),
2027
2030
  help && e('div',{className:'pmw-overview__help',ref:helpRef,role:'dialog','aria-label':help.title,style:{left:help.left,top:help.top}},e('h3',null,help.title),e('p',null,help.text)),
2028
2031
  importOpen && e(ReleaseImportDialog,{onClose:function(){setImportOpen(false)},onSaved:function(value){setReleases(value);props.onRefresh()}}),
2029
2032
  info && e(RequirementInfoDialog,{requirement:info.requirement,startEditing:info.editing,onOpen:props.onOpen,onClose:function(){setInfo(null)},onSaved:props.onRefresh}))
@@ -2338,7 +2341,7 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
2338
2341
  // 全局选择总线:左轨(常驻)与 SA 总览页(main 面板)共享选中态
2339
2342
  // -----------------------------------------------------------------------
2340
2343
  var pmBus = {
2341
- state: { selectedId: null, activeSessionId: null, nav: 'home', selectedVersion: null, tabs: {}, scrolls: {}, files: {}, focus: false },
2344
+ state: { selectedId: null, activeSessionId: null, nav: 'home', selectedVersion: null, tabs: {}, scrolls: {}, files: {}, focus: true },
2342
2345
  listeners: [],
2343
2346
  set: function (patch) {
2344
2347
  var changed = false
@@ -2937,6 +2940,57 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
2937
2940
  directoryBrowser && e(DirectoryBrowser,{key:directoryBrowser.key,title:directoryBrowser.title,start:directoryBrowser.start,onCancel:function(){setDirectoryBrowser(null)},onSelect:function(location){changeField(directoryBrowser.key,location);setDirectoryBrowser(null)}}))
2938
2941
  }
2939
2942
 
2943
+ var WORKSPACE_PREVIEW_CSS = "/* Task navigation is distinct from document controls. Preview is opt-in. */\r\nhtml:has(.sa-workspace-shell) .pmw-nav__group:last-child{display:none}\r\nhtml:root .pmw-root.sa-workspace-shell{--sa-preview-ink:var(--glass-ink,var(--dsw-alias-text-primary));--sa-preview-muted:var(--glass-muted,var(--dsw-alias-text-secondary));--sa-preview-card:var(--glass-card,var(--dsw-alias-background-container));--sa-preview-line:var(--glass-input,var(--dsw-alias-border-l2));}\r\n.sa-workspace-toolbar{display:flex;align-items:center;gap:16px;flex:none;padding:14px 22px 12px;min-height:66px;border-bottom:1px solid color-mix(in srgb,var(--sa-preview-line) 35%,transparent);}\r\n.sa-workspace-tabs{display:flex;gap:3px;padding:4px;border-radius:18px;background:var(--sa-preview-card);box-shadow:0 1px 0 color-mix(in srgb,var(--sa-preview-line) 30%,transparent);backdrop-filter:blur(16px);}\r\n.sa-workspace-tabs button{border:0;background:none;color:var(--sa-preview-muted);font:inherit;font-size:13px;border-radius:14px;padding:9px 16px;white-space:nowrap;cursor:pointer;}\r\n.sa-workspace-tabs button[aria-current=page]{background:var(--sa-preview-ink);color:var(--glass-bg,#fff);}\r\n.sa-workspace-tabs button:focus-visible,.sa-presentation button:focus-visible,.sa-board-card:focus-visible{outline:2px solid var(--glass-primary,#7663db);outline-offset:3px;}\r\n.sa-workspace-label{margin-left:auto;font-size:12px;color:var(--sa-preview-muted);}\r\n.sa-mobile-create{display:none;}\r\n.sa-workspace-toolbar .sa-theme-switch{flex:none;}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-overview__head>.sa-theme-switch{display:none}\r\n.sa-settings-scroll{overflow:auto;min-height:0;flex:1;}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-detail__head{padding:18px 24px 14px;gap:12px;}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-detail__head .sa-assistant-toggle{width:auto;margin-left:8px;gap:7px;border:1px solid var(--sa-preview-line);border-radius:16px;padding:7px 12px;}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-detail__head .sa-assistant-toggle[aria-expanded=true]{background:var(--glass-tint);}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-ai{border-left:1px solid var(--sa-preview-line);background:var(--sa-preview-card);}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-ai__context{gap:8px;}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-ai__context>span{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-ai__context>button{margin-left:auto;padding:4px;flex:none;}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-doc--empty{padding:28px 24px;}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-empty-state{max-width:920px;display:grid;grid-template-columns:minmax(0,1fr) minmax(240px,.85fr);column-gap:32px;row-gap:16px;margin:0 auto;align-content:start;}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-empty-state__heading,html:root .pmw-root.sa-workspace-shell .pmw-empty-state__description{grid-column:1;}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-empty-state__heading{align-self:end;}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-empty-state__description{margin:0;max-width:460px;line-height:1.8;}\r\n.sa-deliverable{grid-column:2;grid-row:1 / span 6;align-self:start;padding:24px;border:1px solid color-mix(in srgb,var(--sa-preview-line) 65%,transparent);border-radius:24px;background:var(--sa-preview-card);box-shadow:0 10px 30px -24px var(--sa-preview-ink);}\r\n.sa-deliverable__eyebrow{font-size:11px;letter-spacing:.12em;color:var(--sa-preview-muted);}\r\n.sa-deliverable h4{font-size:18px;line-height:1.55;margin:10px 0 18px;font-weight:600;color:var(--sa-preview-ink);}\r\n.sa-deliverable ul{padding:0;margin:0;list-style:none;display:grid;gap:14px;}\r\n.sa-deliverable li{display:flex;gap:10px;align-items:flex-start;font-size:13px;line-height:1.65;}\r\n.sa-deliverable li>span{flex:none;font-size:10px;width:24px;height:24px;display:grid;place-items:center;border-radius:50%;background:var(--glass-tint);color:var(--sa-preview-muted);}\r\n.sa-deliverable__hint,.sa-deliverable__missing{font-size:12px;line-height:1.8;color:var(--sa-preview-muted);margin:18px 0 0;}\r\n.sa-deliverable__missing{border-top:1px solid var(--sa-preview-line);padding-top:14px;}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-empty-state>.pmw-sources{grid-column:1;max-width:100%;}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-empty-state>.pmw-empty-state__file,html:root .pmw-root.sa-workspace-shell .pmw-empty-state>.pmw-btn,html:root .pmw-root.sa-workspace-shell .pmw-empty-state>.pmw-empty-state__note{grid-column:1;justify-self:start;margin:0;}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-empty-state>.pmw-btn{border-radius:16px;padding:11px 18px;}\r\n.sa-presentation{display:flex;margin-left:auto;padding:3px;border:1px solid var(--sa-preview-line);border-radius:14px;gap:2px;}\r\n.sa-presentation button{font:inherit;font-size:12px;padding:6px 11px;cursor:pointer;color:var(--sa-preview-muted);border:0;border-radius:10px;background:none;}\r\n.sa-presentation button[aria-pressed=true]{background:var(--sa-preview-card);box-shadow:0 1px 4px #0001;color:var(--sa-preview-ink);}\r\n.sa-requirement-board{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px;padding:8px 0 20px;}\r\n.sa-board-column{background:color-mix(in srgb,var(--sa-preview-ink) 3%,transparent);border-radius:22px;padding:12px;min-height:240px;}\r\n.sa-board-column>header{display:flex;align-items:center;justify-content:space-between;margin:2px 4px 14px;font-size:12px;color:var(--sa-preview-muted);}\r\n.sa-board-card{display:flex;text-align:left;flex-direction:column;gap:10px;cursor:pointer;padding:18px;margin:0 0 12px;width:100%;font:inherit;color:var(--sa-preview-ink);border:1px solid color-mix(in srgb,var(--sa-preview-line) 65%,transparent);border-radius:18px;background:var(--sa-preview-card);transition:transform .15s;}\r\n.sa-board-card:hover{transform:translateY(-2px);}\r\n.sa-board-card code{font-size:11px;color:var(--sa-preview-muted);}\r\n.sa-board-card strong{font-size:15px;line-height:1.6;overflow-wrap:anywhere;}\r\n.sa-board-card__stage,.sa-board-card footer{font-size:11px;line-height:1.6;color:var(--sa-preview-muted);}\r\n.sa-board-card footer{display:flex;justify-content:space-between;gap:8px;padding-top:10px;border-top:1px solid var(--sa-preview-line);flex-wrap:wrap;}\r\n.sa-board-empty{font-size:12px;color:var(--sa-preview-muted);padding:20px 6px;}\r\n@media(max-width:1100px){html:root .pmw-root.sa-workspace-shell:has(.pmw-ai) .pmw-empty-state{grid-template-columns:minmax(0,1fr)}html:root .pmw-root.sa-workspace-shell:has(.pmw-ai) .sa-deliverable{grid-column:1;grid-row:auto;}}\r\n@media(max-width:760px){.sa-workspace-toolbar{padding:10px 14px;gap:8px;}.sa-workspace-tabs button{padding:8px 12px;}.sa-workspace-label{display:none}.sa-workspace-toolbar .sa-theme-switch{margin-left:auto;}html:root .pmw-root.sa-workspace-shell .pmw-empty-state{grid-template-columns:minmax(0,1fr);}.sa-deliverable{grid-column:1;grid-row:auto;}.sa-requirement-board{grid-template-columns:minmax(0,1fr)}html:root .pmw-root.sa-workspace-shell .pmw-doc--empty{padding:20px 16px;}html:root .pmw-root.sa-workspace-shell .pmw-detail__head{padding:14px 16px;}html:root .pmw-root.sa-workspace-shell .pmw-ai{position:absolute;right:0;top:0;bottom:0;z-index:20;width:min(420px,100%);box-shadow:-12px 0 40px #0002;}html:root .pmw-root.sa-workspace-shell .pmw-body{position:relative;}}\r\n@media(prefers-reduced-motion:reduce){.sa-board-card{transition:none}}\r\n\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-detail__title{font-size:20px;font-weight:600;line-height:1.45}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-empty-state{max-width:980px;width:100%}\r\nhtml:root .pmw-root.sa-workspace-shell .sa-deliverable li>span{border-radius:50%!important;corner-shape:round!important}\r\n@media(max-width:760px){html:has(.sa-workspace-shell) .pmw-nav{display:none!important}html:root .pmw-root.sa-workspace-shell .pmw-empty-state{max-width:100%}.sa-workspace-toolbar{gap:6px}.sa-workspace-tabs{min-width:0;overflow-x:auto}.sa-workspace-tabs button{font-size:12px;padding:7px 8px}.sa-workspace-toolbar .sa-theme-switch{margin-left:0!important}}\r\n@media(max-width:760px){.sa-mobile-create{display:inline-flex;align-items:center;justify-content:center;flex:none;width:32px;height:32px;border:1px solid var(--sa-preview-line);border-radius:50%;color:var(--sa-preview-ink);background:var(--sa-preview-card);cursor:pointer}.sa-workspace-tabs{flex:1}.sa-workspace-toolbar{padding:10px}}\r\n\r\n/* Annotation revision: segmented stage route and composed start panel. */\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-stages{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:0;padding:18px 24px 20px;overflow:visible}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-step{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:flex-start;gap:8px;padding:0;overflow:visible;background:none;border:0;min-width:0}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-step::before,html:root .pmw-root.sa-workspace-shell .pmw-step::after{display:none}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-step__number{position:relative;z-index:2;display:flex;align-items:center;justify-content:center;width:40px;height:40px;min-width:40px;padding:0;border-radius:50%!important;corner-shape:round!important;border:1.5px solid var(--sa-preview-line);background:var(--glass-popover,var(--glass-bg));color:var(--sa-preview-muted);box-shadow:none;outline:0}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-step__number>svg{width:19px;height:19px}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-step.is-current .pmw-step__number{background:var(--sa-preview-ink);border-color:var(--sa-preview-ink);color:var(--glass-bg)}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-step.is-active:not(.is-current) .pmw-step__number{border-color:var(--glass-primary);color:var(--glass-primary);background:var(--glass-bg);box-shadow:0 0 0 4px var(--glass-tint)}\r\nhtml:root .pmw-root.sa-workspace-shell .sa-stage-connector{position:absolute;z-index:1;top:19px;left:calc(-50% + 24px);width:calc(100% - 48px);height:0;border-top:2px solid var(--sa-preview-line);pointer-events:none}\r\nhtml:root .pmw-root.sa-workspace-shell .sa-stage-connector.is-reached{border-color:var(--sa-preview-ink)}\r\nhtml:root .pmw-root.sa-workspace-shell .sa-stage-connector.is-optional{border-top-style:dashed}\r\nhtml:root .pmw-root.sa-workspace-shell .sa-stage-done{position:absolute;right:-3px;bottom:-2px;width:16px;height:16px;border-radius:50%;display:grid;place-items:center;background:var(--sa-preview-ink);color:var(--glass-bg);border:2px solid var(--glass-bg)}\r\nhtml:root .pmw-root.sa-workspace-shell .sa-stage-done .pmw-icon{width:10px;height:10px}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-step__label{font-size:13px;line-height:20px}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-step small{margin:0;font-size:11px;line-height:16px}\r\n.sa-empty-workspace{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,.9fr);gap:28px;max-width:1060px;margin:10px auto 0;width:100%;align-items:stretch}\r\n.sa-empty-workspace>.sa-deliverable{grid-column:auto;grid-row:auto;align-self:stretch;box-shadow:none}\r\n.sa-stage-start{display:flex;flex-direction:column;gap:0;padding:28px;border:1px solid color-mix(in srgb,var(--sa-preview-line) 60%,transparent);border-radius:24px;background:var(--sa-preview-card);min-width:0}\r\n.sa-stage-start__header{display:flex;gap:10px;align-items:center;font-size:12px;color:var(--sa-preview-muted)}\r\n.sa-stage-start__glyph{display:grid;place-items:center;width:36px;height:36px;border-radius:12px;color:var(--glass-primary);background:var(--glass-tint)}\r\n.sa-stage-start__state{margin-left:auto;font-size:11px;padding:4px 9px;border-radius:999px;background:var(--glass-secondary)}\r\nhtml:root .pmw-root.sa-workspace-shell .sa-stage-start h3{font-size:24px;line-height:1.4;font-weight:600;margin:22px 0 12px;color:var(--sa-preview-ink)}\r\n.sa-stage-start__intro{font-size:13px;line-height:1.85;margin:0 0 24px;color:var(--sa-preview-muted)}\r\nhtml:root .pmw-root.sa-workspace-shell .sa-stage-start>.pmw-sources{max-width:100%;width:100%;margin:0 0 18px}\r\n.sa-stage-output{display:flex;align-items:center;gap:12px;background:var(--glass-secondary);border:1px solid color-mix(in srgb,var(--sa-preview-line) 45%,transparent);border-radius:16px;padding:15px 16px;margin-top:auto}\r\n.sa-stage-output__icon{display:grid;place-items:center;width:36px;height:40px;border-radius:9px;background:var(--glass-card);color:var(--sa-preview-muted)}\r\n.sa-stage-output small{display:block;font-size:11px;color:var(--sa-preview-muted);margin-bottom:4px}\r\n.sa-stage-output code{display:block;font-size:13px;color:var(--sa-preview-ink);overflow-wrap:anywhere}\r\n.sa-stage-start__actions{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-top:22px}\r\nhtml:root .pmw-root.sa-workspace-shell .sa-stage-start__actions .pmw-btn{display:inline-flex;align-items:center;gap:18px;padding:11px 18px;border-radius:14px}\r\n.sa-stage-start__actions>span{font-size:11px;color:var(--sa-preview-muted)}\r\n@media(max-width:1100px){html:root .pmw-root.sa-workspace-shell:has(.pmw-ai) .sa-empty-workspace{grid-template-columns:minmax(0,1fr)}}\r\n@media(max-width:760px){.sa-empty-workspace{grid-template-columns:minmax(0,1fr);gap:18px;margin-top:0}.sa-stage-start{padding:22px}.sa-empty-workspace>.sa-deliverable{grid-column:auto;grid-row:auto}html:root .pmw-root.sa-workspace-shell .pmw-stages{padding:16px 12px 18px}html:root .pmw-root.sa-workspace-shell .pmw-step__number{width:34px;height:34px;min-width:34px}html:root .pmw-root.sa-workspace-shell .sa-stage-connector{top:16px;left:calc(-50% + 21px);width:calc(100% - 42px)}html:root .pmw-root.sa-workspace-shell .pmw-step__label{font-size:11px}}\r\n";
2944
+ function StageGlyph(props){
2945
+ var paths={intake:['M4 5h16v11H9l-5 4V5','M8 9h8M8 12h5'],solution:['M4 4h6v6H4zM14 14h6v6h-6z','M10 7h7v7M7 10v7h7'],prd:['M14 3H6a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V8l-5-5z','M14 3v5h5M8 14l2 2 5-5'],prototype:['M3 4h18v16H3z','M3 9h18M9 9v11']};
2946
+ return e('svg',{width:20,height:20,viewBox:'0 0 24 24',fill:'none',stroke:'currentColor',strokeWidth:1.65,strokeLinecap:'round',strokeLinejoin:'round','aria-hidden':true},(paths[props.stage] || paths.prd).map(function(d,i){return e('path',{key:i,d:d})}))
2947
+ }
2948
+ function StageStartCard(props){
2949
+ var action={intake:'开始梳理',solution:'开始设计',prd:'开始编写',prototype:'开始制作'}[props.stage];
2950
+ return e('section',{className:'sa-stage-start','aria-label':props.title},
2951
+ e('header',{className:'sa-stage-start__header'},e('span',{className:'sa-stage-start__glyph'},e(StageGlyph,{stage:props.stage})),e('span',null,props.archived?'归档记录':'准备开始'),e('span',{className:'sa-stage-start__state'},props.archived?'未包含':'尚未生成')),
2952
+ e('h3',null,props.title),e('p',{className:'sa-stage-start__intro'},props.description),
2953
+ props.sources,
2954
+ props.artifact && e('div',{className:'sa-stage-output'},e('span',{className:'sa-stage-output__icon'},e(StageGlyph,{stage:props.stage})),e('div',null,e('small',null,props.archived?'未包含文件':'交付文件'),e('code',null,props.artifact.path))),
2955
+ !props.archived && props.artifact && e('footer',{className:'sa-stage-start__actions'},e('button',{className:'pmw-btn pmw-btn--primary',disabled:props.busy,onClick:props.onStart},props.busy?'正在准备…':action,e('svg',{width:16,height:16,viewBox:'0 0 24 24',fill:'none',stroke:'currentColor',strokeWidth:1.8,'aria-hidden':true},e('path',{d:'M5 12h14M13 6l6 6-6 6',strokeLinecap:'round',strokeLinejoin:'round'}))),e('span',null,'使用当前工作方法')))
2956
+ }
2957
+ function WorkspaceNavigation(props){
2958
+ var active=props.current==='create'?'home':props.current;
2959
+ return e('header',{className:'sa-workspace-toolbar'},
2960
+ e('nav',{'aria-label':'SA 工作台导航',className:'sa-workspace-tabs'},[['home','需求'],['kb','知识库'],['plib','归档库'],['settings','工作方法']].map(function(t){return e('button',{key:t[0],type:'button','aria-current':active===t[0]?'page':undefined,onClick:function(){props.onNavigate(t[0])}},t[1])})),
2961
+ e('span',{className:'sa-workspace-label'},'SA 工作台'),
2962
+ e('button',{className:'sa-mobile-create',type:'button','aria-label':'新建需求',onClick:function(){props.onNavigate('create')}},e(UiIcon,{name:'plus'})),
2963
+ e('div',{className:'sa-theme-switch','aria-label':'工作台外观'},['light','dark'].map(function(a){return e('button',{key:a,type:'button','aria-label':a==='light'?'浅色模式':'暗色模式','aria-pressed':(pmBus.state.appearance || saAppearance())===a,onClick:function(){setSaAppearance(a)}},a==='light'?'☀':'☾')})))
2964
+ }
2965
+ function stageDeliverableModel(stage,requirement,artifact){
2966
+ var definitions={
2967
+ intake:{title:'一份可继续设计的业务需求',items:['业务目标与使用场景','范围、现状与资料依据','需要进一步确认的问题']},
2968
+ solution:{title:'一份可讨论的高阶方案',items:['关键设计点与系统职责','业务流程、依赖及改造范围','方案依据与待决策事项']},
2969
+ prd:{title:'一份可评审、可验证的 PRD',items:['用户故事与完整业务规则','Given / When / Then 验收条件','相关流程与交互说明']},
2970
+ prototype:{title:'一份可操作的交互原型',items:['主要页面与关键任务路径','适用的正常、异常与空状态','供讨论与迭代的页面交互']}
2971
+ };
2972
+ var model=definitions[stage] || definitions.intake;
2973
+ var prior=stage==='solution'?['intake']:stage==='prd'?['intake','solution']:stage==='prototype'?['prd']:[];
2974
+ var missing=prior.filter(function(id){var s=(requirement.stages || []).find(function(s){return s.id===id});return !s || !(s.artifacts || []).some(function(a){return a.exists})});
2975
+ return {title:model.title,items:model.items,missing:missing.map(function(id){return {intake:'业务需求',solution:'高阶方案',prd:'PRD'}[id]}),file:artifact && artifact.path,archived:!!requirement.archived};
2976
+ }
2977
+ function StageDeliverablePreview(props){
2978
+ var model=stageDeliverableModel(props.stage,props.requirement,props.artifact);
2979
+ if(model.archived)return null;
2980
+ return e('aside',{className:'sa-deliverable','aria-label':'本阶段交付预览'},
2981
+ e('div',{className:'sa-deliverable__eyebrow'},'本阶段交付'),e('h4',null,model.title),
2982
+ e('ul',null,model.items.map(function(text,i){return e('li',{key:text},e('span',{'aria-hidden':true},String(i+1).padStart(2,'0')),text)})),
2983
+ model.missing.length>0 && e('p',{className:'sa-deliverable__missing'},'尚未发现'+model.missing.join('、')+'文档。助手会先核对依据,必要时补充澄清。'),
2984
+ e('p',{className:'sa-deliverable__hint'},'以上为预期内容,当前尚未生成;生成后仍需评审。'))
2985
+ }
2986
+ function RequirementKanban(props){
2987
+ return e('div',{className:'sa-requirement-board','aria-label':'需求状态看板'},[['waiting','待启动'],['running','进行中'],['done','已完成']].map(function(group){
2988
+ var rows=props.requirements.filter(function(r){return overviewStatus(r)===group[0]});
2989
+ return e('section',{key:group[0],className:'sa-board-column'},e('header',null,e('span',{className:'pmw-stage-pill is-'+group[0]},e('i',{'aria-hidden':true}),group[1]),e('span',null,rows.length)),
2990
+ rows.length?rows.map(function(req){var c=collaborationValue(req),stages=req.stages || [],existing=stages.filter(function(s){return (s.artifacts || []).some(function(a){return a.exists})}).length;return e('button',{key:req.id,className:'sa-board-card',onClick:function(){props.onOpen(req)},'aria-label':'查看 '+req.code+' '+req.title},e('code',null,req.code),e('strong',null,req.title),e('span',{className:'sa-board-card__stage'},stageTitle(req)),e('footer',null,e('span',null,c.pmOwner || 'SA 待填写'),e('span',null,existing?existing+' 个阶段已有稿':'尚无阶段稿')))}):e('p',{className:'sa-board-empty'},'当前筛选下暂无需求'))
2991
+ }))
2992
+ }
2993
+
2940
2994
  function Panel(props) {
2941
2995
  var layout = props.layout
2942
2996
  var pm = props.pm
@@ -2949,6 +3003,7 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
2949
3003
  var form = useState('home')
2950
3004
  var view = form[0]
2951
3005
  var setView = form[1]
3006
+ var pendingNavigationSt=useState(null),pendingNavigation=pendingNavigationSt[0],setPendingNavigation=pendingNavigationSt[1]
2952
3007
  var ft = useState('')
2953
3008
  var formTitle = ft[0]
2954
3009
  var setFormTitle = ft[1]
@@ -3348,7 +3403,7 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
3348
3403
  return pm.sendToReq(selected, dir, body.prompt).then(function (res) {
3349
3404
  setBusy(false)
3350
3405
  if (!res || !res.ok) setOpErr((res && res.error) || '发送失败')
3351
- else {setNotice('已发送到对话 · 使用 '+body.skill.name+';请在会话中查看进展。');if(stageId==='intake')return apiSend('POST','/requirement-start',{id:selected.id}).then(reload)}
3406
+ else {pmBus.set({focus:false});setNotice('已发送到对话 · 使用 '+body.skill.name+';请在会话中查看进展。');if(stageId==='intake')return apiSend('POST','/requirement-start',{id:selected.id}).then(reload)}
3352
3407
  })
3353
3408
  }).catch(function (err) {
3354
3409
  setBusy(false)
@@ -3517,10 +3572,16 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
3517
3572
  }).catch(function(err) { if (pmBus.state.selectedId === owner.id) setOpErr(String(err.message || err)) }).finally(function(){setBusy(false)})
3518
3573
  }
3519
3574
 
3575
+ function navigateWorkspace(target){
3576
+ if(editor){setPendingNavigation(target);return}
3577
+ completeNavigation(target)
3578
+ }
3579
+ function completeNavigation(target){setPendingNavigation(null);setEditor(null);pmBus.set({nav:target,selectedId:null,activeSessionId:null,settingsReturn:null});setView(target)}
3580
+ var workspaceNav=e(WorkspaceNavigation,{current:view,onNavigate:navigateWorkspace})
3520
3581
  var children = []
3521
3582
 
3522
3583
  if (data.data && (data.data.setupRequired || data.data.restartRequired)) return e('div',{className:'pmw-root','data-sa-appearance':bus.appearance || saAppearance()},e(SettingsPanel,{onboarding:true,onComplete:function(){pmBus.set({nav:'home',selectedId:null,activeSessionId:null,settingsReturn:null});setView('home');reload()}}))
3523
- if (view === 'settings') return e('div', { className: 'pmw-root', 'data-sa-appearance':bus.appearance || saAppearance() }, e(SettingsPanel))
3584
+ if (view === 'settings') return e('div', { className: 'pmw-root sa-workspace-shell', 'data-sa-appearance':bus.appearance || saAppearance() },e('style',null,WORKSPACE_PREVIEW_CSS),workspaceNav,e('div',{className:'sa-settings-scroll'},e(SettingsPanel)))
3524
3585
 
3525
3586
  // header(纯标题,动作全部收进各自语境:Tab 空态/地铁图归档站/右栏线程条)
3526
3587
  if (!selected && (view !== 'home' || !data.data)) children.push(e('div', { className: 'pmw-header', key: 'header' },
@@ -3541,7 +3602,7 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
3541
3602
  e('div',{className:'pmw-dialog__body'},e('label',{className:'pmw-field'},e('span',{className:'pmw-field__label'},'文件名称'),e('input',{className:'pmw-input',autoFocus:true,'aria-label':'文件名称',value:newFile.name,maxLength:110,onChange:function(ev){setNewFile(Object.assign({},newFile,{name:ev.target.value}))},placeholder:'例如:接口说明'})),
3542
3603
  e('label',{className:'pmw-field'},e('span',{className:'pmw-field__label'},'文档内容'),e('textarea',{className:'pmw-textarea','aria-label':'新增文档内容',value:newFile.content,onChange:function(ev){setNewFile(Object.assign({},newFile,{content:ev.target.value}))},placeholder:'支持 Markdown'})),opErr && e('p',{role:'alert'},opErr)),
3543
3604
  e('div',{className:'pmw-dialog__foot'},e('button',{type:'button',className:'pmw-btn',disabled:isBusy,onClick:function(){setNewFile(null)}},'取消'),e('button',{type:'submit',className:'pmw-btn pmw-btn--primary',disabled:isBusy || !newFile.name.trim() || !newFile.content.trim()},isBusy?'正在添加…':'添加文档')))))
3544
- return e('div', { ref:rootRef, className: 'pmw-root' + (expanded ? ' is-expanded' : ''), 'data-sa-appearance':bus.appearance || saAppearance() }, children)
3605
+ return e('div', { ref:rootRef, className: 'pmw-root sa-workspace-shell' + (expanded ? ' is-expanded' : ''), 'data-sa-appearance':bus.appearance || saAppearance() },e('style',null,WORKSPACE_PREVIEW_CSS),!expanded && workspaceNav,pendingNavigation && e(DetailDialog,{title:'离开未保存的文档?',onClose:function(){setPendingNavigation(null)},footer:e(React.Fragment,null,e('button',{className:'pmw-btn',onClick:function(){setPendingNavigation(null)}},'继续编辑'),e('button',{className:'pmw-btn pmw-btn--primary',onClick:function(){completeNavigation(pendingNavigation)}},'放弃修改并离开'))},e('p',null,'当前修改尚未保存。继续编辑可保留草稿;离开将放弃这些修改,原文件不变。')),children)
3545
3606
  }
3546
3607
 
3547
3608
  // body: main + chat
@@ -3676,13 +3737,10 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
3676
3737
  return e('button', { key: stage.id, className: 'pmw-step' + (stage.id === curTab ? ' is-active' : '') + (exists ? ' is-complete' : '') + (current ? ' is-current' : '') + (optional ? ' is-optional' : ''),
3677
3738
  'aria-pressed': stage.id === curTab, 'aria-current': current ? 'step' : undefined, title: stage.title + ' · ' + (exists ? '已有文档' : '尚未生成') + (stage.id === curTab ? ' · 正在查看' : ''),
3678
3739
  onClick: function () { if (stage.id === curTab) return; if (editor && !confirm('有未保存的修改,确定放弃并切换文档?')) return; setEditor(null); setTabSt(stage.id) },
3679
- }, e('span', { className: 'pmw-step__number', 'aria-hidden': true }, exists ? e(UiIcon,{name:'check'}) : String(index + 1)),
3740
+ },index>0 && e('span',{className:'sa-stage-connector'+(optional?' is-optional':'')+((exists || current) && selected.stages[index-1].artifacts[0].exists?' is-reached':''),'aria-hidden':true}),e('span',{className:'pmw-step__number','aria-hidden':true},e(StageGlyph,{stage:stage.id}),exists && e('span',{className:'sa-stage-done'},e(UiIcon,{name:'check'}))),
3680
3741
  e('span', {className:'pmw-step__label'}, label), e('small', null, status))
3681
3742
  })
3682
- metroNodes.unshift(e('svg',{key:'route',className:'pmw-metro__track',viewBox:'0 0 1000 64',preserveAspectRatio:'none','aria-hidden':true},
3683
- e('path',{className:'pmw-metro__line',d:'M125 20 H625',vectorEffect:'non-scaling-stroke'}),
3684
- progressX > 125 && e('path',{className:'pmw-metro__line is-travelled',d:'M125 20 H'+progressX,vectorEffect:'non-scaling-stroke'}),
3685
- e('path',{className:'pmw-metro__line pmw-metro__branch'+(prototypeExists ? ' is-travelled' : ''),d:'M625 20 H875',vectorEffect:'non-scaling-stroke'})))
3743
+
3686
3744
 
3687
3745
  var currentDocReady = doc && curArt && doc.path === curArt.path && !doc.loading && !doc.error
3688
3746
  var cloudReceipt = currentDocReady && doc.receipt
@@ -3713,20 +3771,9 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
3713
3771
  var sourcesNode = curTab === 'intake' && e(SourceInputs,{key:'sources-'+selected.id,id:selected.id,readOnly:!!selected.archived,hasDoc:!!(curArt && curArt.exists),stageBusy:isBusy,onBusy:setSourceBusy,onStart:function(){handStage('intake')}})
3714
3772
  if (!curArt || !curArt.exists) {
3715
3773
  var emptyCopy={intake:['梳理业务需求','从你的诉求和业务资料开始,澄清目标、使用场景与范围,保留待确认的问题。','梳理需求'],solution:['形成高阶方案','结合业务需求与现状,明确系统职责、改造方向、依赖与未决事项。','设计高阶方案'],prd:['编写 PRD','基于需求与高阶方案,展开可验证的功能、业务规则和验收条件。','编写 PRD'],prototype:['制作交互原型','用可操作的页面检验 PRD 中的流程与交互。原型按需交付,不阻止归档。','制作原型']}[curTab]
3716
- contentNode = e('div', { className: 'pmw-doc pmw-doc--empty', key: 'empty' },e('section',{className:'pmw-empty-state'},
3717
- e('div',{className:'pmw-empty-state__heading'},
3718
- e('div',{className:'pmw-empty-state__icon','aria-hidden':true},e(UiIcon,{name:curTab==='prototype'?'select':'doc'})),
3719
- e('h3',null,selected.archived ? '本次归档未包含'+documentName : emptyCopy[0])),
3720
- e('p',{className:'pmw-empty-state__description'},selected.archived ? '此归档保留了当时已有的交付文件,未生成的文档不会自动补齐。' : emptyCopy[1]),
3721
- sourcesNode,
3722
- curArt && e('div',{className:'pmw-empty-state__file'},e(UiIcon,{name:'doc'}),selected.archived?'未包含文件':'交付文件',e('code',null,curArt.path)),
3723
- !selected.archived && curArt && e('button', {
3724
- className: 'pmw-btn pmw-btn--primary',
3725
- disabled: isBusy || sourceBusy,
3726
- onClick: function () { handStage(curTab) },
3727
- }, isBusy ? '正在准备…' : '开始动手吧'),
3728
- !selected.archived && e('p',{className:'pmw-empty-state__note'},'使用当前绑定的工作方法发送到当前对话;信息不足时先澄清。'),
3729
- ))
3774
+ contentNode=e('div',{className:'pmw-doc pmw-doc--empty',key:'empty'},e('div',{className:'sa-empty-workspace'},
3775
+ e(StageStartCard,{stage:curTab,title:selected.archived?'本次归档未包含'+documentName:emptyCopy[0],description:selected.archived?'此归档保留了当时已有的交付文件,未生成的文档不会自动补齐。':emptyCopy[1],artifact:curArt,archived:!!selected.archived,sources:sourcesNode,busy:isBusy || sourceBusy,onStart:function(){handStage(curTab)}}),
3776
+ e(StageDeliverablePreview,{stage:curTab,requirement:selected,artifact:curArt})))
3730
3777
  } else if (doc && doc.path === curArt.path) {
3731
3778
  var isHtml = /\.html?$/i.test(doc.path)
3732
3779
  // UX 标注工具条:原型 Tab、当前版本即出现;已归档降级为只读(可看 pin,不可新增/改稿)
@@ -3785,10 +3832,10 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
3785
3832
  mainChildren.push(e('div', { className: 'pmw-detail', key: 'detail' },
3786
3833
  !expanded && e('div', { className: 'pmw-detail__head' },
3787
3834
  e('h2', { className: 'pmw-detail__title' }, selected.title),
3788
- e('button',{className:'pmw-btn pmw-btn--ghost',onClick:function(){setRequirementInfo(selected)}},e(UiIcon,{name:'settings'}),'协作信息'),
3835
+ e('button',{className:'pmw-btn pmw-btn--ghost',onClick:function(){setRequirementInfo(selected)}},e(UiIcon,{name:'users'}),'协作信息'),
3789
3836
  selected.code ? e('span', { className: 'pmw-tag pmw-tag--code' }, selected.code) : null,
3790
3837
  e('span', { className: 'pmw-detail__version' }, selected.version || '未排期'),
3791
- e('button', { className: 'pmw-btn pmw-btn--ghost pmw-btn--icon', 'aria-label': bus.focus ? '显示会话' : '专注阅读', 'aria-pressed': bus.focus, onClick: function () { pmBus.set({ focus: !bus.focus }) } }, e(UiIcon, { name: 'focus' })),
3838
+ e('button', { className: 'pmw-btn pmw-btn--ghost sa-assistant-toggle', 'aria-label':bus.focus?'打开需求助手':'收起需求助手','aria-expanded':!bus.focus,onClick:function(){pmBus.set({focus:!bus.focus})} },e(UiIcon,{name:'chat'}),bus.focus?'助手':'收起助手'),
3792
3839
  ),
3793
3840
  !expanded && e('nav', { className: 'pmw-stages', 'aria-label': '需求交付阶段' }, metroNodes),
3794
3841
  tabBar,
@@ -3842,7 +3889,7 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
3842
3889
  var chatError = bus.sessionError || (convRef && convRef.id === activeSessionId && convRef.error)
3843
3890
  chatNode = e('div', { className: 'pmw-ai', key: 'ai' },
3844
3891
  barNode,
3845
- e('div', { className: 'pmw-ai__context' }, e(UiIcon, { name: 'link' }), e('span', null, selected.code + ' · ' + selected.title)),
3892
+ e('div', { className: 'pmw-ai__context' }, e(UiIcon, { name: 'link' }), e('span', null, selected.code + ' · ' + selected.title),e('button',{className:'pmw-btn pmw-btn--ghost','aria-label':'收起需求助手',onClick:function(){pmBus.set({focus:true})}},e(UiIcon,{name:'close'}))),
3846
3893
  canChat
3847
3894
  ? e('div', { className: 'pmw-ai__conv', key: 'conv' },
3848
3895
  e(props.SessionProvider, { session: convRef.ref }, props.renderSlot('pm.conv', {})))
@@ -3881,7 +3928,7 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
3881
3928
  e('div',{className:'pmw-dialog__body'},e('label',{className:'pmw-field'},e('span',{className:'pmw-field__label'},'文件名称'),e('input',{className:'pmw-input',autoFocus:true,'aria-label':'文件名称',value:newFile.name,maxLength:110,onChange:function(ev){setNewFile(Object.assign({},newFile,{name:ev.target.value}))},placeholder:'例如:接口说明'})),
3882
3929
  e('label',{className:'pmw-field'},e('span',{className:'pmw-field__label'},'文档内容'),e('textarea',{className:'pmw-textarea','aria-label':'新增文档内容',value:newFile.content,onChange:function(ev){setNewFile(Object.assign({},newFile,{content:ev.target.value}))},placeholder:'支持 Markdown'})),opErr && e('p',{role:'alert'},opErr)),
3883
3930
  e('div',{className:'pmw-dialog__foot'},e('button',{type:'button',className:'pmw-btn',disabled:isBusy,onClick:function(){setNewFile(null)}},'取消'),e('button',{type:'submit',className:'pmw-btn pmw-btn--primary',disabled:isBusy || !newFile.name.trim() || !newFile.content.trim()},isBusy?'正在添加…':'添加文档')))))
3884
- return e('div', { ref:rootRef, className: 'pmw-root' + (expanded ? ' is-expanded' : ''), 'data-sa-appearance':bus.appearance || saAppearance() }, children)
3931
+ return e('div', { ref:rootRef, className: 'pmw-root sa-workspace-shell' + (expanded ? ' is-expanded' : ''), 'data-sa-appearance':bus.appearance || saAppearance() },e('style',null,WORKSPACE_PREVIEW_CSS),!expanded && workspaceNav,pendingNavigation && e(DetailDialog,{title:'离开未保存的文档?',onClose:function(){setPendingNavigation(null)},footer:e(React.Fragment,null,e('button',{className:'pmw-btn',onClick:function(){setPendingNavigation(null)}},'继续编辑'),e('button',{className:'pmw-btn pmw-btn--primary',onClick:function(){completeNavigation(pendingNavigation)}},'放弃修改并离开'))},e('p',null,'当前修改尚未保存。继续编辑可保留草稿;离开将放弃这些修改,原文件不变。')),children)
3885
3932
  }
3886
3933
 
3887
3934
  // -----------------------------------------------------------------------
@@ -36,7 +36,7 @@ window.__ModuleLoader__.load({
36
36
  return function(){if(previousShell===undefined)delete root.dataset.saShell;else root.dataset.saShell=previousShell;if(previousAppearance===undefined)delete root.dataset.saAppearance;else root.dataset.saAppearance=previousAppearance}
37
37
  }
38
38
  function toggleSaAppearance(){var next=(pmBus.state.appearance || saAppearance())==='dark'?'light':'dark';try{localStorage.setItem('sa-workbench-appearance',next)}catch(err){}pmBus.set({appearance:next})}
39
- var CLIENT_VERSION = '0.1.28'
39
+ var CLIENT_VERSION = '0.1.29'
40
40
 
41
41
  // A session may disappear or fail to open after selection. Keep failures
42
42
  // inside the conversation pane, and release even a rejected/pending ref.
@@ -1788,6 +1788,7 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
1788
1788
  edit: 'M12 20H4V12M9 15l3-.5L21 6l-3-3-8.5 9z', list: 'M8 5h13M8 12h13M8 19h13M3 5h.01M3 12h.01M3 19h.01',
1789
1789
  chat: 'M4 4h16v12H9l-5 4z', expand: 'M8 3H3v5M16 3h5v5M21 16v5h-5M3 16v5h5', focus: 'M4 4h16v16H4zM15 4v16', history: 'M3 10a9 9 0 1 1 2 9M3 3v7h7M12 7v5l3 2',
1790
1790
  check: 'M5 12l4 4L19 6', link: 'M10 13a5 5 0 0 0 7 0l4-4a5 5 0 0 0-7-7l-2 2M14 11a5 5 0 0 0-7 0l-4 4a5 5 0 0 0 7 7l2-2',
1791
+ users: 'M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2M9 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8M22 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75',
1791
1792
  settings: 'M12 8a4 4 0 1 0 0 8 4 4 0 0 0 0-8M10 3h4l1 3 3 1 3 3v4l-3 1-1 3-3 3h-4l-1-3-3-1-3-3v-4l3-1 1-3z',
1792
1793
  folder: 'M3 7V5a2 2 0 0 1 2-2h5l2 3h7a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z',
1793
1794
  route: 'M4 5h16M4 12h16M4 19h16M7 3v4M12 10v4M17 17v4',
@@ -1967,8 +1968,10 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
1967
1968
  var progressGradientId=useState(function(){return 'pmw-progress-blue-'+(++overviewGradientSequence)})[0]
1968
1969
  var planServiceReady=!!(props.releases && Array.isArray(props.releases.plans))
1969
1970
  var rs=useState(props.releases || {currentVersion:null,plans:[],fingerprint:null}),releases=rs[0],setReleases=rs[1]
1970
- var versionSt=useState(function(){return props.releases && props.releases.currentVersion || '*'}),version=versionSt[0],setVersion=versionSt[1]
1971
- var statusSt=useState('all'),status=statusSt[0],setStatus=statusSt[1],querySt=useState(''),query=querySt[0],setQuery=querySt[1]
1971
+ var versionSt=useState(function(){return pmBus.overviewContext ? pmBus.overviewContext.version : props.releases && props.releases.currentVersion || '*'}),version=versionSt[0],setVersion=versionSt[1]
1972
+ var statusSt=useState(pmBus.overviewContext && pmBus.overviewContext.status || 'all'),status=statusSt[0],setStatus=statusSt[1],querySt=useState(pmBus.overviewContext && pmBus.overviewContext.query || ''),query=querySt[0],setQuery=querySt[1]
1973
+ var presentationSt=useState(pmBus.overviewContext && pmBus.overviewContext.presentation || 'table'),presentation=presentationSt[0],setPresentation=presentationSt[1]
1974
+ useEffect(function(){pmBus.overviewContext={version:version,status:status,query:query,presentation:presentation}},[version,status,query,presentation])
1972
1975
  var sortSt=useState('updated'),sort=sortSt[0],setSort=sortSt[1],choiceSt=useState(false),choice=choiceSt[0],setChoice=choiceSt[1]
1973
1976
  var infoSt=useState(null),info=infoSt[0],setInfo=infoSt[1],pickerRef=React.useRef(null),pickerButton=React.useRef(null)
1974
1977
  var hs=useState(null),help=hs[0],setHelp=hs[1],helpRef=React.useRef(null),ims=useState(false),importOpen=ims[0],setImportOpen=ims[1]
@@ -2020,10 +2023,10 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
2020
2023
  e('section',{className:'pmw-summary','aria-label':'本版需求统计'},e('div',{className:'pmw-summary__metrics'},statistic('total','需求总数',model.total),statistic('done','已完成',model.completed),statistic('running','进行中',model.running),statistic('waiting','待启动',model.waiting))),
2021
2024
  e('div',{className:'pmw-overview__panels'},train),
2022
2025
  e('section',{className:'pmw-overview__tablepanel','aria-label':'需求列表'},
2023
- e('div',{className:'pmw-overview__boardhead'},e('span',{className:'pmw-panel-icon'},e(UiIcon,{name:'list'})),e('h2',null,'需求地图'),e('span',{role:'status'},model.rows.length)),
2026
+ e('div',{className:'pmw-overview__boardhead'},e('span',{className:'pmw-panel-icon'},e(UiIcon,{name:'list'})),e('h2',null,'需求地图'),e('span',{role:'status'},model.rows.length),e('div',{className:'sa-presentation',role:'group','aria-label':'需求展示方式'},[['table','表格'],['board','看板']].map(function(p){return e('button',{key:p[0],'aria-pressed':presentation===p[0],onClick:function(){setPresentation(p[0])}},p[1])}))),
2024
2027
  e('div',{className:'pmw-overview__tools'},e('div',{className:'pmw-overview__views',role:'group','aria-label':'按需求状态筛选'},tabs.map(function(t){return e('button',{key:t.id,'aria-pressed':status===t.id,onClick:function(){setStatus(t.id)}},t.title,e('span',null,t.count))})),e('label',{className:'pmw-overview__search'},e(UiIcon,{name:'search'}),e('input',{'aria-label':'搜索需求、编码、负责人或应用',placeholder:'搜索需求、负责人或应用',value:query,onChange:function(ev){setQuery(ev.target.value)}}),query && e('button',{'aria-label':'清除总览搜索',onClick:function(){setQuery('')}},e(UiIcon,{name:'close'})))),
2025
2028
  props.requirements.length===0?e('div',{className:'pmw-overview__empty'},e(UiIcon,{name:'grid'}),e('h2',null,'新建第一条需求'),e('button',{className:'pmw-btn pmw-btn--primary',onClick:props.onCreate},'新建需求')):model.rows.length===0?e('div',{className:'pmw-overview__empty'},e(UiIcon,{name:'search'}),e('h2',null,'当前范围没有需求'),e('button',{className:'pmw-btn',onClick:function(){setStatus('all');setQuery('')}},'清除状态与搜索筛选')):
2026
- e('div',{className:'pmw-requirements-scroll'},e('table',{className:'pmw-requirements'},e('thead',null,e('tr',null,['需求','状态','业务方','SA','前端开发','后端开发','测试','外部应用','操作'].map(function(label){return e('th',{key:label,scope:'col'},label)}))),e('tbody',null,model.rows.map(card))))),
2029
+ presentation==='board'?e(RequirementKanban,{requirements:model.rows,onOpen:function(req){setInfo({requirement:req,editing:false})}}):e('div',{className:'pmw-requirements-scroll'},e('table',{className:'pmw-requirements'},e('thead',null,e('tr',null,['需求','状态','业务方','SA','前端开发','后端开发','测试','外部应用','操作'].map(function(label){return e('th',{key:label,scope:'col'},label)}))),e('tbody',null,model.rows.map(card))))),
2027
2030
  help && e('div',{className:'pmw-overview__help',ref:helpRef,role:'dialog','aria-label':help.title,style:{left:help.left,top:help.top}},e('h3',null,help.title),e('p',null,help.text)),
2028
2031
  importOpen && e(ReleaseImportDialog,{onClose:function(){setImportOpen(false)},onSaved:function(value){setReleases(value);props.onRefresh()}}),
2029
2032
  info && e(RequirementInfoDialog,{requirement:info.requirement,startEditing:info.editing,onOpen:props.onOpen,onClose:function(){setInfo(null)},onSaved:props.onRefresh}))
@@ -2338,7 +2341,7 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
2338
2341
  // 全局选择总线:左轨(常驻)与 SA 总览页(main 面板)共享选中态
2339
2342
  // -----------------------------------------------------------------------
2340
2343
  var pmBus = {
2341
- state: { selectedId: null, activeSessionId: null, nav: 'home', selectedVersion: null, tabs: {}, scrolls: {}, files: {}, focus: false },
2344
+ state: { selectedId: null, activeSessionId: null, nav: 'home', selectedVersion: null, tabs: {}, scrolls: {}, files: {}, focus: true },
2342
2345
  listeners: [],
2343
2346
  set: function (patch) {
2344
2347
  var changed = false
@@ -2937,6 +2940,57 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
2937
2940
  directoryBrowser && e(DirectoryBrowser,{key:directoryBrowser.key,title:directoryBrowser.title,start:directoryBrowser.start,onCancel:function(){setDirectoryBrowser(null)},onSelect:function(location){changeField(directoryBrowser.key,location);setDirectoryBrowser(null)}}))
2938
2941
  }
2939
2942
 
2943
+ var WORKSPACE_PREVIEW_CSS = "/* Task navigation is distinct from document controls. Preview is opt-in. */\r\nhtml:has(.sa-workspace-shell) .pmw-nav__group:last-child{display:none}\r\nhtml:root .pmw-root.sa-workspace-shell{--sa-preview-ink:var(--glass-ink,var(--dsw-alias-text-primary));--sa-preview-muted:var(--glass-muted,var(--dsw-alias-text-secondary));--sa-preview-card:var(--glass-card,var(--dsw-alias-background-container));--sa-preview-line:var(--glass-input,var(--dsw-alias-border-l2));}\r\n.sa-workspace-toolbar{display:flex;align-items:center;gap:16px;flex:none;padding:14px 22px 12px;min-height:66px;border-bottom:1px solid color-mix(in srgb,var(--sa-preview-line) 35%,transparent);}\r\n.sa-workspace-tabs{display:flex;gap:3px;padding:4px;border-radius:18px;background:var(--sa-preview-card);box-shadow:0 1px 0 color-mix(in srgb,var(--sa-preview-line) 30%,transparent);backdrop-filter:blur(16px);}\r\n.sa-workspace-tabs button{border:0;background:none;color:var(--sa-preview-muted);font:inherit;font-size:13px;border-radius:14px;padding:9px 16px;white-space:nowrap;cursor:pointer;}\r\n.sa-workspace-tabs button[aria-current=page]{background:var(--sa-preview-ink);color:var(--glass-bg,#fff);}\r\n.sa-workspace-tabs button:focus-visible,.sa-presentation button:focus-visible,.sa-board-card:focus-visible{outline:2px solid var(--glass-primary,#7663db);outline-offset:3px;}\r\n.sa-workspace-label{margin-left:auto;font-size:12px;color:var(--sa-preview-muted);}\r\n.sa-mobile-create{display:none;}\r\n.sa-workspace-toolbar .sa-theme-switch{flex:none;}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-overview__head>.sa-theme-switch{display:none}\r\n.sa-settings-scroll{overflow:auto;min-height:0;flex:1;}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-detail__head{padding:18px 24px 14px;gap:12px;}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-detail__head .sa-assistant-toggle{width:auto;margin-left:8px;gap:7px;border:1px solid var(--sa-preview-line);border-radius:16px;padding:7px 12px;}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-detail__head .sa-assistant-toggle[aria-expanded=true]{background:var(--glass-tint);}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-ai{border-left:1px solid var(--sa-preview-line);background:var(--sa-preview-card);}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-ai__context{gap:8px;}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-ai__context>span{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-ai__context>button{margin-left:auto;padding:4px;flex:none;}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-doc--empty{padding:28px 24px;}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-empty-state{max-width:920px;display:grid;grid-template-columns:minmax(0,1fr) minmax(240px,.85fr);column-gap:32px;row-gap:16px;margin:0 auto;align-content:start;}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-empty-state__heading,html:root .pmw-root.sa-workspace-shell .pmw-empty-state__description{grid-column:1;}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-empty-state__heading{align-self:end;}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-empty-state__description{margin:0;max-width:460px;line-height:1.8;}\r\n.sa-deliverable{grid-column:2;grid-row:1 / span 6;align-self:start;padding:24px;border:1px solid color-mix(in srgb,var(--sa-preview-line) 65%,transparent);border-radius:24px;background:var(--sa-preview-card);box-shadow:0 10px 30px -24px var(--sa-preview-ink);}\r\n.sa-deliverable__eyebrow{font-size:11px;letter-spacing:.12em;color:var(--sa-preview-muted);}\r\n.sa-deliverable h4{font-size:18px;line-height:1.55;margin:10px 0 18px;font-weight:600;color:var(--sa-preview-ink);}\r\n.sa-deliverable ul{padding:0;margin:0;list-style:none;display:grid;gap:14px;}\r\n.sa-deliverable li{display:flex;gap:10px;align-items:flex-start;font-size:13px;line-height:1.65;}\r\n.sa-deliverable li>span{flex:none;font-size:10px;width:24px;height:24px;display:grid;place-items:center;border-radius:50%;background:var(--glass-tint);color:var(--sa-preview-muted);}\r\n.sa-deliverable__hint,.sa-deliverable__missing{font-size:12px;line-height:1.8;color:var(--sa-preview-muted);margin:18px 0 0;}\r\n.sa-deliverable__missing{border-top:1px solid var(--sa-preview-line);padding-top:14px;}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-empty-state>.pmw-sources{grid-column:1;max-width:100%;}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-empty-state>.pmw-empty-state__file,html:root .pmw-root.sa-workspace-shell .pmw-empty-state>.pmw-btn,html:root .pmw-root.sa-workspace-shell .pmw-empty-state>.pmw-empty-state__note{grid-column:1;justify-self:start;margin:0;}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-empty-state>.pmw-btn{border-radius:16px;padding:11px 18px;}\r\n.sa-presentation{display:flex;margin-left:auto;padding:3px;border:1px solid var(--sa-preview-line);border-radius:14px;gap:2px;}\r\n.sa-presentation button{font:inherit;font-size:12px;padding:6px 11px;cursor:pointer;color:var(--sa-preview-muted);border:0;border-radius:10px;background:none;}\r\n.sa-presentation button[aria-pressed=true]{background:var(--sa-preview-card);box-shadow:0 1px 4px #0001;color:var(--sa-preview-ink);}\r\n.sa-requirement-board{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px;padding:8px 0 20px;}\r\n.sa-board-column{background:color-mix(in srgb,var(--sa-preview-ink) 3%,transparent);border-radius:22px;padding:12px;min-height:240px;}\r\n.sa-board-column>header{display:flex;align-items:center;justify-content:space-between;margin:2px 4px 14px;font-size:12px;color:var(--sa-preview-muted);}\r\n.sa-board-card{display:flex;text-align:left;flex-direction:column;gap:10px;cursor:pointer;padding:18px;margin:0 0 12px;width:100%;font:inherit;color:var(--sa-preview-ink);border:1px solid color-mix(in srgb,var(--sa-preview-line) 65%,transparent);border-radius:18px;background:var(--sa-preview-card);transition:transform .15s;}\r\n.sa-board-card:hover{transform:translateY(-2px);}\r\n.sa-board-card code{font-size:11px;color:var(--sa-preview-muted);}\r\n.sa-board-card strong{font-size:15px;line-height:1.6;overflow-wrap:anywhere;}\r\n.sa-board-card__stage,.sa-board-card footer{font-size:11px;line-height:1.6;color:var(--sa-preview-muted);}\r\n.sa-board-card footer{display:flex;justify-content:space-between;gap:8px;padding-top:10px;border-top:1px solid var(--sa-preview-line);flex-wrap:wrap;}\r\n.sa-board-empty{font-size:12px;color:var(--sa-preview-muted);padding:20px 6px;}\r\n@media(max-width:1100px){html:root .pmw-root.sa-workspace-shell:has(.pmw-ai) .pmw-empty-state{grid-template-columns:minmax(0,1fr)}html:root .pmw-root.sa-workspace-shell:has(.pmw-ai) .sa-deliverable{grid-column:1;grid-row:auto;}}\r\n@media(max-width:760px){.sa-workspace-toolbar{padding:10px 14px;gap:8px;}.sa-workspace-tabs button{padding:8px 12px;}.sa-workspace-label{display:none}.sa-workspace-toolbar .sa-theme-switch{margin-left:auto;}html:root .pmw-root.sa-workspace-shell .pmw-empty-state{grid-template-columns:minmax(0,1fr);}.sa-deliverable{grid-column:1;grid-row:auto;}.sa-requirement-board{grid-template-columns:minmax(0,1fr)}html:root .pmw-root.sa-workspace-shell .pmw-doc--empty{padding:20px 16px;}html:root .pmw-root.sa-workspace-shell .pmw-detail__head{padding:14px 16px;}html:root .pmw-root.sa-workspace-shell .pmw-ai{position:absolute;right:0;top:0;bottom:0;z-index:20;width:min(420px,100%);box-shadow:-12px 0 40px #0002;}html:root .pmw-root.sa-workspace-shell .pmw-body{position:relative;}}\r\n@media(prefers-reduced-motion:reduce){.sa-board-card{transition:none}}\r\n\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-detail__title{font-size:20px;font-weight:600;line-height:1.45}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-empty-state{max-width:980px;width:100%}\r\nhtml:root .pmw-root.sa-workspace-shell .sa-deliverable li>span{border-radius:50%!important;corner-shape:round!important}\r\n@media(max-width:760px){html:has(.sa-workspace-shell) .pmw-nav{display:none!important}html:root .pmw-root.sa-workspace-shell .pmw-empty-state{max-width:100%}.sa-workspace-toolbar{gap:6px}.sa-workspace-tabs{min-width:0;overflow-x:auto}.sa-workspace-tabs button{font-size:12px;padding:7px 8px}.sa-workspace-toolbar .sa-theme-switch{margin-left:0!important}}\r\n@media(max-width:760px){.sa-mobile-create{display:inline-flex;align-items:center;justify-content:center;flex:none;width:32px;height:32px;border:1px solid var(--sa-preview-line);border-radius:50%;color:var(--sa-preview-ink);background:var(--sa-preview-card);cursor:pointer}.sa-workspace-tabs{flex:1}.sa-workspace-toolbar{padding:10px}}\r\n\r\n/* Annotation revision: segmented stage route and composed start panel. */\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-stages{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:0;padding:18px 24px 20px;overflow:visible}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-step{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:flex-start;gap:8px;padding:0;overflow:visible;background:none;border:0;min-width:0}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-step::before,html:root .pmw-root.sa-workspace-shell .pmw-step::after{display:none}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-step__number{position:relative;z-index:2;display:flex;align-items:center;justify-content:center;width:40px;height:40px;min-width:40px;padding:0;border-radius:50%!important;corner-shape:round!important;border:1.5px solid var(--sa-preview-line);background:var(--glass-popover,var(--glass-bg));color:var(--sa-preview-muted);box-shadow:none;outline:0}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-step__number>svg{width:19px;height:19px}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-step.is-current .pmw-step__number{background:var(--sa-preview-ink);border-color:var(--sa-preview-ink);color:var(--glass-bg)}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-step.is-active:not(.is-current) .pmw-step__number{border-color:var(--glass-primary);color:var(--glass-primary);background:var(--glass-bg);box-shadow:0 0 0 4px var(--glass-tint)}\r\nhtml:root .pmw-root.sa-workspace-shell .sa-stage-connector{position:absolute;z-index:1;top:19px;left:calc(-50% + 24px);width:calc(100% - 48px);height:0;border-top:2px solid var(--sa-preview-line);pointer-events:none}\r\nhtml:root .pmw-root.sa-workspace-shell .sa-stage-connector.is-reached{border-color:var(--sa-preview-ink)}\r\nhtml:root .pmw-root.sa-workspace-shell .sa-stage-connector.is-optional{border-top-style:dashed}\r\nhtml:root .pmw-root.sa-workspace-shell .sa-stage-done{position:absolute;right:-3px;bottom:-2px;width:16px;height:16px;border-radius:50%;display:grid;place-items:center;background:var(--sa-preview-ink);color:var(--glass-bg);border:2px solid var(--glass-bg)}\r\nhtml:root .pmw-root.sa-workspace-shell .sa-stage-done .pmw-icon{width:10px;height:10px}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-step__label{font-size:13px;line-height:20px}\r\nhtml:root .pmw-root.sa-workspace-shell .pmw-step small{margin:0;font-size:11px;line-height:16px}\r\n.sa-empty-workspace{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,.9fr);gap:28px;max-width:1060px;margin:10px auto 0;width:100%;align-items:stretch}\r\n.sa-empty-workspace>.sa-deliverable{grid-column:auto;grid-row:auto;align-self:stretch;box-shadow:none}\r\n.sa-stage-start{display:flex;flex-direction:column;gap:0;padding:28px;border:1px solid color-mix(in srgb,var(--sa-preview-line) 60%,transparent);border-radius:24px;background:var(--sa-preview-card);min-width:0}\r\n.sa-stage-start__header{display:flex;gap:10px;align-items:center;font-size:12px;color:var(--sa-preview-muted)}\r\n.sa-stage-start__glyph{display:grid;place-items:center;width:36px;height:36px;border-radius:12px;color:var(--glass-primary);background:var(--glass-tint)}\r\n.sa-stage-start__state{margin-left:auto;font-size:11px;padding:4px 9px;border-radius:999px;background:var(--glass-secondary)}\r\nhtml:root .pmw-root.sa-workspace-shell .sa-stage-start h3{font-size:24px;line-height:1.4;font-weight:600;margin:22px 0 12px;color:var(--sa-preview-ink)}\r\n.sa-stage-start__intro{font-size:13px;line-height:1.85;margin:0 0 24px;color:var(--sa-preview-muted)}\r\nhtml:root .pmw-root.sa-workspace-shell .sa-stage-start>.pmw-sources{max-width:100%;width:100%;margin:0 0 18px}\r\n.sa-stage-output{display:flex;align-items:center;gap:12px;background:var(--glass-secondary);border:1px solid color-mix(in srgb,var(--sa-preview-line) 45%,transparent);border-radius:16px;padding:15px 16px;margin-top:auto}\r\n.sa-stage-output__icon{display:grid;place-items:center;width:36px;height:40px;border-radius:9px;background:var(--glass-card);color:var(--sa-preview-muted)}\r\n.sa-stage-output small{display:block;font-size:11px;color:var(--sa-preview-muted);margin-bottom:4px}\r\n.sa-stage-output code{display:block;font-size:13px;color:var(--sa-preview-ink);overflow-wrap:anywhere}\r\n.sa-stage-start__actions{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-top:22px}\r\nhtml:root .pmw-root.sa-workspace-shell .sa-stage-start__actions .pmw-btn{display:inline-flex;align-items:center;gap:18px;padding:11px 18px;border-radius:14px}\r\n.sa-stage-start__actions>span{font-size:11px;color:var(--sa-preview-muted)}\r\n@media(max-width:1100px){html:root .pmw-root.sa-workspace-shell:has(.pmw-ai) .sa-empty-workspace{grid-template-columns:minmax(0,1fr)}}\r\n@media(max-width:760px){.sa-empty-workspace{grid-template-columns:minmax(0,1fr);gap:18px;margin-top:0}.sa-stage-start{padding:22px}.sa-empty-workspace>.sa-deliverable{grid-column:auto;grid-row:auto}html:root .pmw-root.sa-workspace-shell .pmw-stages{padding:16px 12px 18px}html:root .pmw-root.sa-workspace-shell .pmw-step__number{width:34px;height:34px;min-width:34px}html:root .pmw-root.sa-workspace-shell .sa-stage-connector{top:16px;left:calc(-50% + 21px);width:calc(100% - 42px)}html:root .pmw-root.sa-workspace-shell .pmw-step__label{font-size:11px}}\r\n";
2944
+ function StageGlyph(props){
2945
+ var paths={intake:['M4 5h16v11H9l-5 4V5','M8 9h8M8 12h5'],solution:['M4 4h6v6H4zM14 14h6v6h-6z','M10 7h7v7M7 10v7h7'],prd:['M14 3H6a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V8l-5-5z','M14 3v5h5M8 14l2 2 5-5'],prototype:['M3 4h18v16H3z','M3 9h18M9 9v11']};
2946
+ return e('svg',{width:20,height:20,viewBox:'0 0 24 24',fill:'none',stroke:'currentColor',strokeWidth:1.65,strokeLinecap:'round',strokeLinejoin:'round','aria-hidden':true},(paths[props.stage] || paths.prd).map(function(d,i){return e('path',{key:i,d:d})}))
2947
+ }
2948
+ function StageStartCard(props){
2949
+ var action={intake:'开始梳理',solution:'开始设计',prd:'开始编写',prototype:'开始制作'}[props.stage];
2950
+ return e('section',{className:'sa-stage-start','aria-label':props.title},
2951
+ e('header',{className:'sa-stage-start__header'},e('span',{className:'sa-stage-start__glyph'},e(StageGlyph,{stage:props.stage})),e('span',null,props.archived?'归档记录':'准备开始'),e('span',{className:'sa-stage-start__state'},props.archived?'未包含':'尚未生成')),
2952
+ e('h3',null,props.title),e('p',{className:'sa-stage-start__intro'},props.description),
2953
+ props.sources,
2954
+ props.artifact && e('div',{className:'sa-stage-output'},e('span',{className:'sa-stage-output__icon'},e(StageGlyph,{stage:props.stage})),e('div',null,e('small',null,props.archived?'未包含文件':'交付文件'),e('code',null,props.artifact.path))),
2955
+ !props.archived && props.artifact && e('footer',{className:'sa-stage-start__actions'},e('button',{className:'pmw-btn pmw-btn--primary',disabled:props.busy,onClick:props.onStart},props.busy?'正在准备…':action,e('svg',{width:16,height:16,viewBox:'0 0 24 24',fill:'none',stroke:'currentColor',strokeWidth:1.8,'aria-hidden':true},e('path',{d:'M5 12h14M13 6l6 6-6 6',strokeLinecap:'round',strokeLinejoin:'round'}))),e('span',null,'使用当前工作方法')))
2956
+ }
2957
+ function WorkspaceNavigation(props){
2958
+ var active=props.current==='create'?'home':props.current;
2959
+ return e('header',{className:'sa-workspace-toolbar'},
2960
+ e('nav',{'aria-label':'SA 工作台导航',className:'sa-workspace-tabs'},[['home','需求'],['kb','知识库'],['plib','归档库'],['settings','工作方法']].map(function(t){return e('button',{key:t[0],type:'button','aria-current':active===t[0]?'page':undefined,onClick:function(){props.onNavigate(t[0])}},t[1])})),
2961
+ e('span',{className:'sa-workspace-label'},'SA 工作台'),
2962
+ e('button',{className:'sa-mobile-create',type:'button','aria-label':'新建需求',onClick:function(){props.onNavigate('create')}},e(UiIcon,{name:'plus'})),
2963
+ e('div',{className:'sa-theme-switch','aria-label':'工作台外观'},['light','dark'].map(function(a){return e('button',{key:a,type:'button','aria-label':a==='light'?'浅色模式':'暗色模式','aria-pressed':(pmBus.state.appearance || saAppearance())===a,onClick:function(){setSaAppearance(a)}},a==='light'?'☀':'☾')})))
2964
+ }
2965
+ function stageDeliverableModel(stage,requirement,artifact){
2966
+ var definitions={
2967
+ intake:{title:'一份可继续设计的业务需求',items:['业务目标与使用场景','范围、现状与资料依据','需要进一步确认的问题']},
2968
+ solution:{title:'一份可讨论的高阶方案',items:['关键设计点与系统职责','业务流程、依赖及改造范围','方案依据与待决策事项']},
2969
+ prd:{title:'一份可评审、可验证的 PRD',items:['用户故事与完整业务规则','Given / When / Then 验收条件','相关流程与交互说明']},
2970
+ prototype:{title:'一份可操作的交互原型',items:['主要页面与关键任务路径','适用的正常、异常与空状态','供讨论与迭代的页面交互']}
2971
+ };
2972
+ var model=definitions[stage] || definitions.intake;
2973
+ var prior=stage==='solution'?['intake']:stage==='prd'?['intake','solution']:stage==='prototype'?['prd']:[];
2974
+ var missing=prior.filter(function(id){var s=(requirement.stages || []).find(function(s){return s.id===id});return !s || !(s.artifacts || []).some(function(a){return a.exists})});
2975
+ return {title:model.title,items:model.items,missing:missing.map(function(id){return {intake:'业务需求',solution:'高阶方案',prd:'PRD'}[id]}),file:artifact && artifact.path,archived:!!requirement.archived};
2976
+ }
2977
+ function StageDeliverablePreview(props){
2978
+ var model=stageDeliverableModel(props.stage,props.requirement,props.artifact);
2979
+ if(model.archived)return null;
2980
+ return e('aside',{className:'sa-deliverable','aria-label':'本阶段交付预览'},
2981
+ e('div',{className:'sa-deliverable__eyebrow'},'本阶段交付'),e('h4',null,model.title),
2982
+ e('ul',null,model.items.map(function(text,i){return e('li',{key:text},e('span',{'aria-hidden':true},String(i+1).padStart(2,'0')),text)})),
2983
+ model.missing.length>0 && e('p',{className:'sa-deliverable__missing'},'尚未发现'+model.missing.join('、')+'文档。助手会先核对依据,必要时补充澄清。'),
2984
+ e('p',{className:'sa-deliverable__hint'},'以上为预期内容,当前尚未生成;生成后仍需评审。'))
2985
+ }
2986
+ function RequirementKanban(props){
2987
+ return e('div',{className:'sa-requirement-board','aria-label':'需求状态看板'},[['waiting','待启动'],['running','进行中'],['done','已完成']].map(function(group){
2988
+ var rows=props.requirements.filter(function(r){return overviewStatus(r)===group[0]});
2989
+ return e('section',{key:group[0],className:'sa-board-column'},e('header',null,e('span',{className:'pmw-stage-pill is-'+group[0]},e('i',{'aria-hidden':true}),group[1]),e('span',null,rows.length)),
2990
+ rows.length?rows.map(function(req){var c=collaborationValue(req),stages=req.stages || [],existing=stages.filter(function(s){return (s.artifacts || []).some(function(a){return a.exists})}).length;return e('button',{key:req.id,className:'sa-board-card',onClick:function(){props.onOpen(req)},'aria-label':'查看 '+req.code+' '+req.title},e('code',null,req.code),e('strong',null,req.title),e('span',{className:'sa-board-card__stage'},stageTitle(req)),e('footer',null,e('span',null,c.pmOwner || 'SA 待填写'),e('span',null,existing?existing+' 个阶段已有稿':'尚无阶段稿')))}):e('p',{className:'sa-board-empty'},'当前筛选下暂无需求'))
2991
+ }))
2992
+ }
2993
+
2940
2994
  function Panel(props) {
2941
2995
  var layout = props.layout
2942
2996
  var pm = props.pm
@@ -2949,6 +3003,7 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
2949
3003
  var form = useState('home')
2950
3004
  var view = form[0]
2951
3005
  var setView = form[1]
3006
+ var pendingNavigationSt=useState(null),pendingNavigation=pendingNavigationSt[0],setPendingNavigation=pendingNavigationSt[1]
2952
3007
  var ft = useState('')
2953
3008
  var formTitle = ft[0]
2954
3009
  var setFormTitle = ft[1]
@@ -3348,7 +3403,7 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
3348
3403
  return pm.sendToReq(selected, dir, body.prompt).then(function (res) {
3349
3404
  setBusy(false)
3350
3405
  if (!res || !res.ok) setOpErr((res && res.error) || '发送失败')
3351
- else {setNotice('已发送到对话 · 使用 '+body.skill.name+';请在会话中查看进展。');if(stageId==='intake')return apiSend('POST','/requirement-start',{id:selected.id}).then(reload)}
3406
+ else {pmBus.set({focus:false});setNotice('已发送到对话 · 使用 '+body.skill.name+';请在会话中查看进展。');if(stageId==='intake')return apiSend('POST','/requirement-start',{id:selected.id}).then(reload)}
3352
3407
  })
3353
3408
  }).catch(function (err) {
3354
3409
  setBusy(false)
@@ -3517,10 +3572,16 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
3517
3572
  }).catch(function(err) { if (pmBus.state.selectedId === owner.id) setOpErr(String(err.message || err)) }).finally(function(){setBusy(false)})
3518
3573
  }
3519
3574
 
3575
+ function navigateWorkspace(target){
3576
+ if(editor){setPendingNavigation(target);return}
3577
+ completeNavigation(target)
3578
+ }
3579
+ function completeNavigation(target){setPendingNavigation(null);setEditor(null);pmBus.set({nav:target,selectedId:null,activeSessionId:null,settingsReturn:null});setView(target)}
3580
+ var workspaceNav=e(WorkspaceNavigation,{current:view,onNavigate:navigateWorkspace})
3520
3581
  var children = []
3521
3582
 
3522
3583
  if (data.data && (data.data.setupRequired || data.data.restartRequired)) return e('div',{className:'pmw-root','data-sa-appearance':bus.appearance || saAppearance()},e(SettingsPanel,{onboarding:true,onComplete:function(){pmBus.set({nav:'home',selectedId:null,activeSessionId:null,settingsReturn:null});setView('home');reload()}}))
3523
- if (view === 'settings') return e('div', { className: 'pmw-root', 'data-sa-appearance':bus.appearance || saAppearance() }, e(SettingsPanel))
3584
+ if (view === 'settings') return e('div', { className: 'pmw-root sa-workspace-shell', 'data-sa-appearance':bus.appearance || saAppearance() },e('style',null,WORKSPACE_PREVIEW_CSS),workspaceNav,e('div',{className:'sa-settings-scroll'},e(SettingsPanel)))
3524
3585
 
3525
3586
  // header(纯标题,动作全部收进各自语境:Tab 空态/地铁图归档站/右栏线程条)
3526
3587
  if (!selected && (view !== 'home' || !data.data)) children.push(e('div', { className: 'pmw-header', key: 'header' },
@@ -3541,7 +3602,7 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
3541
3602
  e('div',{className:'pmw-dialog__body'},e('label',{className:'pmw-field'},e('span',{className:'pmw-field__label'},'文件名称'),e('input',{className:'pmw-input',autoFocus:true,'aria-label':'文件名称',value:newFile.name,maxLength:110,onChange:function(ev){setNewFile(Object.assign({},newFile,{name:ev.target.value}))},placeholder:'例如:接口说明'})),
3542
3603
  e('label',{className:'pmw-field'},e('span',{className:'pmw-field__label'},'文档内容'),e('textarea',{className:'pmw-textarea','aria-label':'新增文档内容',value:newFile.content,onChange:function(ev){setNewFile(Object.assign({},newFile,{content:ev.target.value}))},placeholder:'支持 Markdown'})),opErr && e('p',{role:'alert'},opErr)),
3543
3604
  e('div',{className:'pmw-dialog__foot'},e('button',{type:'button',className:'pmw-btn',disabled:isBusy,onClick:function(){setNewFile(null)}},'取消'),e('button',{type:'submit',className:'pmw-btn pmw-btn--primary',disabled:isBusy || !newFile.name.trim() || !newFile.content.trim()},isBusy?'正在添加…':'添加文档')))))
3544
- return e('div', { ref:rootRef, className: 'pmw-root' + (expanded ? ' is-expanded' : ''), 'data-sa-appearance':bus.appearance || saAppearance() }, children)
3605
+ return e('div', { ref:rootRef, className: 'pmw-root sa-workspace-shell' + (expanded ? ' is-expanded' : ''), 'data-sa-appearance':bus.appearance || saAppearance() },e('style',null,WORKSPACE_PREVIEW_CSS),!expanded && workspaceNav,pendingNavigation && e(DetailDialog,{title:'离开未保存的文档?',onClose:function(){setPendingNavigation(null)},footer:e(React.Fragment,null,e('button',{className:'pmw-btn',onClick:function(){setPendingNavigation(null)}},'继续编辑'),e('button',{className:'pmw-btn pmw-btn--primary',onClick:function(){completeNavigation(pendingNavigation)}},'放弃修改并离开'))},e('p',null,'当前修改尚未保存。继续编辑可保留草稿;离开将放弃这些修改,原文件不变。')),children)
3545
3606
  }
3546
3607
 
3547
3608
  // body: main + chat
@@ -3676,13 +3737,10 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
3676
3737
  return e('button', { key: stage.id, className: 'pmw-step' + (stage.id === curTab ? ' is-active' : '') + (exists ? ' is-complete' : '') + (current ? ' is-current' : '') + (optional ? ' is-optional' : ''),
3677
3738
  'aria-pressed': stage.id === curTab, 'aria-current': current ? 'step' : undefined, title: stage.title + ' · ' + (exists ? '已有文档' : '尚未生成') + (stage.id === curTab ? ' · 正在查看' : ''),
3678
3739
  onClick: function () { if (stage.id === curTab) return; if (editor && !confirm('有未保存的修改,确定放弃并切换文档?')) return; setEditor(null); setTabSt(stage.id) },
3679
- }, e('span', { className: 'pmw-step__number', 'aria-hidden': true }, exists ? e(UiIcon,{name:'check'}) : String(index + 1)),
3740
+ },index>0 && e('span',{className:'sa-stage-connector'+(optional?' is-optional':'')+((exists || current) && selected.stages[index-1].artifacts[0].exists?' is-reached':''),'aria-hidden':true}),e('span',{className:'pmw-step__number','aria-hidden':true},e(StageGlyph,{stage:stage.id}),exists && e('span',{className:'sa-stage-done'},e(UiIcon,{name:'check'}))),
3680
3741
  e('span', {className:'pmw-step__label'}, label), e('small', null, status))
3681
3742
  })
3682
- metroNodes.unshift(e('svg',{key:'route',className:'pmw-metro__track',viewBox:'0 0 1000 64',preserveAspectRatio:'none','aria-hidden':true},
3683
- e('path',{className:'pmw-metro__line',d:'M125 20 H625',vectorEffect:'non-scaling-stroke'}),
3684
- progressX > 125 && e('path',{className:'pmw-metro__line is-travelled',d:'M125 20 H'+progressX,vectorEffect:'non-scaling-stroke'}),
3685
- e('path',{className:'pmw-metro__line pmw-metro__branch'+(prototypeExists ? ' is-travelled' : ''),d:'M625 20 H875',vectorEffect:'non-scaling-stroke'})))
3743
+
3686
3744
 
3687
3745
  var currentDocReady = doc && curArt && doc.path === curArt.path && !doc.loading && !doc.error
3688
3746
  var cloudReceipt = currentDocReady && doc.receipt
@@ -3713,20 +3771,9 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
3713
3771
  var sourcesNode = curTab === 'intake' && e(SourceInputs,{key:'sources-'+selected.id,id:selected.id,readOnly:!!selected.archived,hasDoc:!!(curArt && curArt.exists),stageBusy:isBusy,onBusy:setSourceBusy,onStart:function(){handStage('intake')}})
3714
3772
  if (!curArt || !curArt.exists) {
3715
3773
  var emptyCopy={intake:['梳理业务需求','从你的诉求和业务资料开始,澄清目标、使用场景与范围,保留待确认的问题。','梳理需求'],solution:['形成高阶方案','结合业务需求与现状,明确系统职责、改造方向、依赖与未决事项。','设计高阶方案'],prd:['编写 PRD','基于需求与高阶方案,展开可验证的功能、业务规则和验收条件。','编写 PRD'],prototype:['制作交互原型','用可操作的页面检验 PRD 中的流程与交互。原型按需交付,不阻止归档。','制作原型']}[curTab]
3716
- contentNode = e('div', { className: 'pmw-doc pmw-doc--empty', key: 'empty' },e('section',{className:'pmw-empty-state'},
3717
- e('div',{className:'pmw-empty-state__heading'},
3718
- e('div',{className:'pmw-empty-state__icon','aria-hidden':true},e(UiIcon,{name:curTab==='prototype'?'select':'doc'})),
3719
- e('h3',null,selected.archived ? '本次归档未包含'+documentName : emptyCopy[0])),
3720
- e('p',{className:'pmw-empty-state__description'},selected.archived ? '此归档保留了当时已有的交付文件,未生成的文档不会自动补齐。' : emptyCopy[1]),
3721
- sourcesNode,
3722
- curArt && e('div',{className:'pmw-empty-state__file'},e(UiIcon,{name:'doc'}),selected.archived?'未包含文件':'交付文件',e('code',null,curArt.path)),
3723
- !selected.archived && curArt && e('button', {
3724
- className: 'pmw-btn pmw-btn--primary',
3725
- disabled: isBusy || sourceBusy,
3726
- onClick: function () { handStage(curTab) },
3727
- }, isBusy ? '正在准备…' : '开始动手吧'),
3728
- !selected.archived && e('p',{className:'pmw-empty-state__note'},'使用当前绑定的工作方法发送到当前对话;信息不足时先澄清。'),
3729
- ))
3774
+ contentNode=e('div',{className:'pmw-doc pmw-doc--empty',key:'empty'},e('div',{className:'sa-empty-workspace'},
3775
+ e(StageStartCard,{stage:curTab,title:selected.archived?'本次归档未包含'+documentName:emptyCopy[0],description:selected.archived?'此归档保留了当时已有的交付文件,未生成的文档不会自动补齐。':emptyCopy[1],artifact:curArt,archived:!!selected.archived,sources:sourcesNode,busy:isBusy || sourceBusy,onStart:function(){handStage(curTab)}}),
3776
+ e(StageDeliverablePreview,{stage:curTab,requirement:selected,artifact:curArt})))
3730
3777
  } else if (doc && doc.path === curArt.path) {
3731
3778
  var isHtml = /\.html?$/i.test(doc.path)
3732
3779
  // UX 标注工具条:原型 Tab、当前版本即出现;已归档降级为只读(可看 pin,不可新增/改稿)
@@ -3785,10 +3832,10 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
3785
3832
  mainChildren.push(e('div', { className: 'pmw-detail', key: 'detail' },
3786
3833
  !expanded && e('div', { className: 'pmw-detail__head' },
3787
3834
  e('h2', { className: 'pmw-detail__title' }, selected.title),
3788
- e('button',{className:'pmw-btn pmw-btn--ghost',onClick:function(){setRequirementInfo(selected)}},e(UiIcon,{name:'settings'}),'协作信息'),
3835
+ e('button',{className:'pmw-btn pmw-btn--ghost',onClick:function(){setRequirementInfo(selected)}},e(UiIcon,{name:'users'}),'协作信息'),
3789
3836
  selected.code ? e('span', { className: 'pmw-tag pmw-tag--code' }, selected.code) : null,
3790
3837
  e('span', { className: 'pmw-detail__version' }, selected.version || '未排期'),
3791
- e('button', { className: 'pmw-btn pmw-btn--ghost pmw-btn--icon', 'aria-label': bus.focus ? '显示会话' : '专注阅读', 'aria-pressed': bus.focus, onClick: function () { pmBus.set({ focus: !bus.focus }) } }, e(UiIcon, { name: 'focus' })),
3838
+ e('button', { className: 'pmw-btn pmw-btn--ghost sa-assistant-toggle', 'aria-label':bus.focus?'打开需求助手':'收起需求助手','aria-expanded':!bus.focus,onClick:function(){pmBus.set({focus:!bus.focus})} },e(UiIcon,{name:'chat'}),bus.focus?'助手':'收起助手'),
3792
3839
  ),
3793
3840
  !expanded && e('nav', { className: 'pmw-stages', 'aria-label': '需求交付阶段' }, metroNodes),
3794
3841
  tabBar,
@@ -3842,7 +3889,7 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
3842
3889
  var chatError = bus.sessionError || (convRef && convRef.id === activeSessionId && convRef.error)
3843
3890
  chatNode = e('div', { className: 'pmw-ai', key: 'ai' },
3844
3891
  barNode,
3845
- e('div', { className: 'pmw-ai__context' }, e(UiIcon, { name: 'link' }), e('span', null, selected.code + ' · ' + selected.title)),
3892
+ e('div', { className: 'pmw-ai__context' }, e(UiIcon, { name: 'link' }), e('span', null, selected.code + ' · ' + selected.title),e('button',{className:'pmw-btn pmw-btn--ghost','aria-label':'收起需求助手',onClick:function(){pmBus.set({focus:true})}},e(UiIcon,{name:'close'}))),
3846
3893
  canChat
3847
3894
  ? e('div', { className: 'pmw-ai__conv', key: 'conv' },
3848
3895
  e(props.SessionProvider, { session: convRef.ref }, props.renderSlot('pm.conv', {})))
@@ -3881,7 +3928,7 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
3881
3928
  e('div',{className:'pmw-dialog__body'},e('label',{className:'pmw-field'},e('span',{className:'pmw-field__label'},'文件名称'),e('input',{className:'pmw-input',autoFocus:true,'aria-label':'文件名称',value:newFile.name,maxLength:110,onChange:function(ev){setNewFile(Object.assign({},newFile,{name:ev.target.value}))},placeholder:'例如:接口说明'})),
3882
3929
  e('label',{className:'pmw-field'},e('span',{className:'pmw-field__label'},'文档内容'),e('textarea',{className:'pmw-textarea','aria-label':'新增文档内容',value:newFile.content,onChange:function(ev){setNewFile(Object.assign({},newFile,{content:ev.target.value}))},placeholder:'支持 Markdown'})),opErr && e('p',{role:'alert'},opErr)),
3883
3930
  e('div',{className:'pmw-dialog__foot'},e('button',{type:'button',className:'pmw-btn',disabled:isBusy,onClick:function(){setNewFile(null)}},'取消'),e('button',{type:'submit',className:'pmw-btn pmw-btn--primary',disabled:isBusy || !newFile.name.trim() || !newFile.content.trim()},isBusy?'正在添加…':'添加文档')))))
3884
- return e('div', { ref:rootRef, className: 'pmw-root' + (expanded ? ' is-expanded' : ''), 'data-sa-appearance':bus.appearance || saAppearance() }, children)
3931
+ return e('div', { ref:rootRef, className: 'pmw-root sa-workspace-shell' + (expanded ? ' is-expanded' : ''), 'data-sa-appearance':bus.appearance || saAppearance() },e('style',null,WORKSPACE_PREVIEW_CSS),!expanded && workspaceNav,pendingNavigation && e(DetailDialog,{title:'离开未保存的文档?',onClose:function(){setPendingNavigation(null)},footer:e(React.Fragment,null,e('button',{className:'pmw-btn',onClick:function(){setPendingNavigation(null)}},'继续编辑'),e('button',{className:'pmw-btn pmw-btn--primary',onClick:function(){completeNavigation(pendingNavigation)}},'放弃修改并离开'))},e('p',null,'当前修改尚未保存。继续编辑可保留草稿;离开将放弃这些修改,原文件不变。')),children)
3885
3932
  }
3886
3933
 
3887
3934
  // -----------------------------------------------------------------------
@@ -1 +1 @@
1
- {"type":"module","version":"0.1.28"}
1
+ {"type":"module","version":"0.1.29"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-sa-workbench",
3
- "version": "0.1.28",
3
+ "version": "0.1.29",
4
4
  "description": "SA 工作台:需求整理、方案、PRD、原型和交付归档,一个插件统一安装与更新。",
5
5
  "type": "module",
6
6
  "main": "index.js",