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 @@
-
-
+
+
+
{{ offline ? '连接异常' : '实时数据' }}
-
+
+
{{ title }}
◎项目-组别:{{ projectGroup }}⌖场次-场地:{{ sessionVenue }}
@@ -14,18 +16,28 @@
-
{{ index+1 }}
{{ index+1 }}
+
{{ rankNumber(row,index) }}
{{ rankNumber(row,index) }}
◎{{ row.teamName || row.participantName || '—' }}
{{ value(row.totalScore ?? row.score) }}分
-
{{ item.icon }}{{ value(payload[item.field]) }}{{ item.label }}
+
+
+
+
+
+
+
+
{{ value(payload[item.field]) }}{{ item.label }}
+
-
+
+
+
+
+
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) }}
查看大屏撤回投屏
-
+
{{ row.playOrder }}重赛
{{ row.teamName || row.participantName }}{{ row.entryNo }} · {{ row.groupName }} · {{row.unitName}}
@@ -52,11 +52,11 @@
{{ score(row.result?.deductionScore) }}
{{ row.result?.isDisqualified ? 'DQ' : score(row.result?.totalScore ?? row.result?.scoreText) }}
{{ row.result.resultStatusName }}计算中
-
- 投出成绩详情
- 详情确认成绩修正重赛更多作废成绩导出评分单
+
+ 展示成绩评分详情
+ 确认成绩展示成绩等待成绩详情 handleRowCommand(command, row)">更多 ⌄发起成绩修正安排重赛导出本场评分单
-
+
@@ -67,14 +67,14 @@
- 选手/队伍{{detailRow.teamName || detailRow.participantName}}
总分{{score(detailRow.result?.totalScore)}}
成绩版本V{{detailRow.result?.resultVersion || 0}}
{{score(row.itemValues[col.key])}}
+ 选手/队伍{{detailRow.teamName || detailRow.participantName}}
总分{{score(detailRow.result?.totalScore)}}
成绩版本V{{detailRow.result?.resultVersion || 0}}
{{score(row.itemValues[col.key])}}关闭展示该成绩
取消确定投屏
取消确认
取消发送修正任务
- 确认重赛,本组选手将顺延至当前组别最后出场进行重赛,你还要继续吗?
取消继续
+ 确认后,该选手将顺延至当前组别末尾重新出场。请确认现场安排已就绪。
取消确认安排
@@ -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}}
+
+
+
+