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
442 lines
30 KiB
HTML
442 lines
30 KiB
HTML
<!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> |