doc-forge-remark/docs/原型v3-HTML/执行生成.html

727 lines
49 KiB
HTML
Raw Permalink 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>执行生成 · AI 文档模板生成系统</title>
<script src="https://unpkg.com/lucide@latest"></script>
<style>
:root{
--c-primary:#5b5bd6; --c-primary-hover:#4a4ac0; --c-primary-soft:#eeeefb;
--c-primary-2:#7c7cdb; --c-primary-dark:#3b3ba8;
--c-bg:#f5f6f8; --c-bg-card:#ffffff; --c-bg-soft:#f0f1f3; --c-bg-hover:#eaecef;
--c-border:#e0e2e6; --c-border-light:#eaecef;
--c-text:#1a1d24; --c-text-2:#5b626e; --c-text-3:#9aa1ad; --c-text-4:#c4c8cf;
--c-success:#1a8c4a; --c-warning:#d48a00; --c-danger:#d33; --c-info:#4a90d9;
--c-orange:#e68a00;
--font:-apple-system,"PingFang SC","Microsoft YaHei","Segoe UI",Roboto,sans-serif;
--fs-h1:22px; --fs-h2:17px; --fs-h3:15px; --fs-body:14px; --fs-sm:13px; --fs-xs:12px;
--fw-bold:600; --fw-medium:500;
--sp-1:4px; --sp-2:8px; --sp-3:12px; --sp-4:16px; --sp-5:24px; --sp-6:32px;
--radius:8px; --radius-sm:6px; --radius-lg:12px;
--shadow:0 1px 3px rgba(0,0,0,.06),0 1px 2px rgba(0,0,0,.04);
--shadow-md:0 4px 12px rgba(0,0,0,.08);
--shadow-lg:0 8px 24px rgba(0,0,0,.10);
}
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
body{font-family:var(--font);font-size:var(--fs-body);color:var(--c-text);background:var(--c-bg);line-height:1.6;-webkit-font-smoothing:antialiased;height:100vh;overflow:hidden}
a{color:var(--c-primary);text-decoration:none}
[data-lucide]{width:16px;height:16px;stroke-width:1.8;vertical-align:middle;color:inherit;flex-shrink:0}
.icon-sm{width:14px;height:14px}
.icon-lg{width:20px;height:20px}
/* === top bar === */
.app{display:flex;flex-direction:column;height:100vh}
.topbar{height:52px;background:var(--c-bg-card);border-bottom:1px solid var(--c-border);display:flex;align-items:center;padding:0 var(--sp-5);flex-shrink:0;gap:var(--sp-3)}
.topbar-logo{display:flex;align-items:center;gap:var(--sp-2);font-weight:var(--fw-bold);font-size:var(--fs-h3);color:var(--c-text);margin-right:var(--sp-4);flex-shrink:0}
.logo-icon{width:28px;height:28px;background:var(--c-primary);border-radius:var(--radius-sm);display:flex;align-items:center;justify-content:center;color:#fff;font-size:13px;font-weight:700}
.topbar-nav{display:flex;align-items:center;gap:var(--sp-1)}
.topbar-tab{padding:var(--sp-2) var(--sp-4);cursor:pointer;font-size:var(--fs-sm);color:var(--c-text-2);border-radius:var(--radius-sm);transition:all .12s;user-select:none;display:flex;align-items:center;gap:var(--sp-2);white-space:nowrap}
.topbar-tab:hover{background:var(--c-bg-soft);color:var(--c-text)}
.topbar-tab.active{background:var(--c-primary-soft);color:var(--c-primary);font-weight:var(--fw-medium)}
.topbar-right{margin-left:auto;display:flex;align-items:center;gap:var(--sp-3)}
.user-badge{display:flex;align-items:center;gap:var(--sp-2);padding:var(--sp-1) var(--sp-2) var(--sp-1) var(--sp-3);background:var(--c-bg-soft);border-radius:20px;cursor:pointer}
.user-avatar-sm{width:22px;height:22px;border-radius:50%;background:var(--c-primary-soft);color:var(--c-primary);display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:var(--fw-bold)}
/* === main layout === */
.main-area{flex:1;overflow:hidden;display:flex}
.screen{display:none;flex:1;overflow:hidden}
.screen.active{display:flex}
.scroll-area{flex:1;overflow-y:auto;padding:var(--sp-5) var(--sp-6)}
/* === breadcrumb === */
.breadcrumb{display:flex;align-items:center;gap:var(--sp-2);font-size:var(--fs-sm);color:var(--c-text-3);margin-bottom:var(--sp-4);flex-wrap:wrap}
.breadcrumb span,.breadcrumb a{color:var(--c-text-2)}
/* === card === */
.card{background:var(--c-bg-card);border-radius:var(--radius-lg);border:1px solid var(--c-border);overflow:hidden}
.card-header{display:flex;align-items:center;justify-content:space-between;padding:var(--sp-4) var(--sp-5);border-bottom:1px solid var(--c-border-light);flex-shrink:0}
.card-title{font-size:var(--fs-h3);font-weight:var(--fw-bold);display:flex;align-items:center;gap:var(--sp-2)}
.card-body{padding:var(--sp-5)}
/* === buttons === */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;padding:8px 18px;border-radius:var(--radius);font-size:var(--fs-sm);font-weight:var(--fw-medium);cursor:pointer;border:1px solid transparent;transition:all .12s;line-height:1.4;white-space:nowrap}
.btn-primary{background:var(--c-primary);color:#fff;border-color:var(--c-primary)}
.btn-primary:hover{background:var(--c-primary-hover)}
.btn-outline{background:transparent;color:var(--c-text);border-color:var(--c-border)}
.btn-outline:hover{background:var(--c-bg-soft);border-color:var(--c-text-3)}
.btn-ghost{background:transparent;color:var(--c-text-2);border-color:transparent;padding:6px 10px}
.btn-ghost:hover{background:var(--c-bg-soft)}
.btn-success{background:var(--c-success);color:#fff}
.btn-success:hover{background:#157a3e}
.btn-sm{padding:5px 12px;font-size:var(--fs-xs)}
.btn-xs{padding:3px 8px;font-size:11px;border-radius:var(--radius-sm)}
/* === form === */
.form-group{margin-bottom:var(--sp-4)}
.form-label{display:block;font-size:var(--fs-sm);font-weight:var(--fw-medium);color:var(--c-text-2);margin-bottom:var(--sp-1)}
.form-input,.form-select{width:100%;padding:8px 12px;border:1px solid var(--c-border);border-radius:var(--radius);font-size:var(--fs-body);font-family:var(--font);color:var(--c-text);background:var(--c-bg-card);outline:none;transition:border-color .15s}
.form-input:focus,.form-select:focus{border-color:var(--c-primary);box-shadow:0 0 0 2px var(--c-primary-soft)}
.form-textarea{width:100%;min-height:80px;padding:8px 12px;border:1px solid var(--c-border);border-radius:var(--radius);font-size:var(--fs-body);font-family:var(--font);resize:vertical;outline:none}
.form-textarea:focus{border-color:var(--c-primary);box-shadow:0 0 0 2px var(--c-primary-soft)}
/* === template list === */
.template-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:var(--sp-4)}
.tpl-card{border:1px solid var(--c-border-light);border-radius:var(--radius-lg);background:var(--c-bg-card);padding:var(--sp-5);cursor:pointer;transition:all .12s}
.tpl-card:hover{box-shadow:var(--shadow-md);border-color:var(--c-primary-2)}
.tpl-card .tpl-name{font-size:var(--fs-body);font-weight:var(--fw-bold);margin-bottom:var(--sp-1);display:flex;align-items:center;gap:var(--sp-2)}
.tpl-card .tpl-desc{font-size:var(--fs-xs);color:var(--c-text-3);margin-bottom:var(--sp-3)}
.tpl-card .tpl-meta{display:flex;align-items:center;gap:var(--sp-3);font-size:var(--fs-xs);color:var(--c-text-3)}
.tpl-card .tpl-actions{margin-top:var(--sp-3);display:flex;gap:var(--sp-2)}
.tpl-status{font-size:10px;padding:2px 10px;border-radius:10px;display:inline-block}
.tpl-status.ready{background:#e8f5e9;color:var(--c-success)}
.tpl-status.editing{background:#fff3e0;color:var(--c-warning)}
/.tpl-status.empty{background:var(--c-bg-soft);color:var(--c-text-3)}
/* === template editor LAYOUT (left+right split) === */
.tpl-editor{display:flex;flex:1;overflow:hidden}
.tpl-left{width:380px;flex-shrink:0;border-right:1px solid var(--c-border);background:var(--c-bg-card);display:flex;flex-direction:column;overflow:hidden}
.tpl-left-header{display:flex;align-items:center;justify-content:space-between;padding:var(--sp-3) var(--sp-4);border-bottom:1px solid var(--c-border-light);flex-shrink:0}
.tpl-left-scroll{flex:1;overflow-y:auto;padding:var(--sp-4)}
.tpl-right{flex:1;display:flex;flex-direction:column;overflow:hidden;background:var(--c-bg)}
.tpl-right-toolbar{display:flex;align-items:center;padding:var(--sp-2) var(--sp-4);border-bottom:1px solid var(--c-border);background:var(--c-bg-card);flex-shrink:0;gap:var(--sp-2)}
.tpl-right-body{flex:1;overflow-y:auto;padding:var(--sp-5) var(--sp-6);display:flex;justify-content:center}
/* === mode toggle === */
.mode-group{display:flex;border:1px solid var(--c-border);border-radius:var(--radius);overflow:hidden;flex-shrink:0}
.mode-btn{padding:4px 14px;cursor:pointer;font-size:var(--fs-xs);color:var(--c-text-2);background:var(--c-bg-card);border:none;border-right:1px solid var(--c-border);transition:all .12s}
.mode-btn:last-child{border-right:none}
.mode-btn.active{background:var(--c-primary-soft);color:var(--c-primary);font-weight:var(--fw-medium)}
.mode-btn:hover:not(.active){background:var(--c-bg-soft)}
/* === paragraph markers === */
.doc-edit-page{width:794px;background:#fff;box-shadow:0 2px 12px rgba(0,0,0,.08);padding:80px 72px 120px;min-height:500px;height:auto;font-size:14px;line-height:1.8;position:relative}
.doc-edit-page .doc-title{font-size:20px;font-weight:var(--fw-bold);text-align:center;margin-bottom:var(--sp-5)}
.doc-edit-page .doc-subtitle{text-align:center;font-size:var(--fs-sm);color:var(--c-text-2);margin-bottom:var(--sp-5)}
.doc-edit-page .sec-title{font-size:16px;font-weight:var(--fw-bold);margin-top:var(--sp-5);margin-bottom:var(--sp-3);padding-bottom:var(--sp-1);border-bottom:2px solid var(--c-text)}
.doc-edit-page .para-block{position:relative;padding:var(--sp-2);margin:var(--sp-1) 0;border-radius:var(--radius-sm);border:2px solid transparent;cursor:pointer;transition:all .12s}
.doc-edit-page .para-block:hover{border-color:var(--c-border)}
.doc-edit-page .para-block.selected{border-color:var(--c-primary);background:var(--c-primary-soft)}
.doc-edit-page .para-block .para-tag{position:absolute;right:4px;top:4px;font-size:9px;padding:1px 6px;border-radius:4px;display:none}
.doc-edit-page .para-block:hover .para-tag,.doc-edit-page .para-block.selected .para-tag{display:block}
.doc-edit-page .para-block .para-tag.ai{background:var(--c-primary-soft);color:var(--c-primary)}
.doc-edit-page .para-block .para-tag.manual{background:#fff3e0;color:var(--c-orange)}
.doc-edit-page table{width:100%;border-collapse:collapse;margin:var(--sp-3) 0;font-size:var(--fs-sm)}
.doc-edit-page th,.doc-edit-page td{padding:6px 10px;border:1px solid #ddd;text-align:left}
.doc-edit-page th{background:var(--c-bg-soft);font-weight:var(--fw-medium);font-size:var(--fs-xs)}
/* === edit mode rich editor === */
.edit-toolbar{display:flex;align-items:center;gap:var(--sp-1);padding:var(--sp-2) var(--sp-3);border:1px solid var(--c-border);border-bottom:none;border-radius:var(--radius) var(--radius) 0 0;background:var(--c-bg-card);flex-wrap:wrap;flex-shrink:0}
.edit-toolbar .tb-divider{width:1px;height:18px;background:var(--c-border);margin:0 var(--sp-1)}
.edit-toolbar .tb-btn{width:28px;height:28px;display:flex;align-items:center;justify-content:center;border-radius:var(--radius-sm);cursor:pointer;color:var(--c-text-2);font-size:var(--fs-sm)}
.edit-toolbar .tb-btn:hover{background:var(--c-bg-soft);color:var(--c-text)}
.edit-toolbar .tb-btn.active{background:var(--c-primary-soft);color:var(--c-primary)}
.edit-body{border:1px solid var(--c-border);border-radius:0 0 var(--radius) var(--radius);padding:var(--sp-5) var(--sp-6);background:var(--c-bg-card);min-height:500px;outline:none;font-size:14px;line-height:1.8;color:var(--c-text);width:794px}
.edit-body:focus{border-color:var(--c-primary)}
.edit-body .doc-title{font-size:20px;font-weight:var(--fw-bold);text-align:center;margin-bottom:var(--sp-5)}
.edit-body .doc-subtitle{text-align:center;font-size:var(--fs-sm);color:var(--c-text-2);margin-bottom:var(--sp-5)}
.edit-body .sec-title{font-size:16px;font-weight:var(--fw-bold);margin-top:var(--sp-5);margin-bottom:var(--sp-3);padding-bottom:var(--sp-1);border-bottom:2px solid var(--c-text)}
.edit-body table{width:100%;border-collapse:collapse;margin:var(--sp-3) 0;font-size:var(--fs-sm)}
.edit-body th,.edit-body td{padding:6px 10px;border:1px solid #ddd;text-align:left}
.edit-body th{background:var(--c-bg-soft);font-weight:var(--fw-medium);font-size:var(--fs-xs)}
/* === left panel config === */
.config-section{margin-bottom:var(--sp-5)}
.config-section-title{font-size:var(--fs-sm);font-weight:var(--fw-bold);color:var(--c-text);margin-bottom:var(--sp-3);padding-bottom:var(--sp-2);border-bottom:1px solid var(--c-border-light)}
.config-field{margin-bottom:var(--sp-3)}
.config-field .cf-label{font-size:var(--fs-xs);color:var(--c-text-3);margin-bottom:var(--sp-1)}
.config-field .cf-value{font-size:var(--fs-sm);color:var(--c-text)}
.cfg-toggle{display:flex;align-items:center;gap:var(--sp-2);cursor:pointer;user-select:none;padding:var(--sp-1) 0}
.toggle-switch{width:32px;height:18px;border-radius:9px;background:var(--c-border);position:relative;cursor:pointer;transition:background .2s;flex-shrink:0}
.toggle-switch.on{background:var(--c-primary)}
.toggle-switch::after{content:'';width:14px;height:14px;border-radius:50%;background:#fff;position:absolute;top:2px;left:2px;transition:transform .2s;box-shadow:0 1px 2px rgba(0,0,0,.15)}
.toggle-switch.on::after{transform:translateX(14px)}
.cfg-select{padding:6px 10px;border:1px solid var(--c-border);border-radius:var(--radius-sm);font-size:var(--fs-sm);font-family:var(--font);color:var(--c-text);background:var(--c-bg-card);outline:none;width:100%}
.cfg-select:focus{border-color:var(--c-primary)}
/* === left panel paragraph list (edit mode) === */
.para-list-item{display:flex;align-items:center;gap:var(--sp-2);padding:var(--sp-2) var(--sp-3);border-radius:var(--radius-sm);cursor:pointer;font-size:var(--fs-sm);color:var(--c-text-2);transition:all .12s;margin-bottom:2px}
.para-list-item:hover{background:var(--c-bg-soft)}
.para-list-item.active{background:var(--c-primary-soft);color:var(--c-primary);font-weight:var(--fw-medium)}
.para-list-item .pli-index{width:20px;height:20px;border-radius:50%;background:var(--c-bg-soft);display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:var(--fw-bold);color:var(--c-text-3);flex-shrink:0}
.para-list-item.active .pli-index{background:var(--c-primary);color:#fff}
.para-list-item .pli-badge{font-size:9px;padding:0 6px;border-radius:6px;margin-left:auto;flex-shrink:0}
.para-list-item .pli-badge.ai{background:var(--c-primary-soft);color:var(--c-primary)}
.para-list-item .pli-badge.manual{background:#fff3e0;color:var(--c-orange)}
/* === gen progress & hints === */
.gen-progress{background:var(--c-bg-card);border:1px solid var(--c-border);border-radius:var(--radius);padding:var(--sp-4);margin-bottom:var(--sp-4);display:flex;align-items:center;gap:var(--sp-4)}
.spinner{width:20px;height:20px;border:2px solid var(--c-border);border-top-color:var(--c-primary);border-radius:50%;animation:spin .8s linear infinite;flex-shrink:0}
@keyframes spin{to{transform:rotate(360deg)}}
/* === upload zone === */
.upload-zone{border:2px dashed var(--c-border);border-radius:var(--radius-lg);padding:var(--sp-6) var(--sp-4);text-align:center;cursor:pointer;transition:all .15s;background:var(--c-bg-card)}
.upload-zone:hover{border-color:var(--c-primary);background:var(--c-primary-soft)}
.upload-icon{width:48px;height:48px;background:var(--c-bg-soft);border-radius:50%;display:flex;align-items:center;justify-content:center;margin:0 auto var(--sp-3);color:var(--c-text-3)}
.uploaded-file{display:flex;align-items:center;gap:var(--sp-3);padding:var(--sp-3) var(--sp-4);background:var(--c-bg-soft);border-radius:var(--radius);margin-top:var(--sp-3)}
.uploaded-file .file-icon.excel{background:#e8f5e9;color:#2e7d32}
/* === model card === */
.model-card{border:1px solid var(--c-border-light);border-radius:var(--radius);padding:var(--sp-4);margin-bottom:var(--sp-3);display:flex;align-items:center;gap:var(--sp-4)}
.model-card .mc-icon{width:40px;height:40px;border-radius:var(--radius);display:flex;align-items:center;justify-content:center;flex-shrink:0;font-size:16px;font-weight:var(--fw-bold);color:#fff}
.model-card .mc-info{flex:1;min-width:0}
.model-card .mc-name{font-size:var(--fs-sm);font-weight:var(--fw-medium)}
.model-card .mc-provider{font-size:var(--fs-xs);color:var(--c-text-3)}
.model-card .mc-status{font-size:var(--fs-xs)}
.model-card .mc-status.on{color:var(--c-success)}
.model-card .mc-status.off{color:var(--c-text-3)}
/* === test result modal === */
.modal-overlay{display:none;position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,.4);z-index:1000;align-items:center;justify-content:center}
.modal-overlay.open{display:flex}
.modal{background:var(--c-bg-card);border-radius:var(--radius-lg);width:640px;max-width:90vw;max-height:80vh;overflow-y:auto;box-shadow:var(--shadow-lg)}
.modal-header{display:flex;align-items:center;justify-content:space-between;padding:var(--sp-4) var(--sp-5);border-bottom:1px solid var(--c-border);font-size:var(--fs-h3);font-weight:var(--fw-bold)}
.modal-header .close-btn{cursor:pointer;color:var(--c-text-3);padding:4px;border-radius:var(--radius-sm)}
.modal-header .close-btn:hover{background:var(--c-bg-soft);color:var(--c-text)}
.modal-body{padding:var(--sp-5)}
.modal-footer{display:flex;justify-content:flex-end;gap:var(--sp-2);padding:var(--sp-4) var(--sp-5);border-top:1px solid var(--c-border-light)}
/* === typography === */
.text-xs{font-size:var(--fs-xs)}
.text-sm{font-size:var(--fs-sm)}
.text-muted{color:var(--c-text-3)}
.flex{display:flex}
.flex-1{flex:1}
.gap-2{gap:var(--sp-2)}
.gap-3{gap:var(--sp-3)}
.items-center{align-items:center}
.justify-between{justify-content:space-between}
.mb-3{margin-bottom:var(--sp-3)}
.mb-4{margin-bottom:var(--sp-4)}
.mt-3{margin-top:var(--sp-3)}
.p-3{padding:var(--sp-3)}
.p-4{padding:var(--sp-4)}
</style>
</head>
<body>
<div class="app">
<header class="topbar">
<div class="topbar-logo"><div class="logo-icon">A</div><span>AI 文档模板</span></div>
<a class="topbar-tab" href="模板管理.html"><i data-lucide="layout-dashboard" class="icon-sm"></i> 模板管理</a>
<a class="topbar-tab" href="模型管理.html"><i data-lucide="cpu" class="icon-sm"></i> 模型管理</a>
<a class="topbar-tab active" href="执行生成.html"><i data-lucide="zap" class="icon-sm"></i> 执行生成</a>
<a class="topbar-tab" href="生成记录.html"><i data-lucide="clock" class="icon-sm"></i> 生成记录</a>
<div class="topbar-right">
<span class="text-xs text-muted">v3.0</span>
<div class="user-badge"><span class="text-xs" style="font-weight:var(--fw-medium)">周文涛</span><div class="user-avatar-sm"></div></div>
</div>
</header>
<div class="main-area">
<div class="screen active" id="screen-generate">
<div class="scroll-area" style="display:flex;flex-direction:column;height:100%;padding-bottom:0">
<div class="breadcrumb"><i data-lucide="home" class="icon-sm"></i> 执行生成 / <span>选择模板 → 上传文件 → AI 自动生成</span></div>
<div style="display:flex;gap:var(--sp-5);flex:1;min-height:0">
<!-- Left: 选择模板 -->
<div style="width:340px;flex-shrink:0;display:flex;flex-direction:column">
<div class="card" style="flex-shrink:0">
<div class="card-header"><span class="card-title"><i data-lucide="file-text" style="color:var(--c-primary)"></i>选择模板</span></div>
<div class="card-body">
<div class="form-group" style="margin-bottom:var(--sp-3)">
<select class="form-select" onchange="onTplSelect()">
<option value="" disabled selected>— 请选择已编辑好的模板 —</option>
<option value="季度经济活动分析报告" selected>季度经济活动分析报告</option>
<option value="年度工作总结模板">年度工作总结模板</option>
</select>
</div>
<div style="background:var(--c-bg-soft);border-radius:var(--radius);padding:var(--sp-3);font-size:var(--fs-sm);color:var(--c-text-2)">
<div style="font-weight:var(--fw-medium);margin-bottom:var(--sp-1)">季度经济活动分析报告</div>
<div class="text-xs text-muted">8 个段落 · 3 个需上传参考文件 · 5 个可直接生成</div>
</div>
<!-- 模板统计 -->
<div style="display:flex;gap:var(--sp-3);margin-top:var(--sp-3);font-size:var(--fs-sm)">
<div style="flex:1;text-align:center;padding:var(--sp-2);background:var(--c-bg-soft);border-radius:var(--radius-sm)">
<div style="font-size:18px;font-weight:var(--fw-bold);color:var(--c-primary)">8</div>
<div class="text-xs text-muted">总段落</div>
</div>
<div style="flex:1;text-align:center;padding:var(--sp-2);background:#e8f5e9;border-radius:var(--radius-sm)">
<div style="font-size:18px;font-weight:var(--fw-bold);color:var(--c-success)">5</div>
<div class="text-xs text-muted">自动生成</div>
</div>
<div style="flex:1;text-align:center;padding:var(--sp-2);background:#fff3e0;border-radius:var(--radius-sm)">
<div style="font-size:18px;font-weight:var(--fw-bold);color:var(--c-warning)">3</div>
<div class="text-xs text-muted">需要文件</div>
</div>
</div>
</div>
</div>
<!-- 进度显示在左侧底部 -->
<div id="genLeftStatus" style="display:none;flex:1;margin-top:var(--sp-4)">
<div class="gen-progress"><div class="spinner"></div><div style="flex:1;font-size:var(--fs-sm);color:var(--c-text-2)" id="genLeftText">正在生成「一、主要经营指标完成情况」...</div></div>
<div style="background:var(--c-bg-card);border:1px solid var(--c-border);border-radius:var(--radius);padding:var(--sp-3);margin-top:var(--sp-3)">
<div style="font-size:var(--fs-sm);font-weight:var(--fw-medium);margin-bottom:var(--sp-2)">生成进度</div>
<div style="height:8px;background:var(--c-bg-soft);border-radius:4px;overflow:hidden;margin-bottom:var(--sp-3)"><div id="genProgressBar" style="width:42%;height:100%;background:var(--c-primary);border-radius:4px;transition:width .3s"></div></div>
<div style="display:flex;flex-direction:column;gap:var(--sp-1);font-size:var(--fs-xs)">
<div class="flex items-center gap-2"><span id="g1" style="color:var(--c-success)"><i data-lucide="check-circle" class="icon-sm"></i></span><span style="color:var(--c-text-2)">一、主要经营指标完成情况</span></div>
<div class="flex items-center gap-2"><span id="g2" style="color:var(--c-success)"><i data-lucide="check-circle" class="icon-sm"></i></span><span style="color:var(--c-text-2)">主要经营指标完成情况表</span></div>
<div class="flex items-center gap-2"><span id="g3" style="color:var(--c-primary)"><i data-lucide="loader" class="icon-sm"></i></span><span style="color:var(--c-text)">二、成本费用分析</span></div>
<div class="flex items-center gap-2"><span id="g4" style="color:var(--c-text-4)"><i data-lucide="circle" class="icon-sm"></i></span><span class="text-muted">三、存在的主要问题</span></div>
<div class="flex items-center gap-2"><span id="g5" style="color:var(--c-text-4)"><i data-lucide="circle" class="icon-sm"></i></span><span class="text-muted">四、下一步工作措施</span></div>
<div class="flex items-center gap-2"><span id="g6" style="color:var(--c-text-4)"><i data-lucide="circle" class="icon-sm"></i></span><span class="text-muted">附图:各季度营收趋势图</span></div>
</div>
</div>
</div>
<!-- 完成状态 -->
<div id="genDoneSide" style="display:none;background:#e8f5e9;border:1px solid #a5d6a7;border-radius:var(--radius);padding:var(--sp-3);margin-top:var(--sp-4);align-items:center;gap:var(--sp-3)">
<i data-lucide="check-circle" style="color:var(--c-success);flex-shrink:0"></i>
<span style="flex:1;font-size:var(--fs-sm)">全部生成完毕</span>
</div>
</div>
<!-- Right: 段落 + 上传 -->
<div style="flex:1;display:flex;flex-direction:column;min-width:0">
<div class="card" style="flex:1;display:flex;flex-direction:column">
<div class="card-header"><span class="card-title"><i data-lucide="list" style="color:var(--c-primary)"></i>段落文件配置</span><span class="text-xs text-muted">根据模板配置,以下段落需要上传参考文件</span></div>
<div style="flex:1;overflow-y:auto;padding:var(--sp-4)">
<!-- 段落1 -->
<div style="border:1px solid var(--c-border-light);border-radius:var(--radius);padding:var(--sp-3);margin-bottom:var(--sp-3);background:var(--c-bg-card)">
<div class="flex items-center justify-between">
<div class="flex items-center gap-2">
<span style="width:22px;height:22px;border-radius:50%;background:var(--c-primary-soft);color:var(--c-primary);display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:700">1</span>
<span style="font-size:var(--fs-sm);font-weight:var(--fw-medium)">一、主要经营指标完成情况</span>
<span style="font-size:10px;padding:1px 8px;border-radius:6px;background:var(--c-primary-soft);color:var(--c-primary)">Claude 3.5</span>
</div>
<div style="display:flex;align-items:center;gap:var(--sp-2)">
<span class="text-xs" style="color:var(--c-success)"><i data-lucide="check-circle" class="icon-sm"></i>已上传</span>
<button class="btn btn-ghost btn-xs">更换</button>
</div>
</div>
<div class="text-xs text-muted" style="margin-top:var(--sp-1);padding-left:var(--sp-8)">备注需上传财务部提供的季度财务数据报表Excel格式含各指标完成值</div>
</div>
<!-- 段落2 -->
<div style="border:1px solid var(--c-border-light);border-radius:var(--radius);padding:var(--sp-3);margin-bottom:var(--sp-3);background:var(--c-bg-card)">
<div class="flex items-center justify-between">
<div class="flex items-center gap-2">
<span style="width:22px;height:22px;border-radius:50%;background:var(--c-primary-soft);color:var(--c-primary);display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:700">2</span>
<span style="font-size:var(--fs-sm);font-weight:var(--fw-medium)">主要经营指标完成情况表</span>
<span style="font-size:10px;padding:1px 8px;border-radius:6px;background:#e8f5e9;color:var(--c-success)">GPT-4o</span>
</div>
<div style="display:flex;align-items:center;gap:var(--sp-2)">
<span class="text-xs" style="color:var(--c-success)"><i data-lucide="check-circle" class="icon-sm"></i>已上传</span>
<button class="btn btn-ghost btn-xs">更换</button>
</div>
</div>
<div class="text-xs text-muted" style="margin-top:var(--sp-1);padding-left:var(--sp-8)">备注需上传各部门经营数据汇总表Excel格式含指标明细</div>
</div>
<!-- 段落3 -->
<div style="border:1px solid var(--c-border-light);border-radius:var(--radius);padding:var(--sp-3);margin-bottom:var(--sp-3);background:var(--c-bg-card)">
<div class="flex items-center justify-between">
<div class="flex items-center gap-2">
<span style="width:22px;height:22px;border-radius:50%;background:var(--c-primary-soft);color:var(--c-primary);display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:700">3</span>
<span style="font-size:var(--fs-sm);font-weight:var(--fw-medium)">附图:各季度营收趋势图</span>
<span style="font-size:10px;padding:1px 8px;border-radius:6px;background:#fff3e0;color:#e65100">DeepSeek-V3</span>
</div>
<div style="display:flex;align-items:center;gap:var(--sp-2)">
<span class="text-xs" style="color:var(--c-success)"><i data-lucide="check-circle" class="icon-sm"></i>已上传</span>
<button class="btn btn-ghost btn-xs">更换</button>
</div>
</div>
<div class="text-xs text-muted" style="margin-top:var(--sp-1);padding-left:var(--sp-8)">备注需上传营收数据季度表Excel格式</div>
</div>
<!-- 自动生成段落(不需要上传文件) -->
<div style="border:1px dashed var(--c-border-light);border-radius:var(--radius);padding:var(--sp-3);margin-bottom:var(--sp-3);background:var(--c-bg-soft);opacity:.7">
<div class="flex items-center gap-2">
<span style="width:22px;height:22px;border-radius:50%;background:var(--c-bg-hover);color:var(--c-text-3);display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:700">4</span>
<span style="font-size:var(--fs-sm);color:var(--c-text-2)">二、成本费用分析</span>
<span style="font-size:10px;padding:1px 8px;border-radius:6px;background:var(--c-primary-soft);color:var(--c-primary)">Claude 3.5</span>
<span style="margin-left:auto;font-size:var(--fs-xs);color:var(--c-text-3)">无需上传文件</span>
</div>
</div>
<div style="border:1px dashed var(--c-border-light);border-radius:var(--radius);padding:var(--sp-3);margin-bottom:var(--sp-3);background:var(--c-bg-soft);opacity:.7">
<div class="flex items-center gap-2">
<span style="width:22px;height:22px;border-radius:50%;background:var(--c-bg-hover);color:var(--c-text-3);display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:700">5</span>
<span style="font-size:var(--fs-sm);color:var(--c-text-2)">三、存在的主要问题</span>
<span style="font-size:10px;padding:1px 8px;border-radius:6px;background:var(--c-primary-soft);color:var(--c-primary)">Claude 3.5</span>
<span style="margin-left:auto;font-size:var(--fs-xs);color:var(--c-text-3)">无需上传文件</span>
</div>
</div>
<div style="border:1px dashed var(--c-border-light);border-radius:var(--radius);padding:var(--sp-3);margin-bottom:var(--sp-3);background:var(--c-bg-soft);opacity:.7">
<div class="flex items-center gap-2">
<span style="width:22px;height:22px;border-radius:50%;background:var(--c-bg-hover);color:var(--c-text-3);display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:700">6</span>
<span style="font-size:var(--fs-sm);color:var(--c-text-2)">四、下一步工作措施</span>
<span style="font-size:10px;padding:1px 8px;border-radius:6px;background:var(--c-primary-soft);color:var(--c-primary)">Claude 3.5</span>
<span style="margin-left:auto;font-size:var(--fs-xs);color:var(--c-text-3)">无需上传文件</span>
</div>
</div>
</div>
<!-- 底部: 统计 + 生成按钮 -->
<div style="display:flex;align-items:center;justify-content:space-between;padding:var(--sp-3) var(--sp-4);border-top:1px solid var(--c-border-light);background:var(--c-bg-soft);border-radius:0 0 var(--radius-lg) var(--radius-lg)">
<span class="text-xs text-muted"><span style="color:var(--c-success);font-weight:var(--fw-medium)">3/3</span> 个需上传文件的段落已准备就绪 · <span style="color:var(--c-text-2)">3</span> 个自动生成</span>
<button class="btn btn-primary" onclick="startGeneration()"><i data-lucide="zap"></i>立即生成</button>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
lucide.createIcons();
// === Screen switch ===
function switchScreen(el, id) {
// If called with a single string argument, treat it as screen id
if(!id && typeof el === 'string') {
document.querySelectorAll('.topbar-tab').forEach(t=>t.classList.remove('active'));
document.querySelectorAll('.screen').forEach(s=>s.classList.remove('active'));
document.getElementById(el).classList.add('active');
return;
}
document.querySelectorAll('.topbar-tab').forEach(t=>t.classList.remove('active'));
document.querySelectorAll('.screen').forEach(s=>s.classList.remove('active'));
el.classList.add('active');
document.getElementById(id).classList.add('active');
}
// === Template list nav ===
function backToTplList() {
document.getElementById('tplList').style.display = 'flex';
document.getElementById('tplEditor').style.display = 'none';
}
function editTemplate(name) {
document.getElementById('tplList').style.display = 'none';
document.getElementById('tplEditor').style.display = 'flex';
document.getElementById('editorTplName').textContent = name;
initParaList();
selectPara(1);
}
function startNewTemplate() {
document.getElementById('tplList').style.display = 'none';
document.getElementById('tplEditor').style.display = 'flex';
document.getElementById('editorTplName').textContent = '新建模板';
alert('模拟:上传 Word 模板弹窗');
initParaList();
selectPara(1);
}
// === 3-column editor functions ===
const paraData = [
{id:1, name:'标题2025年Q1报告', badge:'manual', label:'人工编辑'},
{id:2, name:'一、主要经营指标完成情况', badge:'ai', label:'AI 生成'},
{id:3, name:'主要经营指标完成情况表', badge:'ai', label:'AI 生成'},
{id:4, name:'二、成本费用分析', badge:'ai', label:'AI 生成'},
{id:5, name:'三、存在的主要问题', badge:'ai', label:'AI 生成'},
{id:6, name:'四、下一步工作措施', badge:'ai', label:'AI 生成'},
{id:7, name:'封面信息', badge:'manual', label:'人工编辑'},
{id:8, name:'附图:各季度营收趋势图', badge:'ai', label:'AI 生成'},
];
const paraConfigs = {
1: {name:'一、主要经营指标完成情况', mode:'AI 生成', model:'Claude 3.5 Sonnet', prompt:'请根据上传的财务数据,生成经营指标完成情况章节,要求包括营业收入、利润总额等核心指标的完成值、同比变化及原因分析。', needPrompt:true, needFile:true, format:'正式报告段落', note:'需上传财务部提供的季度财务数据报表Excel格式含各指标完成值'},
2: {name:'主要经营指标完成情况表', mode:'AI 生成', model:'GPT-4o', prompt:'根据上传的各部门数据,生成指标完成情况表,包含指标名、完成值、同比、完成率、责任部门。', needPrompt:true, needFile:true, format:'表格形式', note:'需上传各部门经营数据汇总表Excel格式含指标明细'},
3: {name:'二、成本费用分析', mode:'AI 生成', model:'Claude 3.5 Sonnet', prompt:'根据财务数据生成成本费用分析内容,包括各项成本构成、同比变化及原因。', needPrompt:true, needFile:false, format:'正式报告段落', note:''},
4: {name:'三、存在的主要问题', mode:'AI 生成', model:'Claude 3.5 Sonnet', prompt:'基于经营数据和报告要求,分析当前存在的主要问题和风险。', needPrompt:true, needFile:false, format:'正式报告段落', note:''},
5: {name:'四、下一步工作措施', mode:'AI 生成', model:'Claude 3.5 Sonnet', prompt:'针对问题生成具体可执行的工作措施。', needPrompt:true, needFile:false, format:'正式报告段落', note:''},
6: {name:'封面信息', mode:'人工编辑', model:'—', prompt:'', needPrompt:false, needFile:false, format:'—', note:''},
};
function initParaList() {
let html = '';
paraData.forEach(p => {
html += '<div class="para-list-item" id="leftParaItem'+p.id+'" onclick="selectPara('+p.id+')">'
+ '<span class="pli-index">'+p.id+'</span>'
+ '<span style="flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">'+p.name+'</span>'
+ '<span class="pli-badge '+p.badge+'">'+p.label+'</span>'
+ '</div>';
});
document.getElementById('leftParaList').innerHTML = html;
}
function selectPara(id) {
// Update left list
document.querySelectorAll('.para-list-item').forEach(e => e.classList.remove('active'));
const leftItem = document.getElementById('leftParaItem'+id);
if(leftItem) leftItem.classList.add('active');
// Scroll center to paragraph
const block = document.getElementById('paraBlock'+id);
if(block) {
block.scrollIntoView({behavior:'smooth', block:'center'});
document.querySelectorAll('.para-block').forEach(b => b.classList.remove('selected'));
block.classList.add('selected');
}
// Update right panel
buildRightPanel(id);
}
function selectParaFromDoc(id) {
selectPara(id);
}
function buildRightPanel(id) {
const cfg = paraConfigs[id] || paraConfigs[1];
const isAi = cfg.mode === 'AI 生成';
document.getElementById('rightPanelTitle').textContent = '段落配置';
document.getElementById('rightParaName').textContent = '第 '+id+' 段 · '+(cfg.name||'');
const html = `
<div class="config-section">
<div class="config-section-title">段落信息</div>
<div class="config-field"><div class="cf-label">段落名称</div><div class="cf-value" style="font-weight:var(--fw-medium)">${cfg.name}</div></div>
<div class="config-field"><div class="cf-label">所处位置</div><div class="cf-value text-sm text-muted">第 ${id} 段</div></div>
</div>
<div class="config-section">
<div class="config-section-title">生成配置</div>
<div class="config-field">
<div class="cf-label">编辑方式</div>
<select class="cfg-select" onchange="onEditModeChange(this,${id})">
<option value="人工编辑" ${cfg.mode==='人工编辑'?'selected':''}>人工编辑</option>
<option value="AI 生成" ${cfg.mode==='AI 生成'?'selected':''}>AI 生成</option>
</select>
</div>
<div class="config-field" id="rmodelField${id}" style="${isAi?'':'display:none'}">
<div class="cf-label">生成模型</div>
<select class="cfg-select">
<option ${cfg.model==='Claude 3.5 Sonnet'?'selected':''}>Claude 3.5 Sonnet</option>
<option ${cfg.model==='GPT-4o'?'selected':''}>GPT-4o</option>
<option ${cfg.model==='DeepSeek-V3'?'selected':''}>DeepSeek-V3</option>
</select>
</div>
<div class="config-field" id="rformatField${id}" style="${isAi?'':'display:none'}">
<div class="cf-label">输出格式</div>
<select class="cfg-select">
<option ${cfg.format==='正式报告段落'?'selected':''}>正式报告段落</option>
<option ${cfg.format==='表格形式'?'selected':''}>表格形式</option>
<option ${cfg.format==='分条列出'?'selected':''}>分条列出</option>
<option ${cfg.format==='图表形式'?'selected':''}>图表形式</option>
</select>
</div>
<div class="config-field">
<div class="cf-label">是否需要提示词</div>
<div class="cfg-toggle" onclick="toggleSw(this)">
<div class="toggle-switch ${cfg.needPrompt?'on':''}"></div>
<span class="text-xs">${cfg.needPrompt?'是':'否'}</span>
</div>
</div>
<div class="config-field" id="rpromptField${id}" style="${cfg.needPrompt?'':'display:none'}">
<div class="cf-label">预设提示词 <span class="text-xs text-muted">(编辑模板时设置)</span></div>
<textarea class="form-textarea" style="min-height:80px;font-size:var(--fs-sm)">${cfg.prompt || '请在此输入提示词...'}</textarea>
<div class="text-xs text-muted mt-3">提示词在模板编辑时预设,生成时可确认或微调</div>
</div>
<div class="config-field">
<div class="cf-label">是否需要参考文件</div>
<div class="cfg-toggle" onclick="toggleSw(this)">
<div class="toggle-switch ${cfg.needFile?'on':''}"></div>
<span class="text-xs">${cfg.needFile?'是':'否'}</span>
</div>
</div>
<div class="config-field" id="rnoteField${id}" style="${cfg.needFile?'':'display:none'}">
<div class="cf-label">备注说明 <span class="text-xs text-muted">(执行生成时提示需上传什么文件)</span></div>
<textarea class="form-textarea" style="min-height:60px;font-size:var(--fs-sm)" placeholder="例如:需上传财务部提供的季度财务数据报表">${cfg.note || ''}</textarea>
</div>
</div>
${isAi ? `
<div id="rtestBtn${id}">
<button class="btn btn-primary btn-block" style="width:100%;justify-content:center" onclick="testParagraph(${id})">
<i data-lucide="zap" class="icon-sm"></i> 立即测试
</button>
<div class="text-xs text-muted" style="text-align:center;margin-top:var(--sp-2)">针对此段落单独测试 · 需上传附件 → 文件解析 → 请求AI → 填充预览</div>
</div>
` : `
<div style="background:var(--c-bg-soft);padding:var(--sp-3);border-radius:var(--radius);text-align:center">
<span class="text-xs text-muted">该段落为「人工编辑」,无需 AI 测试</span>
</div>
`}
`;
document.getElementById('rightPanelBody').innerHTML = html;
lucide.createIcons();
}
function onEditModeChange(sel, paraId) {
const isAi = sel.value === 'AI 生成';
document.getElementById('rmodelField'+paraId).style.display = isAi ? 'block' : 'none';
document.getElementById('rformatField'+paraId).style.display = isAi ? 'block' : 'none';
document.getElementById('rpromptField'+paraId).style.display = 'block';
const testBtn = document.getElementById('rtestBtn'+paraId);
if(testBtn) testBtn.style.display = isAi ? 'block' : 'none';
}
// === Toggle switch ===
function toggleSw(el) {
const sw = el.querySelector('.toggle-switch');
const txt = el.querySelector('.text-xs');
sw.classList.toggle('on');
if(txt) txt.textContent = sw.classList.contains('on') ? '是' : '否';
// Show/hide note field (sibling config-field with noteField id)
const noteField = el.closest('.config-field')?.nextElementSibling;
if(noteField && noteField.id && noteField.id.startsWith('noteField')) {
noteField.style.display = sw.classList.contains('on') ? 'block' : 'none';
}
}
// === Test paragraph - 3 step flow ===
function testParagraph(id) {
// Reset modal to step 1
document.getElementById('testStep1').style.display = 'block';
document.getElementById('testStep2').style.display = 'none';
document.getElementById('testStep3').style.display = 'none';
document.getElementById('testModalFooter').style.display = 'none';
document.getElementById('testUploaded').style.display = 'none';
document.getElementById('testModal').classList.add('open');
document.querySelector('#testStep1 .config-section-title span').style.background = 'var(--c-primary)';
}
function simulateUpload() {
document.querySelector('#testStep1 > div:first-child > div > div').style.display = 'none'; // hide upload box
document.getElementById('testUploaded').style.display = 'block';
lucide.createIcons();
}
function startTestStep2() {
document.getElementById('testStep1').style.display = 'none';
document.getElementById('testStep2').style.display = 'block';
document.getElementById('testModalFooter').style.display = 'none';
// Reset task icons
['tsk1','tsk2','tsk3'].forEach(id => {
const el = document.getElementById(id);
el.innerHTML = '<i data-lucide="circle" class="icon-sm"></i>';
el.style.color = 'var(--c-text-4)';
});
lucide.createIcons();
// Simulate step progression
const t1 = document.getElementById('tsk1');
const t2 = document.getElementById('tsk2');
const t3 = document.getElementById('tsk3');
const stepText = document.getElementById('testStepText');
// Step 1: File parsing (after 1.2s)
setTimeout(() => {
t1.innerHTML = '<i data-lucide="loader" class="icon-sm"></i>';
t1.style.color = 'var(--c-primary)';
stepText.textContent = '正在解析文件...';
lucide.createIcons();
}, 200);
setTimeout(() => {
t1.innerHTML = '<i data-lucide="check-circle" class="icon-sm"></i>';
t1.style.color = 'var(--c-success)';
// Step 2: AI request
t2.innerHTML = '<i data-lucide="loader" class="icon-sm"></i>';
t2.style.color = 'var(--c-primary)';
stepText.textContent = '正在请求 AI 大模型Claude 3.5 Sonnet...';
lucide.createIcons();
}, 1400);
setTimeout(() => {
t2.innerHTML = '<i data-lucide="check-circle" class="icon-sm"></i>';
t2.style.color = 'var(--c-success)';
// Step 3: Fill result
t3.innerHTML = '<i data-lucide="loader" class="icon-sm"></i>';
t3.style.color = 'var(--c-primary)';
stepText.textContent = '正在填充生成结果...';
lucide.createIcons();
}, 3200);
setTimeout(() => {
t3.innerHTML = '<i data-lucide="check-circle" class="icon-sm"></i>';
t3.style.color = 'var(--c-success)';
// Switch to step 3
document.getElementById('testStep2').style.display = 'none';
document.getElementById('testStep3').style.display = 'block';
document.getElementById('testModalFooter').style.display = 'flex';
lucide.createIcons();
}, 4800);
}
function closeTestModal() {
document.getElementById('testModal').classList.remove('open');
}
// === Model management modals ===
function openModelModal(mode, name, provider, endpoint, apikey) {
const title = document.getElementById('modelModalTitle');
const mName = document.getElementById('mName');
const mProvider = document.getElementById('mProvider');
const mFormat = document.getElementById('mFormat');
const mEndpoint = document.getElementById('mEndpoint');
const mApiKey = document.getElementById('mApiKey');
if(mode === 'add') {
title.innerHTML = '<i data-lucide="cpu" class="icon-sm" style="color:var(--c-primary)"></i> 添加模型';
mName.value = '';
mProvider.value = '';
mFormat.value = 'OpenAI';
mEndpoint.value = '';
mApiKey.value = '';
} else {
title.innerHTML = '<i data-lucide="settings" class="icon-sm" style="color:var(--c-primary)"></i> 编辑模型 - ' + name;
mName.value = name || '';
mProvider.value = provider || '';
// Guess format from provider name
if(provider && provider.toLowerCase().includes('anthropic')) mFormat.value = 'Anthropic';
else if(provider && (provider.toLowerCase().includes('openai') || provider.toLowerCase().includes('deepseek') || provider.toLowerCase().includes('阿里'))) mFormat.value = 'OpenAI';
else mFormat.value = 'OpenAI';
mEndpoint.value = endpoint || '';
mApiKey.value = apikey || '';
}
document.getElementById('modelModal').classList.add('open');
lucide.createIcons();
}
function closeModelModal() {
document.getElementById('modelModal').classList.remove('open');
}
// === Generation ===
function startGeneration() {
document.getElementById('genLeftStatus').style.display = 'block';
document.getElementById('genDoneSide').style.display = 'none';
let pct = 0;
const bar = document.getElementById('genProgressBar');
const gpText = document.getElementById('genLeftText');
const steps = [
{id:'g1', name:'一、主要经营指标完成情况'},
{id:'g2', name:'主要经营指标完成情况表'},
{id:'g3', name:'二、成本费用分析'},
{id:'g4', name:'三、存在的主要问题'},
{id:'g5', name:'四、下一步工作措施'},
{id:'g6', name:'附图:各季度营收趋势图'}
];
let currentStep = 0;
const interval = setInterval(() => {
pct += Math.floor(Math.random()*8)+3;
if(pct>=100) {
pct=100;
clearInterval(interval);
document.getElementById('genLeftStatus').style.display = 'none';
document.getElementById('genDoneSide').style.display = 'flex';
// Mark all remaining as done
for(let i=currentStep;i<steps.length;i++) {
const el = document.getElementById(steps[i].id);
el.innerHTML = '<i data-lucide="check-circle" class="icon-sm"></i>';
el.style.color = 'var(--c-success)';
}
lucide.createIcons();
return;
}
bar.style.width = pct+'%';
// Update step progress
const stepIdx = Math.floor(pct / 17);
if(stepIdx > currentStep && stepIdx < steps.length) {
currentStep = stepIdx;
// Mark previous as done
if(currentStep > 0) {
const prev = document.getElementById(steps[currentStep-1].id);
if(prev) { prev.innerHTML = '<i data-lucide="check-circle" class="icon-sm"></i>'; prev.style.color = 'var(--c-success)'; }
}
// Mark current as in progress
const cur = document.getElementById(steps[currentStep].id);
if(cur) { cur.innerHTML = '<i data-lucide="loader" class="icon-sm"></i>'; cur.style.color = 'var(--c-primary)'; }
gpText.textContent = '正在生成「'+steps[currentStep].name+'」...';
}
lucide.createIcons();
},600);
}
function goGenerate(name) {
const sel = document.querySelector('#screen-generate .form-select');
if(sel) sel.value = name;
location.href='执行生成.html';
}
function onTplSelect() {}
</script>
</body>
</html>