Files
AIclinicalresearch/docs/03-业务模块/RVW-稿件审查系统/00-系统设计/V3.0/AI审稿V1.html
HaHafeng 16179e16ca feat(rvw): deliver tenant portal v4 flow and config foundation
Implement RVW V4.0 tenant-aware backend/frontend flow with tenant routing, config APIs, and full portal UX updates. Sync system/RVW/deployment docs to capture verified upload-review-report workflow and next-step admin configuration work.

Made-with: Cursor
2026-03-14 22:29:40 +08:00

442 lines
30 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JTIM - 智能审稿工作台</title>
<!-- 引入 Tailwind CSS -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- 引入 Vue 3 -->
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<!-- 引入 FontAwesome 图标 -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
<script>
tailwind.config = {
theme: {
extend: {
colors: {
brand: {
50: '#f0f9ff',
100: '#e0f2fe',
500: '#0ea5e9',
600: '#0284c7',
700: '#0369a1',
900: '#0c4a6e',
}
}
}
}
}
</script>
<style>
/* 隐藏滚动条但保留滚动功能 */
.no-scrollbar::-webkit-scrollbar {
display: none;
}
.no-scrollbar {
-ms-overflow-style: none;
scrollbar-width: none;
}
.pdf-mockup {
background-image: repeating-linear-gradient(0deg, transparent, transparent 27px, #e5e7eb 27px, #e5e7eb 28px);
background-size: 100% 28px;
}
</style>
</head>
<body class="bg-gray-50 text-gray-800 font-sans antialiased">
<div id="app" class="h-screen w-full flex flex-col overflow-hidden">
<!-- ==================== 视图 1: 独立登录页 ==================== -->
<div v-if="currentView === 'login'" class="flex h-screen w-full">
<!-- 左侧品牌展示 -->
<div class="w-1/2 bg-brand-900 flex flex-col justify-center items-center text-white p-12 relative overflow-hidden">
<div class="absolute inset-0 opacity-10 bg-[url('https://www.transparenttextures.com/patterns/cubes.png')]"></div>
<div class="z-10 text-center">
<div class="w-24 h-24 bg-white rounded-full flex items-center justify-center mx-auto mb-6 shadow-xl">
<i class="fas fa-book-medical text-brand-700 text-4xl"></i>
</div>
<h1 class="text-4xl font-bold mb-4">Journal of Translational Internal Medicine</h1>
<p class="text-xl text-brand-100 mb-8">AI 智能审稿系统 (Editor Portal)</p>
<div class="inline-block px-6 py-2 border border-brand-500 rounded-full text-sm">
专属租户入口
</div>
</div>
</div>
<!-- 右侧登录表单 -->
<div class="w-1/2 flex items-center justify-center bg-white">
<div class="w-96">
<h2 class="text-3xl font-bold mb-2 text-gray-800">编辑登录</h2>
<p class="text-gray-500 mb-8">欢迎回来,请登录您的责编工作台。</p>
<form @submit.prevent="login" class="space-y-6">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">工作邮箱</label>
<input type="email" value="editor@jtim.com" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-brand-500 focus:border-brand-500 outline-none transition" required>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">密码</label>
<input type="password" value="password123" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-brand-500 focus:border-brand-500 outline-none transition" required>
</div>
<div class="flex items-center justify-between">
<label class="flex items-center">
<input type="checkbox" class="rounded text-brand-600 focus:ring-brand-500">
<span class="ml-2 text-sm text-gray-600">记住我</span>
</label>
<a href="#" class="text-sm text-brand-600 hover:text-brand-500">忘记密码?</a>
</div>
<button type="submit" class="w-full bg-brand-600 text-white font-medium py-2.5 rounded-lg hover:bg-brand-700 transition shadow-lg shadow-brand-500/30">
进入工作台 <i class="fas fa-arrow-right ml-2"></i>
</button>
</form>
</div>
</div>
</div>
<!-- ==================== 登录后的公共 Header ==================== -->
<header v-if="currentView !== 'login'" class="h-16 bg-white border-b border-gray-200 flex items-center justify-between px-6 shrink-0 z-10">
<div class="flex items-center space-x-4">
<div class="w-8 h-8 bg-brand-700 rounded text-white flex items-center justify-center font-bold">JT</div>
<h1 class="text-lg font-bold text-gray-800">JTIM 审稿工作台</h1>
</div>
<div class="flex items-center space-x-6">
<button class="text-gray-500 hover:text-gray-700"><i class="fas fa-bell"></i></button>
<div class="flex items-center space-x-2 border-l pl-6 border-gray-200 cursor-pointer" @click="currentView = 'login'">
<img src="https://i.pravatar.cc/150?u=a042581f4e29026704d" alt="User" class="w-8 h-8 rounded-full">
<span class="text-sm font-medium text-gray-700">责编 李明</span>
<i class="fas fa-chevron-down text-xs text-gray-400"></i>
</div>
</div>
</header>
<!-- ==================== 视图 2: 稿件管理池 (Dashboard) ==================== -->
<div v-if="currentView === 'dashboard'" class="flex-1 overflow-auto p-6 bg-gray-50">
<!-- 统计卡片 -->
<div class="grid grid-cols-4 gap-6 mb-6">
<div class="bg-white rounded-xl p-5 border border-gray-200 shadow-sm flex items-center">
<div class="w-12 h-12 bg-blue-50 text-blue-600 rounded-lg flex items-center justify-center text-xl mr-4"><i class="fas fa-inbox"></i></div>
<div><p class="text-sm text-gray-500">待预审稿件</p><p class="text-2xl font-bold">12</p></div>
</div>
<div class="bg-white rounded-xl p-5 border border-gray-200 shadow-sm flex items-center">
<div class="w-12 h-12 bg-amber-50 text-amber-600 rounded-lg flex items-center justify-center text-xl mr-4"><i class="fas fa-robot"></i></div>
<div><p class="text-sm text-gray-500">AI 审查中</p><p class="text-2xl font-bold">3</p></div>
</div>
<div class="bg-white rounded-xl p-5 border border-gray-200 shadow-sm flex items-center">
<div class="w-12 h-12 bg-green-50 text-green-600 rounded-lg flex items-center justify-center text-xl mr-4"><i class="fas fa-clipboard-check"></i></div>
<div><p class="text-sm text-gray-500">需人工复核</p><p class="text-2xl font-bold">8</p></div>
</div>
<div class="bg-white rounded-xl p-5 border border-gray-200 shadow-sm flex items-center">
<div class="w-12 h-12 bg-purple-50 text-purple-600 rounded-lg flex items-center justify-center text-xl mr-4"><i class="fas fa-paper-plane"></i></div>
<div><p class="text-sm text-gray-500">今日已退修</p><p class="text-2xl font-bold">5</p></div>
</div>
</div>
<!-- 宽表 -->
<div class="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden">
<div class="px-6 py-4 border-b border-gray-200 flex justify-between items-center bg-gray-50/50">
<h2 class="text-lg font-bold text-gray-800">最新收稿池 (Manuscripts Pool)</h2>
<div class="flex space-x-2">
<input type="text" placeholder="搜索稿件编号/作者..." class="px-3 py-1.5 border border-gray-300 rounded-lg text-sm focus:ring-brand-500 focus:border-brand-500 outline-none">
<button class="bg-white border border-gray-300 text-gray-700 px-3 py-1.5 rounded-lg text-sm hover:bg-gray-50"><i class="fas fa-filter mr-1"></i> 筛选</button>
</div>
</div>
<div class="overflow-x-auto">
<table class="w-full text-left text-sm">
<thead class="bg-gray-50 text-gray-500 border-b border-gray-200">
<tr>
<th class="px-6 py-3 font-medium">稿件编号</th>
<th class="px-6 py-3 font-medium">标题</th>
<th class="px-6 py-3 font-medium">通讯作者</th>
<th class="px-6 py-3 font-medium">综合评分</th>
<th class="px-6 py-3 font-medium text-center">规范性</th>
<th class="px-6 py-3 font-medium text-center">方法学</th>
<th class="px-6 py-3 font-medium text-center">数据验证</th>
<th class="px-6 py-3 font-medium text-center">临床评估</th>
<th class="px-6 py-3 font-medium">状态</th>
<th class="px-6 py-3 font-medium text-right">操作</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-100">
<tr v-for="doc in manuscripts" :key="doc.id" class="hover:bg-blue-50/30 transition">
<td class="px-6 py-4 font-mono text-brand-600 font-medium">{{ doc.id }}</td>
<td class="px-6 py-4 text-gray-800 max-w-xs truncate" :title="doc.title">{{ doc.title }}</td>
<td class="px-6 py-4 text-gray-600">{{ doc.author }}</td>
<td class="px-6 py-4">
<div class="flex items-center">
<div class="w-10 h-10 rounded-full border-4 flex items-center justify-center font-bold text-xs"
:class="doc.score >= 80 ? 'border-green-100 text-green-600 bg-green-50' : (doc.score >= 60 ? 'border-amber-100 text-amber-600 bg-amber-50' : 'border-red-100 text-red-600 bg-red-50')">
{{ doc.score }}
</div>
</div>
</td>
<!-- 4维状态 -->
<td class="px-6 py-4 text-center"><StatusIcon :status="doc.dims.editorial" /></td>
<td class="px-6 py-4 text-center"><StatusIcon :status="doc.dims.method" /></td>
<td class="px-6 py-4 text-center"><StatusIcon :status="doc.dims.data" /></td>
<td class="px-6 py-4 text-center"><StatusIcon :status="doc.dims.clinical" /></td>
<td class="px-6 py-4">
<span class="px-2.5 py-1 text-xs rounded-full font-medium"
:class="doc.status === 'AI审查完毕' ? 'bg-blue-100 text-blue-700' : 'bg-gray-100 text-gray-600'">
{{ doc.status }}
</span>
</td>
<td class="px-6 py-4 text-right">
<button v-if="doc.status === 'AI审查完毕'" @click="openDetail(doc)" class="text-brand-600 hover:text-brand-800 font-medium bg-brand-50 px-3 py-1 rounded-md transition">
人工复核
</button>
<button v-else class="text-gray-400 font-medium px-3 py-1 cursor-not-allowed">
审查中...
</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- ==================== 视图 3: 沉浸式 4-Tab 审稿详情页 ==================== -->
<div v-if="currentView === 'detail'" class="flex-1 flex flex-col overflow-hidden bg-gray-100">
<!-- 详情页工具栏 -->
<div class="h-14 bg-white border-b border-gray-200 flex items-center justify-between px-4 shrink-0 shadow-sm z-10">
<div class="flex items-center">
<button @click="currentView = 'dashboard'" class="text-gray-500 hover:text-gray-800 mr-4 w-8 h-8 rounded-full hover:bg-gray-100 flex items-center justify-center transition">
<i class="fas fa-arrow-left"></i>
</button>
<div>
<span class="text-xs text-gray-400 font-mono">{{ activeDoc.id }}</span>
<h2 class="text-sm font-bold text-gray-800 truncate max-w-lg">{{ activeDoc.title }}</h2>
</div>
</div>
<div class="flex items-center space-x-3">
<button class="px-3 py-1.5 border border-gray-300 text-gray-700 text-sm font-medium rounded hover:bg-gray-50 transition">
<i class="fas fa-file-word mr-1 text-blue-600"></i> 导出审稿报告
</button>
<button class="px-4 py-1.5 bg-red-600 text-white text-sm font-medium rounded hover:bg-red-700 transition shadow-sm">
<i class="fas fa-reply mr-1"></i> 发送退修意见函
</button>
</div>
</div>
<!-- 分屏内容区 -->
<div class="flex-1 flex overflow-hidden">
<!-- 左侧: 原文预览 (模拟) -->
<div class="w-3/5 border-r border-gray-300 bg-gray-100 p-4 overflow-auto relative">
<!-- 浮动工具栏 -->
<div class="absolute top-6 left-1/2 transform -translate-x-1/2 bg-gray-800/80 text-white px-4 py-2 rounded-lg flex space-x-4 text-sm backdrop-blur-sm shadow-lg z-10">
<button class="hover:text-brand-300"><i class="fas fa-search-plus"></i></button>
<button class="hover:text-brand-300"><i class="fas fa-search-minus"></i></button>
<span>第 1 / 15 页</span>
</div>
<!-- 模拟 PDF 纸张 -->
<div class="bg-white shadow-lg mx-auto w-full max-w-3xl min-h-[1000px] p-12 pdf-mockup relative">
<h1 class="text-2xl font-bold text-center mb-6">{{ activeDoc.title }}</h1>
<p class="text-center italic mb-8">Author: {{ activeDoc.author }}, et al.</p>
<h3 class="font-bold text-lg mt-8 mb-2">Abstract</h3>
<p class="text-sm leading-relaxed text-gray-700 mb-6 relative group">
<span class="bg-red-200/50 border-b-2 border-red-400 cursor-pointer">Background: Translational medicine aims to... (Here is a very long abstract that exceeds the 200 words limit specified by JTIM guidelines. It goes on to describe the historical context, which is unnecessary for a structured abstract. The methodology is briefly mentioned but lacks statistical details.)</span>
<span class="absolute left-full ml-2 top-0 w-48 bg-red-50 border border-red-200 text-red-700 p-2 text-xs rounded shadow-lg hidden group-hover:block z-20">
<strong>AI 批注:</strong> 摘要未采用 Structured 格式,且字数可能超标。
</span>
</p>
<h3 class="font-bold text-lg mt-8 mb-2">Materials and Methods</h3>
<p class="text-sm leading-relaxed text-gray-700 mb-6 relative group">
Data were analyzed using SPSS. <span class="bg-amber-200/50 border-b-2 border-amber-400 cursor-pointer">A p-value < 0.05 was considered significant.</span>
<span class="absolute left-full ml-2 top-0 w-48 bg-amber-50 border border-amber-200 text-amber-700 p-2 text-xs rounded shadow-lg hidden group-hover:block z-20">
<strong>AI 批注:</strong> JTIM 稿约要求 P 值报告具体数值,不可简单写 p < 0.05
</span>
</p>
<p class="text-sm text-gray-400 mt-20 text-center">... 模拟文档内容结束 ...</p>
</div>
</div>
<!-- 右侧: 4-Tab 审查工作台 -->
<div class="w-2/5 bg-white flex flex-col overflow-hidden shadow-xl z-20">
<!-- Tabs -->
<div class="flex border-b border-gray-200 bg-gray-50/80 shrink-0 px-2 pt-2">
<button v-for="tab in tabs" :key="tab.id" @click="activeTab = tab.id"
class="flex-1 py-2.5 text-sm font-medium border-b-2 transition-colors duration-200 rounded-t-lg mx-1 flex items-center justify-center space-x-1"
:class="activeTab === tab.id ? 'border-brand-600 text-brand-700 bg-white shadow-sm' : 'border-transparent text-gray-500 hover:text-gray-700 hover:bg-gray-100'">
<i :class="tab.icon"></i>
<span>{{ tab.name }}</span>
<!-- 红点提示 -->
<span v-if="getIssueCount(tab.id) > 0" class="ml-1 w-4 h-4 rounded-full bg-red-100 text-red-600 text-[10px] flex items-center justify-center font-bold">
{{ getIssueCount(tab.id) }}
</span>
</button>
</div>
<!-- Tab 内容区 -->
<div class="flex-1 overflow-y-auto bg-gray-50 p-4">
<!-- 统计摘要栏 -->
<div class="bg-white rounded-lg p-3 mb-4 shadow-sm border border-gray-100 flex justify-between items-center">
<div>
<h3 class="text-sm font-bold text-gray-800">{{ currentTabName }}评估结果</h3>
<p class="text-xs text-gray-500 mt-0.5">AI 已完成初步筛查,请责编确认。</p>
</div>
<div class="text-right">
<span class="text-xs bg-gray-100 text-gray-600 px-2 py-1 rounded">共发现 {{ currentIssues.length }} 个问题</span>
</div>
</div>
<!-- 问题列表 -->
<div class="space-y-3">
<div v-for="issue in currentIssues" :key="issue.id"
class="bg-white rounded-lg border shadow-sm p-4 transition-all duration-200 relative overflow-hidden"
:class="issue.ignored ? 'border-gray-200 opacity-60' : (issue.severity === 'fatal' ? 'border-red-200' : 'border-amber-200')">
<!-- 侧边装饰条 -->
<div class="absolute left-0 top-0 bottom-0 w-1" :class="getSeverityColor(issue.severity, issue.ignored)"></div>
<div class="flex justify-between items-start pl-2">
<div class="flex-1 pr-4">
<div class="flex items-center space-x-2 mb-1.5">
<span class="text-[10px] font-bold px-1.5 py-0.5 rounded uppercase" :class="getSeverityBadge(issue.severity)">
{{ issue.severity === 'fatal' ? '致命错误' : (issue.severity === 'major' ? '主要缺陷' : '一般建议') }}
</span>
<span class="text-xs text-gray-500 font-mono">{{ issue.code }}</span>
</div>
<h4 class="text-sm font-bold text-gray-800 mb-1" :class="{'line-through text-gray-500': issue.ignored}">{{ issue.title }}</h4>
<p class="text-xs text-gray-600 leading-relaxed mb-3" :class="{'line-through': issue.ignored}">{{ issue.desc }}</p>
<div v-if="issue.suggestion" class="bg-blue-50/50 rounded p-2 text-xs text-blue-800 border border-blue-100">
<i class="fas fa-lightbulb text-amber-500 mr-1"></i> <strong>建议修改:</strong>{{ issue.suggestion }}
</div>
</div>
</div>
<!-- Human-in-the-loop 操作区 -->
<div class="mt-3 pt-3 border-t border-gray-100 flex items-center justify-between pl-2">
<span class="text-xs text-gray-400">人工复核确认:</span>
<div class="flex bg-gray-100 p-0.5 rounded-lg">
<button @click="issue.ignored = false"
class="px-3 py-1 text-xs font-medium rounded-md transition-all"
:class="!issue.ignored ? 'bg-white shadow-sm text-brand-700' : 'text-gray-500 hover:text-gray-700'">
<i class="fas fa-check-circle mr-1" :class="!issue.ignored ? 'text-green-500' : ''"></i> 采纳此问题
</button>
<button @click="issue.ignored = true"
class="px-3 py-1 text-xs font-medium rounded-md transition-all"
:class="issue.ignored ? 'bg-white shadow-sm text-gray-800' : 'text-gray-500 hover:text-gray-700'">
<i class="fas fa-times-circle mr-1 text-gray-400"></i> 误报/忽略
</button>
</div>
</div>
</div>
<!-- 状态为空时 -->
<div v-if="currentIssues.length === 0" class="text-center py-12 bg-white rounded-lg border border-gray-200 border-dashed">
<div class="w-16 h-16 bg-green-50 text-green-500 rounded-full flex items-center justify-center mx-auto mb-3 text-2xl">
<i class="fas fa-check"></i>
</div>
<h3 class="text-sm font-bold text-gray-700">未发现明显缺陷</h3>
<p class="text-xs text-gray-500 mt-1">该维度通过了 AI 的自动化审查。</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 独立组件模板 -->
<script>
const { createApp } = Vue;
// 状态图标组件
const StatusIcon = {
props: ['status'],
template: `
<div class="flex justify-center">
<i v-if="status === 'pass'" class="fas fa-check-circle text-green-500 text-lg"></i>
<i v-else-if="status === 'warn'" class="fas fa-exclamation-triangle text-amber-500 text-lg"></i>
<i v-else-if="status === 'error'" class="fas fa-times-circle text-red-500 text-lg"></i>
<i v-else class="fas fa-spinner fa-spin text-gray-300 text-lg"></i>
</div>
`
};
createApp({
components: { StatusIcon },
data() {
return {
currentView: 'login', // login, dashboard, detail
activeTab: 'editorial',
activeDoc: null,
tabs: [
{ id: 'editorial', name: '稿约规范', icon: 'fas fa-clipboard-list' },
{ id: 'method', name: '方法学', icon: 'fas fa-microscope' },
{ id: 'data', name: '数据验证', icon: 'fas fa-database' },
{ id: 'clinical', name: '临床评估', icon: 'fas fa-stethoscope' }
],
// 模拟稿件列表数据
manuscripts: [
{ id: 'JTIM-2026-0881', title: 'Efficacy of novel inhibitor in advanced NSCLC: A retrospective cohort study', author: 'Dr. Zhang Wei', date: '2026-03-13', score: 65, status: 'AI审查完毕', dims: { editorial: 'error', method: 'warn', data: 'pass', clinical: 'pass' } },
{ id: 'JTIM-2026-0882', title: 'Translational approaches for targeting tumor microenvironment', author: 'Dr. Sarah Connor', date: '2026-03-12', score: 92, status: 'AI审查完毕', dims: { editorial: 'pass', method: 'pass', data: 'pass', clinical: 'pass' } },
{ id: 'JTIM-2026-0883', title: 'Machine learning prediction models in diabetic nephropathy', author: 'Dr. Li Hua', date: '2026-03-12', score: 78, status: 'AI审查完毕', dims: { editorial: 'pass', method: 'error', data: 'warn', clinical: 'warn' } },
{ id: 'JTIM-2026-0884', title: 'Long-term cardiovascular outcomes after acute COVID-19', author: 'Dr. Michael Chen', date: '2026-03-11', score: 0, status: '待预审', dims: { editorial: '', method: '', data: '', clinical: '' } },
],
// 模拟 AI 找出的缺陷数据
issuesData: {
'JTIM-2026-0881': {
editorial: [
{ id: 101, code: 'ED-001', severity: 'fatal', title: '知情同意声明缺失', desc: '作为回顾性队列研究,正文及 Title Page 均未找到 Informed Consent 相关声明,违反 ICMJE 基本伦理准则。', suggestion: '请作者补充声明已获取知情同意,或说明伦理委员会已豁免。', ignored: false },
{ id: 102, code: 'ED-045', severity: 'major', title: '摘要结构不合规', desc: 'JTIM 规定 Original Research 必须使用 Structured Abstract (包含 Objectives, Methods, Results, Conclusions),当前摘要为纯文本段落。', suggestion: '请按指南要求拆分摘要段落。', ignored: false },
{ id: 103, code: 'ED-012', severity: 'minor', title: '统计结果 P 值表述不规范', desc: '发现多处 "p < 0.05" 表述。稿约规定应报告 P 值的确切数值 (如 P = 0.048)。', suggestion: '修改 Methods 和 Results 中的 P 值表述。', ignored: false }
],
method: [
{ id: 201, code: 'ME-033', severity: 'major', title: '回归模型未说明共线性检验', desc: '作者构建了多因素 Cox 比例风险模型但未提及是否对纳入的自变量进行了多重共线性VIF检验。', suggestion: '补充共线性诊断的统计学方法描述。', ignored: false }
],
data: [], // 模拟通过
clinical: [
{ id: 401, code: 'CL-005', severity: 'minor', title: '创新性一般', desc: '该靶向药在 NSCLC 中的回顾性研究已有较多报道,增量信息(创新性)评分较低。', suggestion: '', ignored: true } // 默认演示一个被忽略的项
]
}
}
}
},
computed: {
currentTabName() {
return this.tabs.find(t => t.id === this.activeTab)?.name || '';
},
currentIssues() {
if (!this.activeDoc || !this.issuesData[this.activeDoc.id]) return [];
return this.issuesData[this.activeDoc.id][this.activeTab] || [];
}
},
methods: {
login() {
this.currentView = 'dashboard';
},
openDetail(doc) {
this.activeDoc = doc;
this.activeTab = 'editorial';
this.currentView = 'detail';
},
getIssueCount(tabId) {
if (!this.activeDoc || !this.issuesData[this.activeDoc.id]) return 0;
const issues = this.issuesData[this.activeDoc.id][tabId] || [];
// 只计算未被忽略的
return issues.filter(i => !i.ignored).length;
},
getSeverityBadge(severity) {
if (severity === 'fatal') return 'bg-red-100 text-red-700 border border-red-200';
if (severity === 'major') return 'bg-amber-100 text-amber-700 border border-amber-200';
return 'bg-blue-100 text-blue-700 border border-blue-200';
},
getSeverityColor(severity, ignored) {
if (ignored) return 'bg-gray-300';
if (severity === 'fatal') return 'bg-red-500';
if (severity === 'major') return 'bg-amber-500';
return 'bg-blue-500';
}
}
}).mount('#app')
</script>
</body>
</html>