727 lines
49 KiB
HTML
727 lines
49 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>执行生成 · 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> |