You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

712 lines
40 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>“光联万物 创芯未来”首届沪苏协同新兴产业科创大赛报名系统</title>
<link rel="stylesheet" href="../assets/bootstrap.min.css" />
<link rel="stylesheet" href="../assets/prototype.css?v=20260808-2" />
<script src="../assets/prototype-scale.js?v=20260819-hero"></script>
</head>
<body class="prototype-page admin-desktop-page">
<div class="container-fluid p-3 p-md-4">
<div class="d-flex justify-content-between align-items-center flex-wrap gap-2 mb-3">
<h5 id="adminDetailTitle" class="mb-0 section-title">项目详情</h5>
<div class="d-flex align-items-center gap-2 flex-wrap">
<span id="detailStatusBadge" class="status-pill status-pending">项目编号:P2026-0001 · 待评审</span>
<a id="detailBackLink" class="btn btn-sm btn-outline-secondary event-back-btn" href="./admin-list.html">返回列表</a>
</div>
</div>
<div class="card mb-3">
<div class="card-body">
<div class="row g-3">
<div class="col-12 col-md-3">
<label class="form-label">项目名称</label>
<input class="form-control" id="detailProjectName" disabled />
</div>
<div class="col-12 col-md-3">
<label class="form-label">申请人姓名</label>
<input class="form-control" id="detailPlayerName" disabled />
</div>
<div class="col-12 col-md-3">
<label class="form-label">注册邮箱</label>
<input class="form-control" id="detailEmail" disabled />
</div>
<div class="col-12 col-md-3">
<label class="form-label">申请人电话</label>
<input class="form-control" id="detailMobile" disabled />
</div>
<div class="col-12 col-md-3">
<label class="form-label">毕业院校</label>
<input class="form-control" id="detailSchool" disabled />
</div>
<div class="col-12 col-md-3">
<label class="form-label">最高学历</label>
<input class="form-control" id="detailDegree" disabled />
</div>
<div class="col-12 col-md-3">
<label class="form-label">细分赛道</label>
<input class="form-control" id="detailTrack" disabled />
</div>
<div class="col-12 col-md-3">
<label class="form-label">企业名称</label>
<input class="form-control company-name-input" id="detailCompanyName" placeholder="如已注册企业,请填写" disabled />
</div>
<div class="col-12 col-md-3">
<label class="form-label">项目所在地</label>
<input class="form-control" id="detailLocationCountry" disabled />
</div>
<div class="col-12 col-md-3">
<label class="form-label">省份</label>
<input class="form-control" id="detailLocationProvince" disabled />
</div>
<div class="col-12 col-md-3">
<label class="form-label">城市</label>
<input class="form-control" id="detailLocationCity" disabled />
</div>
<div class="col-12 col-md-3">
<label class="form-label">参赛地点</label>
<input class="form-control" id="detailEventLocation" disabled />
</div>
<div class="col-12 col-md-3">
<label class="form-label">团队成员</label>
<input class="form-control" id="detailTeamMembers" disabled />
</div>
<div class="col-12 col-md-3">
<label class="form-label">推荐方</label>
<input class="form-control" id="detailReferrer" disabled />
</div>
<div class="col-12">
<label class="form-label">项目简介</label>
<textarea class="form-control" rows="4" id="detailIntro" disabled></textarea>
</div>
<div class="col-12">
<label class="form-label">商业计划书</label>
<div id="detailPlanFile" class="detail-attachment-list" aria-label="已上传的商业计划书"></div>
</div>
<div class="col-12">
<label class="form-label">其他佐证材料</label>
<div id="detailSupportingFiles" class="detail-attachment-list" aria-label="已上传的其他佐证材料"></div>
</div>
<div class="col-12">
<label class="form-label">参赛承诺书</label>
<div id="detailPromiseFile" class="detail-attachment-list" aria-label="已签署的参赛承诺书"></div>
</div>
</div>
</div>
</div>
<div id="auditOpinionCard" class="card mb-3 d-none">
<div class="card-body">
<label id="auditOpinionLabel" class="form-label mb-2">审核意见</label>
<div id="reviewerOpinionList" class="list-group"></div>
<textarea id="auditOpinionText" class="form-control d-none" rows="6" style="line-height: 1.65"></textarea>
</div>
</div>
<div id="auditActionBar" class="d-flex gap-2 flex-wrap mt-2">
<button type="button" id="rejectBtn" class="btn btn-warning text-dark">驳回</button>
<button type="button" id="approveBtn" class="btn btn-success">审核通过</button>
<button type="button" id="scoreBtn" class="btn btn-primary d-none">评分</button>
</div>
</div>
<div class="modal fade" id="rejectConfirmModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">审核意见</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="关闭"></button>
</div>
<div class="modal-body">
<textarea id="rejectCopyDisplay" class="form-control" rows="10" style="line-height: 1.65; resize: vertical;"></textarea>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button type="button" class="btn btn-warning text-dark" id="rejectConfirmOk">确认驳回</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="approveConfirmModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">审核通过确认</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="关闭"></button>
</div>
<div class="modal-body">
<textarea id="approveCopyDisplay" class="form-control" rows="6" style="line-height: 1.65; resize: vertical;"></textarea>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button type="button" class="btn btn-success" id="approveConfirmOk">确认通过</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="scoreModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable score-modal-dialog">
<div class="modal-content">
<div class="modal-header">
<div class="score-modal-heading">
<h5 id="scoreModalTitle" class="modal-title">项目评分</h5>
<a id="scorePlanLink" class="score-plan-link" href="#" target="_blank" rel="noopener">新窗口查看商业计划书</a>
</div>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="关闭"></button>
</div>
<div class="modal-body">
<section class="score-rules" aria-label="项目评分标准">
<div class="score-rules-table-wrap">
<table class="table score-rules-table mb-0">
<thead>
<tr>
<th scope="col">序号</th>
<th scope="col">指标分类</th>
<th scope="col">评审指标</th>
<th scope="col">核心评审要素</th>
<th scope="col">分值</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<th rowspan="6" scope="rowgroup" class="score-rules-group">通用指标</th>
<th scope="row">市场前景与需求匹配</th>
<td class="score-rules-detail">目标客群是否清晰,需求洞察是否精准,是否了解真实痛点;所处细分市场规模大、增速快及项目可拓展良好;若已有落地场景并运营数据良好可适当加分。</td>
<td><input class="score-module-input" type="text" inputmode="decimal" data-max="20" aria-label="市场前景与需求匹配评分" placeholder="0-20"></td>
</tr>
<tr><td>2</td><th scope="row">项目创新性</th><td class="score-rules-detail">产品、服务或商业模式较传统消费有明显创新;核心卖点独特且有一定门槛。</td><td><input class="score-module-input" type="text" inputmode="decimal" data-max="15" aria-label="项目创新性评分" placeholder="0-15"></td></tr>
<tr><td>3</td><th scope="row">团队综合实力</th><td class="score-rules-detail">创始人行业底蕴与领导力;技术、运营、供应链人才配置互补,团队核心骨干稳定。</td><td><input class="score-module-input" type="text" inputmode="decimal" data-max="15" aria-label="团队综合实力评分" placeholder="0-15"></td></tr>
<tr><td>4</td><th scope="row">材料及现场表现</th><td class="score-rules-detail">商业计划书逻辑严密、视觉精美;路演陈述清晰,答辩正面、准确、控场力强。</td><td><input class="score-module-input" type="text" inputmode="decimal" data-max="10" aria-label="材料及现场表现评分" placeholder="0-10"></td></tr>
<tr><td>5</td><th scope="row">合规及风险控制</th><td class="score-rules-detail">核心知识产权归属清晰无纠纷;产品与营销符合社会伦理;具备基本的舆情风控与意识。</td><td><input class="score-module-input" type="text" inputmode="decimal" data-max="5" aria-label="合规及风险控制评分" placeholder="0-5"></td></tr>
<tr><td>6</td><th scope="row">社会及文化效益</th><td class="score-rules-detail">在创造就业、绿色低碳、拉动地方经济方面具备积极社会效益;倡导健康向上的消费文化。</td><td><input class="score-module-input" type="text" inputmode="decimal" data-max="5" aria-label="社会及文化效益评分" placeholder="0-5"></td></tr>
<tr>
<td>7</td>
<th rowspan="2" scope="rowgroup" class="score-rules-group">特色指标</th>
<th scope="row">品牌附加值</th>
<td class="score-rules-detail">项目的文化内涵挖掘深度、国潮/老字号讲故事能力、IP化打造与品牌情感连接力。</td>
<td><input class="score-module-input" type="text" inputmode="decimal" data-max="15" aria-label="品牌附加值评分" placeholder="0-15"></td>
</tr>
<tr><td>8</td><th scope="row">消费体验与场景融合创新</th><td class="score-rules-detail">体验式、场景化、多元化消费场景设计;线上线下融合(O2O)能力;用户参与感与沉浸式体验。</td><td><input class="score-module-input" type="text" inputmode="decimal" data-max="15" aria-label="消费体验与场景融合创新评分" placeholder="0-15"></td></tr>
</tbody>
</table>
</div>
</section>
<div class="score-entry-panel">
<label for="scoreInput" class="form-label">项目总分</label>
<div class="score-input-row">
<input id="scoreInput" type="number" class="form-control" min="0" max="100" step="0.01" value="0.00" readonly aria-describedby="scoreInputSuffix scoreInputFeedback" />
<span id="scoreInputSuffix" class="score-input-suffix">满分 100</span>
</div>
<div id="scoreInputFeedback" class="invalid-feedback">请完成所有细分模块评分,且不得超过各项满分。</div>
</div>
<div class="form-check rescue-vote-card" id="rescueVoteCard">
<input class="form-check-input" type="checkbox" id="rescueVote" aria-describedby="rescueVoteHint rescueVoteLimit" />
<label class="form-check-label rescue-vote-label" for="rescueVote">
<span class="rescue-vote-copy">
<strong>使用一票拯救权</strong>
<small id="rescueVoteHint">勾选后,该项目将直接进入总决赛。</small>
</span>
<span class="rescue-vote-limit" id="rescueVoteLimit">每位专家仅一次</span>
</label>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary" id="scoreConfirmOk">提交评分</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="documentPreviewModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered document-preview-dialog">
<div class="modal-content document-preview-shell">
<div class="document-preview-header">
<div class="document-preview-heading">
<span class="document-preview-type">PDF</span>
<div class="min-w-0">
<h2 id="documentPreviewTitle">文档预览</h2>
<p>安全预览 · 仅供赛事审核使用</p>
</div>
</div>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="关闭"></button>
</div>
<div class="document-preview-toolbar">
<div class="document-page-control"><button type="button" class="document-tool-btn" disabled>上一页</button><span><strong>1</strong> / 1</span><button type="button" class="document-tool-btn" disabled>下一页</button></div>
<div class="document-zoom-control"><span>100%</span><button type="button" class="document-tool-btn" data-bs-dismiss="modal">关闭</button></div>
</div>
<div class="modal-body document-preview-stage">
<div class="document-page-wrap" style="--document-zoom:1">
<article class="document-paper" id="documentPaper" aria-label="文档正文"></article>
</div>
</div>
<div class="document-preview-footer"><span>文件内容已加载完成</span><button type="button" class="btn btn-primary px-4" data-bs-dismiss="modal">关闭</button></div>
</div>
</div>
</div>
<script src="../assets/bootstrap.bundle.min.js"></script>
<script>
(function () {
var params = new URLSearchParams(location.search);
var role = params.get("role") || "";
var state = params.get("state") || "pending";
var id = params.get("id") || "P2026-0001";
var score = params.get("score") || "";
var total = params.get("total") || "";
var isLocked = state === "pass" || state === "reject";
var listUrl = role === "reviewer" ? "./admin-list.html?role=reviewer" : "./admin-list.html";
var detailBackLink = document.getElementById("detailBackLink");
if (detailBackLink) detailBackLink.href = listUrl;
var adminDetailTitle = document.getElementById("adminDetailTitle");
if (role === "reviewer" && adminDetailTitle) {
adminDetailTitle.textContent = "项目详情";
}
var rejectCopy =
"参赛者,您好!\n\n" +
"非常感谢您主动报名本次大赛,认真提交相关申报材料。\n" +
"经组委会严格初审综合评定后,遗憾通知您,本次未能进入下一阶段。\n" +
"感谢您的积极参与和付出,望再接再厉,未来再创佳绩!";
var passCopy = "同意参赛。";
var detailMap = {
"P2026-0001": {
projectName: "高速硅光芯片研发平台",
playerName: "张晓华",
mobile: "13800138000",
email: "zhangxh@example.com",
companyName: "江苏某科技有限公司",
track: "场景与应用",
locationCountry: "中国",
locationProvince: "江苏省",
locationCity: "南京市",
overseaCountry: "-",
intro: "这是一个面向算力网络的高速硅光芯片研发与产业化,聚焦低功耗、高带宽和国产化替代。",
school: "南京大学",
degree: "硕士",
eventLocation: "苏州",
teamMembers: "张晓华、李明、王雪",
referrer: "南京大学科技成果转化中心",
planFileName: "高速硅光芯片研发平台-商业计划书.pdf",
supportingFileNames: ["企业营业执照.pdf", "核心专利证书.pdf"],
promiseSigner: "张晓华",
promiseDate: "2026年4月27日",
reviewers: [
{ name: "评审员A", score: 99.0 },
{ name: "评审员B", score: null },
{ name: "评审员C", score: null },
{ name: "评审员D", score: null }
]
},
"P2026-0002": {
projectName: "高密度光模块封装方案",
playerName: "顾苏明",
mobile: "13900139000",
email: "gusm@example.com",
companyName: "杭州文旅创新有限公司",
track: "材料与设备",
locationCountry: "中国",
locationProvince: "浙江省",
locationCity: "杭州市",
overseaCountry: "-",
intro: "面向高速光模块量产需求,研发高密度封装、耦合与测试一体化工艺。",
school: "浙江大学",
degree: "本科",
eventLocation: "上海",
teamMembers: "顾苏明、周灵",
referrer: "浙江大学校友会",
planFileName: "高密度光模块封装方案-商业计划书.pdf",
supportingFileNames: ["专利证书.pdf"],
promiseSigner: "顾苏明",
promiseDate: "2026年4月26日",
reviewers: [
{ name: "评审员A", score: 99.0 },
{ name: "评审员B", score: 100.0 },
{ name: "评审员C", score: 98.0 },
{ name: "评审员D", score: 97.0 }
]
},
"P2026-0003": {
projectName: "智能光纤传感系统",
playerName: "陈静",
mobile: "13700137000",
email: "chenj@example.com",
companyName: "",
track: "制造与封装",
locationCountry: "海外",
locationProvince: "-",
locationCity: "-",
overseaCountry: "新加坡",
intro: "基于社区服务网络构建便民生活服务集成平台,覆盖居家养老与健康管理。",
school: "新加坡国立大学",
degree: "本科",
eventLocation: "深圳",
teamMembers: "陈静、Lim Wei",
referrer: "-",
planFileName: "智能光纤传感系统-商业计划书.pdf",
supportingFileNames: ["软件著作权证书.pdf"],
promiseSigner: "陈静",
promiseDate: "2026年4月25日",
reviewers: [
{ name: "评审员A", score: 80.0 },
{ name: "评审员B", score: 78.0 },
{ name: "评审员C", score: 82.0 },
{ name: "评审员D", score: 79.0 }
]
}
};
var badge = document.getElementById("detailStatusBadge");
var suffix = " · 待评审";
if (state === "pass") {
badge.className = "status-pill status-pass";
suffix = role === "reviewer" && score ? " · " + score : total ? " · " + total : " · 通过";
} else if (state === "reject") {
badge.className = "status-pill status-reject";
suffix = role === "reviewer" && score ? " · " + score : total ? " · " + total : " · 未通过";
} else {
badge.className = "status-pill status-pending";
if (!role && total) suffix = " · " + total;
}
badge.textContent = "项目编号:" + id + suffix;
var detail = detailMap[id] || detailMap["P2026-0001"];
function readSavedSignature() {
var directSignature = localStorage.getItem("jscc_submitted_signature_" + id);
if (directSignature) return directSignature;
var draftKeys = ["jscc_my_event_detail_v2", "jscc_signup_form_draft_v1"];
for (var i = 0; i < draftKeys.length; i += 1) {
try {
var draft = JSON.parse(localStorage.getItem(draftKeys[i]) || "{}");
if (draft.promiseSignatureDataUrl) return draft.promiseSignatureDataUrl;
} catch (err) {
// Ignore malformed legacy drafts and continue to the next source.
}
}
return "";
}
var submittedSignature = readSavedSignature();
function signatureMarkup() {
if (!submittedSignature) {
return '<span class="signature-missing">未获取到手写签名</span>';
}
return '<img class="submitted-signature" src="' + submittedSignature + '" alt="' + detail.playerName + '提交的手写签名">';
}
var scoreModalTitle = document.getElementById("scoreModalTitle");
if (scoreModalTitle) scoreModalTitle.textContent = detail.projectName;
document.getElementById("detailProjectName").value = detail.projectName;
document.getElementById("detailPlayerName").value = detail.playerName;
document.getElementById("detailMobile").value = detail.mobile;
document.getElementById("detailEmail").value = detail.email;
document.getElementById("detailCompanyName").value = detail.companyName || "-";
document.getElementById("detailTrack").value = detail.track;
document.getElementById("detailLocationCountry").value = detail.locationCountry;
document.getElementById("detailLocationProvince").value = detail.locationProvince;
document.getElementById("detailLocationCity").value = detail.locationCity;
document.getElementById("detailIntro").value = detail.intro;
document.getElementById("detailSchool").value = detail.school;
document.getElementById("detailDegree").value = detail.degree;
document.getElementById("detailEventLocation").value = detail.eventLocation || "-";
document.getElementById("detailTeamMembers").value = detail.teamMembers || "-";
document.getElementById("detailReferrer").value = detail.referrer || "-";
var documentPreviewModal = new bootstrap.Modal(document.getElementById("documentPreviewModal"));
var documentPreviewTitle = document.getElementById("documentPreviewTitle");
var documentPaper = document.getElementById("documentPaper");
function buildPreviewContent(fileName, kind) {
if (kind === "promise") {
return '<h1>光通信创新创业大赛赛事承诺书</h1>' +
'<p>本团队(或个人)自愿报名参加大赛,为明确权利义务,维护赛事公平性与合法性,承诺严格履行以下条款:</p>' +
'<h2>一、参赛保证</h2>' +
'<p>1.1 提交的全部参赛材料真实、准确、完整,技术参数、研发进度、市场营收、产业链合作等数据来源合法可追溯,不存在造假、夸大宣传或刻意误导。</p>' +
'<p>1.2 同意组委会要求补充证明材料,并配合真实性核验、知识产权权属溯源、技术资料复核及样机实测;拒绝配合或核查结果存疑时,组委会有权取消参赛资格及已获奖项。</p>' +
'<p>1.3 参赛项目相关技术、产品、设计、代码、图纸、商标文案及商业模式等知识产权合法所有;使用第三方技术、开源代码或素材时已取得有效授权并遵守协议。</p>' +
'<p>1.4 因知识产权侵权或权属纠纷产生的法律责任与经济损失由参赛方承担,主办方、承办方及组委会不承担连带责任。</p>' +
'<h2>二、授权许可</h2>' +
'<p>2.1 为赛事存档、行业宣传、成果推介及产业科普,参赛方无偿授权组委会及合作机构在赛事及配套活动中拍照、录像、录音,并使用参赛人员肖像及项目图文视频资料进行发布传播。</p>' +
'<p>2.2 经准许入场的媒体、产业机构等第三方使用相关资料的权责由第三方与参赛方自行约定,组委会不对其独立传播行为承担责任。</p>' +
'<h2>三、声明</h2>' +
'<p>3.1 参赛方可在合规前提下分享参赛历程与技术成果,并对自行拍摄、剪辑和发布内容的真实性、知识产权、保密及秩序责任负责。</p>' +
'<p>3.2 因参赛方发布内容造成索赔、处罚或名誉损失的,参赛方应处理纠纷并承担赔偿金、罚金、律师费、诉讼费及公关维权费等损失。</p>' +
'<h2>四、承诺</h2>' +
'<p>4.1 参赛方遵守管理条例、评审细则和赛程安排,尊重评审专家及最终结果,理性沟通赛事争议,共同维护赛事秩序。</p>' +
'<p>本承诺书签字后即刻生效,约束全体参赛成员(个人参赛仅约束本人),受赛事举办地法律法规管辖。</p>' +
'<div class="doc-signature"><p class="signature-line"><span>参赛人签名:</span>' + signatureMarkup() + '</p><p>日期:' + detail.promiseDate + '</p></div>';
}
if (fileName.indexOf("营业执照") !== -1) {
return '<div class="license-document"><p class="license-label">营业执照</p><h1>营业执照</h1><p class="license-subtitle">(副本)</p><dl><dt>统一社会信用代码</dt><dd>91320594MA2EXAMPLE</dd><dt>名称</dt><dd>' + (detail.companyName || "江苏示例科技有限公司") + '</dd><dt>类型</dt><dd>有限责任公司</dd><dt>法定代表人</dt><dd>' + detail.playerName + '</dd><dt>注册资本</dt><dd>人民币 1000 万元</dd><dt>成立日期</dt><dd>2021 年 6 月 18 日</dd><dt>经营范围</dt><dd>集成电路设计、光电子器件研发、技术服务与成果转化。</dd></dl><p class="license-seal">市场监督管理局<br><span>2026 年 3 月 12 日</span></p></div>';
}
if (fileName.indexOf("专利") !== -1 || fileName.indexOf("著作权") !== -1) {
return '<div class="patent-document"><p class="patent-country">中华人民共和国国家知识产权局</p><h1>知识产权证书</h1><p>成果名称:一种低功耗高速光通信器件及其控制方法</p><p>权利人:' + (detail.companyName || detail.playerName) + '</p><p>证书编号:ZL 2024 1 0123456.7</p><p>授权日期:2026 年 2 月 8 日</p><div class="patent-note">本项成果经审查符合相关法律法规规定,依法授予知识产权并予以登记。</div><p class="license-seal">国家知识产权局<br><span>2026 年 2 月 8 日</span></p></div>';
}
return '<div class="doc-cover"><p class="doc-kicker">首届沪苏协同新兴产业科创大赛</p><h1>' + detail.projectName + '<br>商业计划书</h1><div class="doc-cover-rule"></div><p>申报单位:' + (detail.companyName || "个人项目") + '</p><p>项目负责人:' + detail.playerName + '</p><p>申报日期:2026 年 4 月</p></div>';
}
function buildPreviewDocument(fileName, kind) {
return '<!doctype html><html lang="zh-CN"><head><meta charset="UTF-8">' +
'<meta name="viewport" content="width=device-width,initial-scale=1">' +
'<title>' + fileName.replace(/[&<>"']/g, "") + '</title>' +
'<style>body{margin:0;background:#eef1f4;color:#20242a;font-family:"Noto Sans CJK SC","Source Han Sans SC","Noto Sans SC","Liberation Sans",sans-serif}' +
'.toolbar{position:sticky;top:0;padding:12px 20px;background:#20242a;color:#fff;font-size:14px}' +
'.paper{box-sizing:border-box;width:min(820px,calc(100% - 32px));min-height:1080px;margin:24px auto;padding:72px;background:#fff;box-shadow:0 8px 30px #0002}' +
'h1{text-align:center;margin:0 0 36px}.doc-cover{padding-top:180px;text-align:center}.doc-cover-rule{width:80px;border-top:3px solid #109bd3;margin:36px auto}' +
'h2{margin:28px 0 12px;font-size:20px}p{line-height:1.9;text-align:justify}.doc-signature{margin-top:56px;text-align:right}.doc-signature p{margin:8px 0;text-align:right}.signature-line{display:flex;align-items:center;justify-content:flex-end;gap:12px}.submitted-signature{display:inline-block;width:180px;height:64px;object-fit:contain;object-position:center;mix-blend-mode:multiply}.signature-missing{display:inline-block;min-width:180px;color:#777;font-size:14px;text-align:center;border-bottom:1px solid #aaa}.license-document dl{display:grid;grid-template-columns:160px 1fr;gap:12px}.patent-note{margin:40px 0;line-height:2}' +
'@media(max-width:600px){.paper{padding:36px 24px;min-height:calc(100vh - 76px);margin:16px auto}}' +
'</style></head><body><div class="toolbar">附件预览 · ' + fileName.replace(/[&<>]/g, "") +
'</div><article class="paper">' + buildPreviewContent(fileName, kind) + '</article></body></html>';
}
function renderAttachments(container, files) {
if (!files.length) {
container.innerHTML = '<div class="detail-attachment-empty">暂无附件</div>';
return;
}
files.forEach(function (file) {
var previewUrl = URL.createObjectURL(new Blob(
[buildPreviewDocument(file.name, file.kind)],
{ type: "text/html;charset=utf-8" }
));
var row = document.createElement("div");
row.className = "detail-attachment-row";
var name = document.createElement("a");
name.className = "detail-attachment-name";
name.href = previewUrl;
name.target = "_blank";
name.rel = "noopener";
name.title = file.name;
name.textContent = file.name;
name.setAttribute("aria-label", "在新窗口浏览" + file.name);
row.append(name);
container.appendChild(row);
});
}
renderAttachments(document.getElementById("detailPlanFile"), detail.planFileName ? [{ name: detail.planFileName, kind: "plan" }] : []);
renderAttachments(document.getElementById("detailSupportingFiles"), (detail.supportingFileNames || []).map(function (name) { return { name: name, kind: "supporting" }; }));
renderAttachments(document.getElementById("detailPromiseFile"), [{ name: "首届沪苏协同新兴产业科创大赛承诺书.pdf", kind: "promise" }]);
var scorePlanLink = document.getElementById("scorePlanLink");
var renderedPlanLink = document.querySelector("#detailPlanFile .detail-attachment-name");
if (scorePlanLink && renderedPlanLink) scorePlanLink.href = renderedPlanLink.href;
var auditActionBar = document.getElementById("auditActionBar");
var rejectBtn = document.getElementById("rejectBtn");
var approveBtn = document.getElementById("approveBtn");
var scoreBtn = document.getElementById("scoreBtn");
var auditOpinionCard = document.getElementById("auditOpinionCard");
var auditOpinionLabel = document.getElementById("auditOpinionLabel");
var reviewerOpinionList = document.getElementById("reviewerOpinionList");
var auditOpinionText = document.getElementById("auditOpinionText");
var isReviewer = role === "reviewer";
if (!isReviewer) {
auditActionBar.classList.add("d-none");
auditOpinionCard.classList.remove("d-none");
auditOpinionLabel.textContent = "评分";
if (reviewerOpinionList) {
var rowsHtml = (detail.reviewers || []).map(function (r) {
var isPending = r.score === null || r.score === undefined;
var scoreText = isPending ? "待评审" : Number(r.score).toFixed(2);
var scoreCls = isPending ? "reviewer-score-pending" : "reviewer-score-done";
return (
'<div class="reviewer-score-row">' +
'<span class="reviewer-score-name">' + r.name + "</span>" +
'<span class="' + scoreCls + '">' + scoreText + "</span>" +
"</div>"
);
}).join("");
reviewerOpinionList.innerHTML =
'<div class="reviewer-score-header">' +
'<span>评审员</span><span>评分</span>' +
"</div>" +
rowsHtml;
}
auditOpinionText.classList.add("d-none");
}
if (isLocked) {
auditActionBar.classList.add("d-none");
auditOpinionCard.classList.remove("d-none");
if (isReviewer) {
if (auditOpinionLabel) auditOpinionLabel.textContent = "评分";
if (reviewerOpinionList) reviewerOpinionList.classList.add("d-none");
auditOpinionText.classList.remove("d-none");
auditOpinionText.value = score && Number.isFinite(Number(score)) ? Number(score).toFixed(2) : "-";
auditOpinionText.rows = 2;
auditOpinionText.style.resize = "none";
auditOpinionText.classList.add("score-value-box");
} else {
auditOpinionText.classList.remove("score-value-box");
auditOpinionText.value = state === "pass" ? passCopy : rejectCopy;
}
} else if (isReviewer) {
rejectBtn.classList.add("d-none");
approveBtn.classList.add("d-none");
scoreBtn.classList.remove("d-none");
}
function goList() {
window.location.href = listUrl;
}
var rejectModalEl = document.getElementById("rejectConfirmModal");
var rejectModal = new bootstrap.Modal(rejectModalEl);
var approveModalEl = document.getElementById("approveConfirmModal");
var approveModal = new bootstrap.Modal(approveModalEl);
var rejectModalTa = document.getElementById("rejectCopyDisplay");
var approveModalTa = document.getElementById("approveCopyDisplay");
var scoreModalEl = document.getElementById("scoreModal");
var scoreModal = new bootstrap.Modal(scoreModalEl);
var scoreInput = document.getElementById("scoreInput");
var scoreInputFeedback = document.getElementById("scoreInputFeedback");
var scoreModuleInputs = Array.from(document.querySelectorAll(".score-module-input"));
var rescueVote = document.getElementById("rescueVote");
var rescueVoteCard = document.getElementById("rescueVoteCard");
var rescueVoteHint = document.getElementById("rescueVoteHint");
var rescueVoteLimit = document.getElementById("rescueVoteLimit");
var rescueKey = "hs_competition_reviewer_rescue_used";
function syncRescueVoteState() {
var usedProjectId = localStorage.getItem(rescueKey);
var hasBeenUsed = Boolean(usedProjectId);
rescueVote.checked = false;
rescueVote.disabled = hasBeenUsed;
rescueVoteCard.classList.toggle("is-disabled", hasBeenUsed);
rescueVoteHint.textContent = hasBeenUsed
? "本专家的一票拯救权已用于项目 " + usedProjectId + "。"
: "勾选后,该项目将直接进入总决赛。";
rescueVoteLimit.textContent = hasBeenUsed ? "拯救权已使用" : "每位专家仅一次";
}
syncRescueVoteState();
var scorePrecisionPattern = /^\d+(?:\.\d{1,2})?$/;
function validateScoreModule(input, allowEmpty) {
var rawValue = (input.value || "").trim();
var value = Number(rawValue);
var max = Number(input.dataset.max);
var errorMessage = "";
if (rawValue === "") {
if (!allowEmpty) errorMessage = "请填写本项评分(0-" + max + ")";
} else if (!scorePrecisionPattern.test(rawValue)) {
errorMessage = "评分最多保留小数点后2位";
} else if (!Number.isFinite(value) || value < 0 || value > max) {
errorMessage = "本项评分必须在0-" + max + "之间";
}
input.classList.toggle("is-invalid", Boolean(errorMessage));
input.setCustomValidity(errorMessage);
input.title = errorMessage || "允许范围:0-" + max + ",最多保留2位小数";
return !errorMessage;
}
function updateScoreTotal() {
var total = scoreModuleInputs.reduce(function (sum, input) {
var value = Number(input.value);
return sum + (Number.isFinite(value) ? value : 0);
}, 0);
scoreInput.value = total.toFixed(2);
scoreInput.classList.remove("is-invalid");
}
scoreModuleInputs.forEach(function (input) {
input.type = "text";
input.inputMode = "decimal";
input.dataset.lastValidValue = "";
input.addEventListener("input", function () {
var rawValue = input.value.trim();
var max = Number(input.dataset.max);
var isAllowedFormat = /^(?:\d+\.?\d{0,2})?$/.test(rawValue);
var numericValue = Number(rawValue);
var isWithinRange = rawValue === "" || (Number.isFinite(numericValue) && numericValue >= 0 && numericValue <= max);
if (!isAllowedFormat || !isWithinRange) {
input.value = input.dataset.lastValidValue;
return;
}
input.dataset.lastValidValue = rawValue;
input.classList.remove("is-invalid");
input.setCustomValidity("");
updateScoreTotal();
});
input.addEventListener("blur", function () {
if (input.value.endsWith(".")) input.value = input.value.slice(0, -1);
var value = Number(input.value);
if (validateScoreModule(input, false)) {
input.value = value.toFixed(2);
input.dataset.lastValidValue = input.value;
}
updateScoreTotal();
});
});
if (!isLocked && !isReviewer) {
rejectBtn.addEventListener("click", function () {
rejectModalTa.value = rejectCopy;
rejectModal.show();
});
approveBtn.addEventListener("click", function () {
approveModalTa.value = passCopy;
approveModal.show();
});
}
if (!isLocked && isReviewer) {
scoreBtn.addEventListener("click", function () {
syncRescueVoteState();
scoreModal.show();
});
}
document.getElementById("rejectConfirmOk").addEventListener("click", function () {
goList();
});
document.getElementById("approveConfirmOk").addEventListener("click", function () {
goList();
});
document.getElementById("scoreConfirmOk").addEventListener("click", function () {
if (rescueVote && rescueVote.checked && localStorage.getItem(rescueKey)) {
syncRescueVoteState();
return;
}
var invalidModule = null;
scoreModuleInputs.forEach(function (input) {
if (!validateScoreModule(input, false) && !invalidModule) invalidModule = input;
});
if (invalidModule) {
scoreInput.classList.add("is-invalid");
if (scoreInputFeedback) {
scoreInputFeedback.textContent = invalidModule.validationMessage;
}
invalidModule.focus();
return;
}
updateScoreTotal();
var v = Number(scoreInput.value);
var totalIsValid = Number.isFinite(v) && v >= 0 && v <= 100 && /^\d+(?:\.\d{2})$/.test(scoreInput.value);
if (!totalIsValid) {
scoreInput.classList.add("is-invalid");
if (scoreInputFeedback) scoreInputFeedback.textContent = "项目总分必须在0-100之间,并保留小数点后2位。";
scoreInput.focus();
return;
}
scoreInput.classList.remove("is-invalid");
scoreInput.value = v.toFixed(2);
if (rescueVote && rescueVote.checked) {
localStorage.setItem(rescueKey, id);
sessionStorage.setItem("hs_rescue_notice", "项目" + id + "已通过一票拯救权直通总决赛");
}
goList();
});
})();
</script>
</body>
</html>