diff --git a/src/assets/scoring/screen-wave.png b/src/assets/scoring/screen-wave.png new file mode 100644 index 0000000..6810906 Binary files /dev/null and b/src/assets/scoring/screen-wave.png differ diff --git a/src/views/match/manage/index.vue b/src/views/match/manage/index.vue index 8889403..12561cc 100644 --- a/src/views/match/manage/index.vue +++ b/src/views/match/manage/index.vue @@ -244,7 +244,7 @@ const columns = reactive([ prop: 'matchTime', label: '比赛时间', }, - { prop: 'action', label: '操作', align: 'center', width: 200, fixed: 'right', isShow: auths(['event:edit', 'event:delete', 'event:workbench']) }, + { prop: 'action', label: '操作', align: 'center', width: 250, fixed: 'right', isShow: auths(['event:edit', 'event:delete', 'event:workbench']) }, ]); const exportableColumns = computed(() => [ diff --git a/src/views/scoring/screen/index.vue b/src/views/scoring/screen/index.vue index dea9308..4f5df8a 100644 --- a/src/views/scoring/screen/index.vue +++ b/src/views/scoring/screen/index.vue @@ -1,8 +1,10 @@ + + diff --git a/src/views/scoring/workbench/index.vue b/src/views/scoring/workbench/index.vue index a8935db..e4fc986 100644 --- a/src/views/scoring/workbench/index.vue +++ b/src/views/scoring/workbench/index.vue @@ -23,25 +23,25 @@
+
+
{{ selectedSession.projectName || '未命名项目' }}{{ selectedSession.groupName || '混合组别' }}场次 {{ selectedSession.sessionNo }} · {{ selectedSession.venueName }}
+
{{ entries.length }}当前列表
+
- - - 查询 - 重置 +
查询重置
- 投出排名 - 打开成绩大屏 +
投出排名打开成绩大屏 +
-
- LIVE
当前正在投屏:{{ currentCast.castType === 1 ? '单人成绩' : '组别排名' }}{{ formatTime(currentCast.castTime) }}
撤回投屏 +
+ LIVE
当前正在展示:{{ currentCastSummary }}{{ formatTime(currentCast.castTime) }}
查看大屏撤回投屏
- +
@@ -52,11 +52,11 @@ - @@ -67,14 +67,14 @@ -
选手/队伍{{detailRow.teamName || detailRow.participantName}}
总分{{score(detailRow.result?.totalScore)}}
成绩版本V{{detailRow.result?.resultVersion || 0}}
+
选手/队伍{{detailRow.teamName || detailRow.participantName}}
总分{{score(detailRow.result?.totalScore)}}
成绩版本V{{detailRow.result?.resultVersion || 0}}
-
确认重赛,本组选手将顺延至当前组别最后出场进行重赛,你还要继续吗?
+
确认后,该选手将顺延至当前组别末尾重新出场。请确认现场安排已就绪。
@@ -97,11 +97,14 @@ const eventName=ref(String(route.query.eventName||savedContext.eventName||'未 if(eventId.value)sessionStorage.setItem('scoring-context',JSON.stringify({...savedContext,eventId:eventId.value,eventName:eventName.value,mode:'freestyle'})); const activeTab=ref('screen'), sessions=ref([]), selectedSession=ref(null), entries=ref([]), currentCast=ref(null); const loadingSessions=ref(false), loadingEntries=ref(false), offline=ref(false), sessionKeyword=ref(''), sessionStatus=ref(null), entryKeyword=ref(''), resultStatus=ref(null), selectedResultIds=ref([]); -const detailVisible=ref(false), detailRow=ref(null), rankingVisible=ref(false), reasonVisible=ref(false), reasonAction=ref(''), reasonText=ref(''), reasonRow=ref(null), actionLoading=ref(false); -const correctionVisible=ref(false), correctionRow=ref(null), correctionForm=ref({scoreSheetId:null,reason:''}); +const detailVisible=ref(false), detailRow=ref(null), rankingVisible=ref(false), reasonVisible=ref(false), reasonAction=ref(''), reasonText=ref(''), reasonRow=ref(null), actionLoading=ref(false), rowActionId=ref(null); +const correctionVisible=ref(false), correctionRow=ref(null), correctionForm=ref({judgeRoleType:'',scoreSheetId:null,reason:''}); +const rematchVisible=ref(false), rematchRow=ref(null); const corrections=ref([]), loadingCorrections=ref(false), correctionKeyword=ref(''), correctionStatus=ref(null); let pollTimer; let entriesRequesting=false,currentCastRequesting=false; +let scoreScreenWindow=null; +const scoreScreenWindowName='yd-event-score-screen'; const resultStatuses=[{value:0,label:'计算中'},{value:10,label:'待复核'},{value:20,label:'已确认'},{value:30,label:'已投屏'},{value:40,label:'已更正'},{value:90,label:'已作废'}]; const sessionStatuses=[{value:0,label:'草稿'},{value:10,label:'就绪'},{value:20,label:'检录中'},{value:30,label:'进行中'},{value:40,label:'暂停'},{value:50,label:'待确认'},{value:60,label:'已结束'}]; @@ -111,9 +114,21 @@ const rankingSelection=computed(()=>rankingOptions.value.find(x=>x.key===ranking const showDifficulty=computed(()=>!String(selectedSession.value?.scoreRuleCode||'').toUpperCase().includes('PRESCRIBED')); const detailColumns=computed(()=>{const map=new Map();for(const sheet of detailRow.value?.judgeScores||[])for(const item of sheet.scoreItems||[]){const key=`${item.itemCode}:${item.subjectCode||''}`;if(!map.has(key))map.set(key,{key,label:item.subjectCode?`${item.itemName}-${item.subjectCode}`:item.itemName,sort:item.sort})}return [...map.values()].sort((a,b)=>a.sort-b.sort)}); const detailRows=computed(()=>(detailRow.value?.judgeScores||[]).map(sheet=>({...sheet,itemValues:Object.fromEntries((sheet.scoreItems||[]).map(item=>[`${item.itemCode}:${item.subjectCode||''}`,item.inputValue??item.countValue??item.subtotal]))}))); +const correctionGroups=computed(()=>{const groups=new Map();for(const sheet of correctionRow.value?.judgeScores||[]){const key=sheet.judgeRoleType||sheet.judgeRoleName;if(key&&!groups.has(key))groups.set(key,{judgeRoleType:key,judgeRoleName:sheet.judgeRoleName||key})}return [...groups.values()]}); +const correctionSheetOptions=computed(()=>(correctionRow.value?.judgeScores||[]).filter(sheet=>(sheet.judgeRoleType||sheet.judgeRoleName)===correctionForm.value.judgeRoleType)); const correctionStatuses=[{value:0,label:'已申请'},{value:10,label:'已批准'},{value:20,label:'已拒绝'},{value:30,label:'裁判修改中'},{value:40,label:'已完成'}]; const tabTitle=computed(()=>({screen:'成绩投屏',results:'成绩管理',corrections:'成绩修正申请'})[activeTab.value]); const tabDescription=computed(()=>({screen:'选择已完成成绩投到现场大屏',results:'复核成绩、查看评分单并处理异常比赛',corrections:'审批裁判发起的修正申请并追踪处理进度'})[activeTab.value]); +const currentCastPayload=computed(()=>{try{const value=JSON.parse(currentCast.value?.payloadJson||'{}');return Array.isArray(value)?value.map(normalizeCastValue):normalizeCastValue(value)}catch{return {}}}); +const currentCastSummary=computed(()=>{ + if(!currentCast.value)return '—'; + if(currentCast.value.castType===2)return `${currentCast.value.projectName||'当前项目'} / ${currentCast.value.groupName||'当前组别'}排名`; + const data=currentCastPayload.value; + const name=data.teamName||data.participantName||'未命名选手'; + return `${name} · ${score(data.totalScore??data.score)}分`; +}); + +function normalizeCastValue(value){if(!value||typeof value!=='object')return value;return Object.fromEntries(Object.entries(value).map(([key,item])=>[key.charAt(0).toLowerCase()+key.slice(1),item]))} async function ensureEvent(){ if(eventId.value)return true; @@ -123,7 +138,7 @@ async function ensureEvent(){ } async function loadSessions(){if(!await ensureEvent())return;loadingSessions.value=true;try{const res=await workbenchSessionsGet({eventId:eventId.value,keyword:sessionKeyword.value||undefined,sessionStatus:sessionStatus.value??undefined});sessions.value=res?.data||[];if(!sessions.value.some(x=>x.sessionId===selectedSession.value?.sessionId))selectedSession.value=null;if(!selectedSession.value&&sessions.value.length)await selectSession(sessions.value[0]);}finally{loadingSessions.value=false}} -async function selectSession(session){selectedSession.value=session;await loadEntries()} +async function selectSession(session){selectedResultIds.value=[];selectedSession.value=session;await loadEntries()} async function loadEntries(silent=false){if(!selectedSession.value||entriesRequesting)return;entriesRequesting=true;if(!silent)loadingEntries.value=true;try{const res=await workbenchSessionEntriesGet(selectedSession.value.sessionId,{keyword:entryKeyword.value||undefined,resultStatus:resultStatus.value??undefined});entries.value=res?.data||[];offline.value=false}catch{offline.value=true}finally{entriesRequesting=false;loadingEntries.value=false}} async function loadCurrentCast(){if(!eventId.value||currentCastRequesting)return;currentCastRequesting=true;try{const res=await workbenchScreenCastCurrentGet({eventId:eventId.value,venueId:selectedSession.value?.venueId});currentCast.value=res?.data||null;offline.value=false}catch{offline.value=true}finally{currentCastRequesting=false}} async function loadCorrections(){if(!eventId.value)return;loadingCorrections.value=true;try{const res=await workbenchCorrectionsGet({eventId:eventId.value,keyword:correctionKeyword.value||undefined,correctionStatus:correctionStatus.value??undefined});corrections.value=res?.data||[]}finally{loadingCorrections.value=false}} @@ -139,24 +154,59 @@ function resultTag(status){return ({10:'warning',20:'success',30:'primary',40:'s function formatTime(value){return value?String(value).replace('T',' ').slice(0,19):'—'} function onSelection(rows){selectedResultIds.value=rows.map(x=>x.result?.resultId).filter(Boolean)} function showDetail(row){detailRow.value=row;detailVisible.value=true} +function handleRowCommand(command,row){if(command==='correction')openCorrection(row);else if(command==='rematch')confirmRematch(row);else if(command==='void')openReason('void',row);else if(command==='export')exportSheets(row)} -async function castScore(row){if(actionLoading.value)return;actionLoading.value=true;try{await workbenchScreenCastPost({eventId:eventId.value,castType:1,venueId:selectedSession.value.venueId,sessionId:selectedSession.value.sessionId,sessionEntryId:row.sessionEntryId,eventResultId:row.result.resultId,resultVersion:row.result.resultVersion});ElMessage.success('成绩已投出');await Promise.all([loadEntries(true),loadCurrentCast()])}finally{actionLoading.value=false}} +async function castScore(row){if(actionLoading.value)return;const presentation=prepareScoreScreen(selectedSession.value.venueId);rowActionId.value=row.sessionEntryId;actionLoading.value=true;try{await workbenchScreenCastPost({eventId:eventId.value,castType:1,venueId:selectedSession.value.venueId,sessionId:selectedSession.value.sessionId,sessionEntryId:row.sessionEntryId,eventResultId:row.result.resultId,resultVersion:row.result.resultVersion});showScoreScreen(presentation,selectedSession.value.venueId);ElMessage.success('成绩已投出');await Promise.all([loadEntries(true),loadCurrentCast()])}catch(error){closeUnusedScreen(presentation);throw error}finally{actionLoading.value=false;rowActionId.value=null}} +async function castDetailScore(){const row=detailRow.value;if(!row)return;await castScore(row);detailVisible.value=false} function openRanking(){rankingKey.value=selectedSession.value?.eventProjectGroupId?`${selectedSession.value.eventProjectId}:${selectedSession.value.eventProjectGroupId}`:'';rankingVisible.value=true} -async function castRanking(){const target=rankingSelection.value;if(!target)return ElMessage.warning('请选择项目和组别');if(actionLoading.value)return;actionLoading.value=true;try{await workbenchScreenCastPost({eventId:eventId.value,castType:2,venueId:selectedSession.value?.venueId,eventProjectId:target.eventProjectId,eventProjectGroupId:target.eventProjectGroupId});rankingVisible.value=false;ElMessage.success('组别排名已投出');await Promise.all([loadEntries(true),loadCurrentCast()])}finally{actionLoading.value=false}} +async function castRanking(){const target=rankingSelection.value;if(!target)return ElMessage.warning('请选择项目和组别');if(actionLoading.value)return;const venueId=target.venueId??selectedSession.value?.venueId;const presentation=prepareScoreScreen(venueId);actionLoading.value=true;try{await workbenchScreenCastPost({eventId:eventId.value,castType:2,venueId,eventProjectId:target.eventProjectId,eventProjectGroupId:target.eventProjectGroupId});showScoreScreen(presentation,venueId);rankingVisible.value=false;ElMessage.success('组别排名已投出');await Promise.all([loadEntries(true),loadCurrentCast()])}catch(error){closeUnusedScreen(presentation);throw error}finally{actionLoading.value=false}} async function withdrawCast(){if(actionLoading.value)return;await ElMessageBox.confirm('撤回后大屏将回到等待状态,是否继续?','撤回投屏',{type:'warning'});actionLoading.value=true;try{await workbenchScreenCastWithdrawPost(currentCast.value.screenCastId);currentCast.value=null;ElMessage.success('已撤回')}finally{actionLoading.value=false}} -async function confirmOne(row){if(actionLoading.value)return;actionLoading.value=true;try{await workbenchResultConfirmPost(row.result.resultId);ElMessage.success('成绩已确认');await loadEntries()}finally{actionLoading.value=false}} +async function confirmOne(row){if(actionLoading.value)return;rowActionId.value=row.sessionEntryId;actionLoading.value=true;try{await workbenchResultConfirmPost(row.result.resultId);ElMessage.success('成绩已确认');await loadEntries()}finally{actionLoading.value=false;rowActionId.value=null}} async function batchConfirm(){if(actionLoading.value)return;await ElMessageBox.confirm(`确认选中的 ${selectedResultIds.value.length} 条成绩?`,'批量确认');actionLoading.value=true;try{await workbenchResultsBatchConfirmPost({sessionId:selectedSession.value.sessionId,resultIds:selectedResultIds.value});ElMessage.success('批量确认完成');await loadEntries()}finally{actionLoading.value=false}} function openReason(action,row){reasonAction.value=action;reasonRow.value=row;reasonText.value='';reasonVisible.value=true} async function submitReason(){const text=reasonText.value.trim();if(text.length<2)return ElMessage.warning('请填写至少 2 个字符的原因');actionLoading.value=true;try{if(reasonAction.value==='rematch')await workbenchEntryRematchPost({originalSessionEntryId:reasonRow.value.sessionEntryId,rematchReason:text});else await workbenchResultVoidPost({sessionEntryId:reasonRow.value.sessionEntryId,voidReason:text});reasonVisible.value=false;ElMessage.success(reasonAction.value==='rematch'?'重赛已安排到场次末尾':'成绩已作废');loadEntries()}finally{actionLoading.value=false}} -function openCorrection(row){correctionRow.value=row;correctionForm.value={scoreSheetId:null,reason:''};correctionVisible.value=true} +function openCorrection(row){correctionRow.value=row;correctionForm.value={judgeRoleType:'',scoreSheetId:null,reason:''};correctionVisible.value=true} +function onCorrectionRoleChange(){correctionForm.value.scoreSheetId=null} +function isCorrectionSheetAvailable(sheet){return sheet.sheetStatus>=10&&sheet.sheetStatus<90&&!sheet.hasPendingCorrection} async function submitCorrection(){const reason=correctionForm.value.reason.trim();if(!correctionForm.value.scoreSheetId)return ElMessage.warning('请选择裁判评分单');if(reason.length<2)return ElMessage.warning('请填写至少 2 个字符的修正原因');actionLoading.value=true;try{await judgeScoreCorrectionInitiatePost({scoreSheetId:correctionForm.value.scoreSheetId,reason});correctionVisible.value=false;ElMessage.success('修正任务已发送给裁判');loadEntries()}finally{actionLoading.value=false}} +function confirmRematch(row){rematchRow.value=row;rematchVisible.value=true} +async function submitRematch(){if(!rematchRow.value||actionLoading.value)return;actionLoading.value=true;try{await workbenchEntryRematchPost({originalSessionEntryId:rematchRow.value.sessionEntryId,rematchReason:'后台确认安排重赛'});rematchVisible.value=false;ElMessage.success('重赛已安排到当前组别末尾');await loadEntries()}finally{actionLoading.value=false}} async function approveCorrection(row,isApproved){let remark='';if(!isApproved)remark=await ElMessageBox.prompt('请输入驳回原因','驳回修正申请',{inputValidator:v=>String(v||'').trim().length>=2||'至少输入2个字符'}).then(x=>x.value);else await ElMessageBox.confirm('批准后将向裁判下发修正任务,是否继续?','批准申请');await workbenchCorrectionApprovePost({correctionId:row.correctionId,isApproved,approveRemark:remark});ElMessage.success('申请已处理');loadCorrections()} async function showCorrectionDetail(row){const res=await workbenchCorrectionDetailGet(row.correctionId);const x=res?.data;if(!x)return;ElMessageBox.alert(`选手:${x.entry?.participantName||'-'}\n裁判:${x.originalScore?.judgeName||'-'}(${x.originalScore?.judgeRoleName||'-'})\n原分:${score(x.originalScore?.totalScore)}\n原因:${x.applyReason}`,'修正详情',{confirmButtonText:'关闭'})} async function download(blob,name){const url=URL.createObjectURL(blob);const a=document.createElement('a');a.href=url;a.download=name;document.body.appendChild(a);a.click();a.remove();URL.revokeObjectURL(url)} async function exportResults(){const blob=await workbenchResultsExportGet({eventId:eventId.value,sessionId:selectedSession.value?.sessionId,keyword:entryKeyword.value||undefined,resultStatus:resultStatus.value??undefined});download(blob,`成绩册_${eventId.value}.xlsx`)} async function exportSheets(){const blob=await workbenchScoreSheetsExportGet({eventId:eventId.value,sessionId:selectedSession.value.sessionId});download(blob,`评分单_${selectedSession.value.sessionNo}.xlsx`)} -function openScoreScreen(){window.open(router.resolve({path:'/scoring/screen',query:{eventId:eventId.value,venueId:selectedSession.value?.venueId,eventName:eventName.value,mode:'freestyle'}}).href,'_blank')} +function scoreScreenHref(venueId){return router.resolve({path:'/scoring/screen',query:{eventId:eventId.value,venueId,eventName:eventName.value,mode:'freestyle',autofullscreen:'1'}}).href} +function prepareScoreScreen(venueId){ + const existing=scoreScreenWindow&&!scoreScreenWindow.closed?scoreScreenWindow:null; + const popup=window.open('',scoreScreenWindowName,'popup=yes,width=1280,height=720,left=0,top=0'); + if(!popup){ElMessage.warning('浏览器已拦截投屏窗口,请允许本站弹出窗口');return null} + scoreScreenWindow=popup; + const presentation={popup,created:!existing}; + if(presentation.created){try{popup.document.title='正在准备成绩大屏';popup.document.body.innerHTML='
正在准备投屏…
'}catch{}} + placeOnPresentationScreen(popup); + return presentation; +} +async function placeOnPresentationScreen(popup){ + try{ + let target=window.screen; + if('getScreenDetails' in window){ + const details=await window.getScreenDetails(); + target=details.screens.find(item=>item.left!==details.currentScreen.left||item.top!==details.currentScreen.top)||details.currentScreen||target; + } + popup.moveTo(target.availLeft??target.left??0,target.availTop??target.top??0); + popup.resizeTo(target.availWidth??target.width,target.availHeight??target.height); + popup.focus(); + }catch{try{popup.focus()}catch{}} +} +function showScoreScreen(presentation,venueId){ + const popup=presentation?.popup&&!presentation.popup.closed?presentation.popup:window.open(scoreScreenHref(venueId),scoreScreenWindowName,'popup=yes,width=1280,height=720'); + if(!popup){ElMessage.warning('成绩已投出,但浏览器拦截了大屏窗口');return} + scoreScreenWindow=popup;popup.location.replace(scoreScreenHref(venueId));placeOnPresentationScreen(popup); +} +function closeUnusedScreen(presentation){if(presentation?.created&&presentation.popup&&!presentation.popup.closed)presentation.popup.close()} +function openScoreScreen(){const presentation=prepareScoreScreen(selectedSession.value?.venueId);if(presentation)showScoreScreen(presentation,selectedSession.value?.venueId)} function openCheckinScreen(){window.open(router.resolve({path:'/scoring/checkin-screen',query:{eventId:eventId.value}}).href,'_blank')} function goLauncher(){router.push({path:'/scoring/launcher'})} function toggleCorrections(){activeTab.value=activeTab.value==='corrections'?'results':'corrections';if(activeTab.value==='corrections')loadCorrections()} @@ -177,3 +227,195 @@ onBeforeUnmount(()=>window.clearInterval(pollTimer)); .workbench-page{height:calc(100vh - 115px);display:flex;overflow:hidden;color:#172b4d;background:#f2f6fb;font-family:"Microsoft YaHei",sans-serif}.workbench-main{min-width:0;flex:1;display:flex;flex-direction:column}.topbar{height:80px;flex:none;display:flex;align-items:center;justify-content:space-between;padding:0 28px;border-bottom:1px solid #e2eaf3;background:#fff}.topbar h1{margin:0;font-size:22px}.topbar p{margin:5px 0 0;color:#91a0b4;font-size:12px}.top-actions{display:flex;align-items:center;gap:10px}.live-dot{color:#22b573;font-size:12px}.live-dot.offline{color:#e74c3c}.workspace{min-height:0;flex:1;display:flex;padding:16px;gap:14px}.session-panel{width:278px;flex:none;display:flex;flex-direction:column;padding:16px;border:1px solid #e1eaf3;border-radius:12px;background:#fff}.session-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px}.session-list{min-height:0;overflow:auto;margin-top:12px}.session-list>button{position:relative;display:grid;grid-template-columns:1fr auto;gap:8px;width:100%;margin-bottom:9px;padding:13px;border:1px solid #e4ecf4;border-radius:10px;color:#29435f;background:#fff;text-align:left;cursor:pointer}.session-list>button:hover,.session-list>button.active{border-color:#1999f5;background:#f0f9ff;box-shadow:0 6px 16px rgba(28,136,221,.1)}.session-list strong,.session-list span{display:block}.session-list strong{font-size:13px}.session-list div span{margin-top:7px;color:#8fa0b2;font-size:11px}.session-list em{padding:3px 6px;height:max-content;border-radius:10px;color:#178bdf;background:#eaf6ff;font-size:10px;font-style:normal}.session-list i{height:4px;overflow:hidden;border-radius:4px;background:#e8eff5}.session-list i span{height:100%;border-radius:4px;background:linear-gradient(90deg,#0584f4,#20cfd6)}.session-list small{color:#7f91a4;text-align:right}.result-panel{min-width:0;flex:1;padding:15px 15px 0;border:1px solid #e1eaf3;border-radius:12px;background:#fff;overflow:hidden}.filterbar{display:flex;align-items:center;gap:9px;margin-bottom:13px}.filterbar>.el-input{width:220px}.filterbar>.el-select{width:130px}.filter-spacer{flex:1}.cast-banner{display:flex;align-items:center;gap:12px;margin-bottom:12px;padding:9px 12px;border:1px solid #bee8dc;border-radius:8px;background:#effbf7}.cast-banner>span{padding:4px 7px;border-radius:5px;color:#fff;background:#13ad72;font-size:10px;font-weight:700}.cast-banner div{flex:1}.cast-banner b,.cast-banner small{display:block}.cast-banner small{margin-top:3px;color:#799286;font-size:10px}.subtext{display:block;margin-top:5px;color:#93a0ae}.order{display:block;color:#198fe8}.rematch-tag{display:block;margin-top:3px;color:#e36b25;font-size:9px;font-style:normal}.submit-progress{padding:4px 8px;border-radius:13px;color:#d88417;background:#fff4dc}.submit-progress.done{color:#11985c;background:#e8f9f0}.total{color:#096fc8;font-size:18px}.total.dq{color:#e54c4c}.muted{color:#9daab6}.correction-page{margin:16px;padding:16px;border:1px solid #e1eaf3;border-radius:12px;background:#fff;overflow:hidden}.correction-filter>.el-input{width:280px}.detail-summary{display:grid;grid-template-columns:2fr 1fr 1fr;gap:12px;margin-bottom:18px}.detail-summary>div{padding:14px;border-radius:9px;background:#f2f7fc}.detail-summary small,.detail-summary b{display:block}.detail-summary small{color:#8ea0b1}.detail-summary b{margin-top:6px;font-size:18px}.dialog-desc{margin-top:16px}.reason-form{margin-top:16px} @media(max-width:1000px){.workbench-aside{width:190px}.session-panel{width:235px}.top-actions .live-dot{display:none}} + + + +