Files
yidaima/RuoYi-Vue/docs/mockups/frontend-function-reorg-options.html

841 lines
22 KiB
HTML
Raw Normal View History

2026-05-28 22:42:12 +08:00
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>EasyCode 前台功能重组草图</title>
<style>
* {
box-sizing: border-box;
}
body {
margin: 0;
color: #182230;
background: #f5f7fb;
font-family: Inter, "PingFang SC", "Microsoft YaHei", Arial, sans-serif;
line-height: 1.6;
}
button,
input,
textarea {
font: inherit;
}
.page {
width: min(1280px, calc(100% - 40px));
margin: 0 auto;
padding: 28px 0 42px;
}
.topbar {
display: flex;
align-items: center;
justify-content: space-between;
gap: 18px;
min-height: 64px;
padding: 0 18px;
border: 1px solid #d9e2ef;
border-radius: 8px;
background: #ffffff;
}
.brand {
display: inline-flex;
align-items: center;
gap: 10px;
font-weight: 800;
}
.brand-mark {
display: inline-grid;
width: 34px;
height: 34px;
place-items: center;
border-radius: 8px;
color: #ffffff;
background: #1d4ed8;
font-size: 13px;
}
.nav {
display: flex;
align-items: center;
gap: 14px;
color: #52657d;
font-size: 14px;
flex-wrap: wrap;
}
.pill {
display: inline-flex;
align-items: center;
min-height: 28px;
padding: 4px 9px;
border: 1px solid #d7deea;
border-radius: 8px;
color: #475467;
background: #ffffff;
font-size: 13px;
font-weight: 700;
}
.hero {
display: grid;
grid-template-columns: minmax(0, 0.95fr) minmax(360px, 1.05fr);
gap: 22px;
align-items: stretch;
margin-top: 22px;
}
.panel {
border: 1px solid #d9e2ef;
border-radius: 8px;
background: #ffffff;
}
.intro {
padding: 26px;
}
.eyebrow {
margin: 0 0 10px;
color: #1d4ed8;
font-size: 13px;
font-weight: 800;
}
h1,
h2,
h3,
p {
letter-spacing: 0;
}
h1 {
margin: 0;
color: #101828;
font-size: 34px;
line-height: 1.22;
}
h2 {
margin: 0;
color: #172033;
font-size: 22px;
line-height: 1.35;
}
h3 {
margin: 0;
color: #172033;
font-size: 17px;
line-height: 1.35;
}
.muted {
margin: 10px 0 0;
color: #667085;
}
.diagnosis {
display: grid;
gap: 12px;
padding: 18px;
}
.signal-list {
display: grid;
gap: 10px;
margin: 0;
padding: 0;
list-style: none;
}
.signal-list li {
display: grid;
grid-template-columns: 32px minmax(0, 1fr);
gap: 10px;
align-items: start;
padding: 12px;
border: 1px solid #e4eaf3;
border-radius: 8px;
background: #fbfdff;
}
.signal-no {
display: inline-grid;
width: 30px;
height: 30px;
place-items: center;
border-radius: 8px;
color: #ffffff;
background: #475467;
font-size: 12px;
font-weight: 800;
}
.section {
margin-top: 24px;
}
.section-head {
display: flex;
align-items: end;
justify-content: space-between;
gap: 16px;
margin-bottom: 14px;
}
.options {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 16px;
}
.option-card {
display: grid;
grid-template-rows: auto auto auto 1fr auto;
gap: 13px;
min-height: 510px;
padding: 18px;
border: 2px solid #dbe3ef;
border-radius: 8px;
background: #ffffff;
cursor: pointer;
}
.option-card:focus,
.option-card:hover,
.option-card.selected {
border-color: #1d4ed8;
outline: none;
}
.option-top {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
}
.letter {
display: inline-grid;
width: 34px;
height: 34px;
place-items: center;
border-radius: 8px;
color: #ffffff;
background: #1d4ed8;
font-weight: 800;
}
.recommend {
color: #067647;
background: #ecfdf3;
border-color: #abefc6;
}
.option-card p {
margin: 0;
color: #667085;
}
.mini-browser {
display: grid;
gap: 8px;
padding: 12px;
border: 1px solid #d8e0eb;
border-radius: 8px;
background: #f8fafc;
}
.browser-bar {
display: flex;
gap: 5px;
}
.dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: #98a2b3;
}
.wire-layout {
display: grid;
gap: 8px;
min-height: 250px;
}
.wire-row,
.wire-nav,
.wire-box,
.wire-main,
.wire-side,
.wire-stage,
.wire-toolbar {
border: 1px solid #c9d4e5;
border-radius: 6px;
background: #ffffff;
}
.wire-nav {
display: flex;
align-items: center;
justify-content: space-between;
min-height: 34px;
padding: 6px 8px;
color: #52657d;
font-size: 12px;
font-weight: 700;
}
.wire-toolbar {
min-height: 36px;
padding: 7px;
color: #52657d;
font-size: 12px;
}
.wire-grid-2 {
display: grid;
grid-template-columns: 130px minmax(0, 1fr);
gap: 8px;
min-height: 170px;
}
.wire-side {
padding: 8px;
}
.wire-main {
display: grid;
gap: 8px;
padding: 8px;
}
.wire-step {
min-height: 32px;
padding: 7px 8px;
border: 1px solid #d8e0eb;
border-radius: 6px;
background: #f8fafc;
color: #475467;
font-size: 12px;
font-weight: 700;
}
.wire-step.active {
border-color: #1d4ed8;
background: #eff6ff;
color: #1d4ed8;
}
.wire-card-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 8px;
}
.wire-card {
min-height: 58px;
border: 1px solid #d8e0eb;
border-radius: 6px;
background: #ffffff;
}
.option-notes {
display: grid;
gap: 8px;
margin: 0;
padding: 0;
list-style: none;
color: #475467;
font-size: 14px;
}
.option-notes li {
padding-left: 12px;
border-left: 3px solid #d9e2ef;
}
.flow-map {
display: grid;
grid-template-columns: 220px minmax(0, 1fr);
gap: 16px;
padding: 18px;
}
.left-nav-demo {
display: grid;
gap: 8px;
align-content: start;
padding: 14px;
border: 1px solid #d9e2ef;
border-radius: 8px;
background: #f8fafc;
}
.left-nav-demo strong {
margin-bottom: 2px;
}
.nav-item {
display: grid;
grid-template-columns: 28px minmax(0, 1fr);
gap: 8px;
align-items: center;
min-height: 38px;
padding: 7px 9px;
border: 1px solid transparent;
border-radius: 8px;
color: #52657d;
font-size: 14px;
font-weight: 700;
}
.nav-item.active {
border-color: #bfdbfe;
color: #1d4ed8;
background: #eff6ff;
}
.nav-icon {
display: inline-grid;
width: 28px;
height: 28px;
place-items: center;
border-radius: 7px;
color: #ffffff;
background: #475467;
font-size: 12px;
font-weight: 800;
}
.active .nav-icon {
background: #1d4ed8;
}
.stage-demo {
display: grid;
gap: 14px;
}
.stage-toolbar {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
padding: 14px;
border: 1px solid #d9e2ef;
border-radius: 8px;
background: #ffffff;
}
.stage-actions {
display: flex;
gap: 8px;
flex-wrap: wrap;
}
.button {
display: inline-flex;
align-items: center;
justify-content: center;
min-height: 32px;
padding: 6px 12px;
border: 1px solid #d0d5dd;
border-radius: 7px;
color: #344054;
background: #ffffff;
font-size: 13px;
font-weight: 700;
}
.button.primary {
border-color: #1d4ed8;
color: #ffffff;
background: #1d4ed8;
}
.stage-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 12px;
}
.stage-card {
display: grid;
gap: 8px;
min-height: 120px;
padding: 14px;
border: 1px solid #d9e2ef;
border-radius: 8px;
background: #ffffff;
}
.stage-card span {
color: #667085;
font-size: 13px;
}
.decision {
display: grid;
gap: 12px;
padding: 18px;
border: 1px solid #bfdbfe;
border-radius: 8px;
background: #eff6ff;
}
.decision strong {
color: #1e40af;
}
.route-list {
display: grid;
gap: 9px;
margin: 0;
padding: 0;
list-style: none;
color: #475467;
}
.route-list li {
display: grid;
grid-template-columns: 150px minmax(0, 1fr);
gap: 10px;
padding: 10px 12px;
border: 1px solid #d9e2ef;
border-radius: 8px;
background: #ffffff;
}
code {
color: #1d4ed8;
font-family: Consolas, "Courier New", monospace;
font-size: 13px;
font-weight: 700;
}
.selected-note {
display: none;
margin-top: 12px;
padding: 10px 12px;
border: 1px solid #abefc6;
border-radius: 8px;
color: #067647;
background: #ecfdf3;
font-weight: 700;
}
.selected-note.show {
display: block;
}
@media (max-width: 1080px) {
.hero,
.options,
.flow-map,
.stage-grid {
grid-template-columns: 1fr;
}
.option-card {
min-height: auto;
}
}
@media (max-width: 680px) {
.page {
width: min(100% - 24px, 1280px);
padding-top: 14px;
}
.topbar,
.section-head,
.stage-toolbar {
align-items: stretch;
flex-direction: column;
}
h1 {
font-size: 26px;
}
.route-list li {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<div class="page">
<header class="topbar">
<div class="brand">
<span class="brand-mark">EC</span>
<span>EasyCode 前台功能重组</span>
</div>
<nav class="nav">
<span>首页</span>
<span>源码库</span>
<span>我的项目</span>
<span>项目工作区</span>
<span>预览运行</span>
</nav>
</header>
<section class="hero">
<div class="panel intro">
<p class="eyebrow">第一版梳理结论</p>
<h1>乱感不是功能缺,而是所有阶段都挤在同一个工作台里</h1>
<p class="muted">
当前链路已经很强:需求、系统模块、数据库、业务动作、页面设计、预览运行都有了。
主要问题是导航层级和页面职责没有跟上功能增长,用户进入后不知道“现在在哪一步、下一步做什么、哪些是高级编辑”。
</p>
</div>
<aside class="panel diagnosis">
<h2>需要整理的三个点</h2>
<ul class="signal-list">
<li>
<span class="signal-no">1</span>
<div>
<strong>入口层级混在一起</strong>
<p class="muted">首页、工作台、项目列表、页面设计器、预览页都能跳转,但缺少一个项目级中心。</p>
</div>
</li>
<li>
<span class="signal-no">2</span>
<div>
<strong>生成动作和编辑动作混在一起</strong>
<p class="muted">工作台里既有“生成系统模块”,又有“编辑数据库”,还挂着页面设计入口和 AI 状态。</p>
</div>
</li>
<li>
<span class="signal-no">3</span>
<div>
<strong>页面设计器正在变成第二个工作台</strong>
<p class="muted">前台、后台、菜单、业务块、字段、动作、JSON 都在一个三栏里,需要更明确的模式边界。</p>
</div>
</li>
</ul>
</aside>
</section>
<section class="section">
<div class="section-head">
<div>
<p class="eyebrow">选择一个重组方向</p>
<h2>三种方案,从小改到重构信息架构</h2>
</div>
<span class="pill">点击卡片会高亮,回到聊天回复 A/B/C</span>
</div>
<div class="options" id="options">
<article class="option-card" tabindex="0" data-choice="A">
<div class="option-top">
<span class="letter">A</span>
<span class="pill">小改动</span>
</div>
<h3>保留现有页面,工作台改成步骤式</h3>
<p>把 `/generate` 清成一条纵向流程,顶部固定进度条,当前阶段只展示一个主操作区。</p>
<div class="mini-browser">
<div class="browser-bar"><span class="dot"></span><span class="dot"></span><span class="dot"></span></div>
<div class="wire-layout">
<div class="wire-nav">项目生成工作台 <span>保存草稿 / 预览</span></div>
<div class="wire-toolbar">需求 -> 系统模块 -> 数据库 -> 业务流程 -> 页面设计 -> 预览</div>
<div class="wire-grid-2">
<aside class="wire-side">
<div class="wire-step active">当前:数据库</div>
<div class="wire-step">页面设计</div>
<div class="wire-step">预览项目</div>
</aside>
<main class="wire-main">
<div class="wire-card"></div>
<div class="wire-card"></div>
<div class="wire-card"></div>
</main>
</div>
</div>
</div>
<ul class="option-notes">
<li>开发成本最低,能快速降低“堆在一起”的感觉。</li>
<li>适合先救急,但项目越来越大后仍可能再次拥挤。</li>
</ul>
</article>
<article class="option-card selected" tabindex="0" data-choice="B">
<div class="option-top">
<span class="letter">B</span>
<span class="pill recommend">推荐</span>
</div>
<h3>新增项目详情枢纽,功能按阶段分区</h3>
<p>把 `/generate` 变成“创建/继续项目”的入口,把每个项目放进 `/project/:id/workspace` 统一管理。</p>
<div class="mini-browser">
<div class="browser-bar"><span class="dot"></span><span class="dot"></span><span class="dot"></span></div>
<div class="wire-layout">
<div class="wire-nav">客户管理系统 <span>运行预览 / 下载</span></div>
<div class="wire-grid-2">
<aside class="wire-side">
<div class="wire-step active">概览</div>
<div class="wire-step">需求与 AI</div>
<div class="wire-step">系统蓝图</div>
<div class="wire-step">数据模型</div>
<div class="wire-step">页面设计</div>
</aside>
<main class="wire-main">
<div class="wire-card-grid">
<div class="wire-card"></div>
<div class="wire-card"></div>
<div class="wire-card"></div>
<div class="wire-card"></div>
</div>
<div class="wire-card"></div>
</main>
</div>
</div>
</div>
<ul class="option-notes">
<li>最适合当前功能规模,后续业务块、模板市场、运行日志都能自然加进去。</li>
<li>改动中等,需要调整路由和若干页面职责,但不是推倒重写。</li>
</ul>
</article>
<article class="option-card" tabindex="0" data-choice="C">
<div class="option-top">
<span class="letter">C</span>
<span class="pill">设计器优先</span>
</div>
<h3>把页面设计器作为主舞台</h3>
<p>项目打开后直接进入设计器,数据库、业务动作、业务块作为左侧资源和右侧配置。</p>
<div class="mini-browser">
<div class="browser-bar"><span class="dot"></span><span class="dot"></span><span class="dot"></span></div>
<div class="wire-layout">
<div class="wire-nav">页面设计器 <span>保存 / 预览</span></div>
<div class="wire-grid-2">
<aside class="wire-side">
<div class="wire-step active">页面树</div>
<div class="wire-step">数据表</div>
<div class="wire-step">业务动作</div>
<div class="wire-step">业务块</div>
</aside>
<main class="wire-main">
<div class="wire-card"></div>
<div class="wire-card-grid">
<div class="wire-card"></div>
<div class="wire-card"></div>
</div>
<div class="wire-card"></div>
</main>
</div>
</div>
</div>
<ul class="option-notes">
<li>页面搭建体验会最强,适合把产品定位成低代码设计工具。</li>
<li>会弱化“从需求生成项目”的主线,改动和认知成本最大。</li>
</ul>
</article>
</div>
<div id="selectedNote" class="selected-note show">当前建议选择 B项目详情枢纽。它能保住生成主线也能容纳越来越多的设计能力。</div>
</section>
<section class="section panel">
<div class="flow-map">
<aside class="left-nav-demo">
<strong>推荐 B 的项目级导航</strong>
<div class="nav-item active"><span class="nav-icon">01</span><span>项目概览</span></div>
<div class="nav-item"><span class="nav-icon">02</span><span>需求与 AI 任务</span></div>
<div class="nav-item"><span class="nav-icon">03</span><span>系统蓝图</span></div>
<div class="nav-item"><span class="nav-icon">04</span><span>数据模型</span></div>
<div class="nav-item"><span class="nav-icon">05</span><span>业务动作</span></div>
<div class="nav-item"><span class="nav-icon">06</span><span>页面设计</span></div>
<div class="nav-item"><span class="nav-icon">07</span><span>预览运行</span></div>
</aside>
<main class="stage-demo">
<div class="stage-toolbar">
<div>
<h2>项目概览作为“下一步”中控台</h2>
<p class="muted">用户不用记住入口,只看当前完成度和下一步动作。</p>
</div>
<div class="stage-actions">
<span class="button">保存草稿</span>
<span class="button primary">继续下一步</span>
</div>
</div>
<div class="stage-grid">
<article class="stage-card">
<h3>需求完整度</h3>
<span>项目名称、关键词、补充说明、模块选择。</span>
</article>
<article class="stage-card">
<h3>生成状态</h3>
<span>系统蓝图、数据库、业务动作、页面设计的任务状态。</span>
</article>
<article class="stage-card">
<h3>交付出口</h3>
<span>项目结构预览、运行预览、源码下载。</span>
</article>
</div>
<div class="decision">
<strong>推荐落地方式</strong>
<p class="muted">
第一阶段先不大改后端:保留现有 API 和组件,把页面职责重排。
`GenerateView` 缩成创建/载入入口;新增 `ProjectWorkspaceView` 承接当前工作台的主流程;
`PageDesignerView` 和 `PreviewView` 继续独立全屏,但由项目工作区统一进入。
</p>
</div>
</main>
</div>
</section>
<section class="section panel intro">
<p class="eyebrow">路由层级草案</p>
<h2>把“平台入口”和“项目内工作”分开</h2>
<ul class="route-list">
<li><code>/</code><span>首页,只做产品说明、关键词输入、进入创建流程。</span></li>
<li><code>/projects</code><span>我的项目,列表、搜索、继续编辑、复制项目、删除。</span></li>
<li><code>/generate</code><span>创建项目/选择模板/恢复最近项目,不再承载所有编辑器。</span></li>
<li><code>/project/:id/workspace</code><span>项目详情枢纽,承载需求、蓝图、数据库、业务动作、页面设计入口和进度。</span></li>
<li><code>/project/:id/page-designer</code><span>全屏页面设计器,专注页面树、画布、属性面板、业务块。</span></li>
<li><code>/project/:id/preview</code><span>项目结构、代码预览、运行预览、下载源码。</span></li>
</ul>
</section>
</div>
<script>
const cards = document.querySelectorAll(".option-card");
const selectedNote = document.getElementById("selectedNote");
function selectCard(card) {
cards.forEach((item) => item.classList.remove("selected"));
card.classList.add("selected");
const choice = card.dataset.choice;
const labels = {
A: "已选择 A保留现有页面工作台改成步骤式。适合快速收拾当前页面。",
B: "已选择 B新增项目详情枢纽。推荐用于当前功能规模和后续扩展。",
C: "已选择 C页面设计器作为主舞台。适合转向低代码设计工具体验。"
};
selectedNote.textContent = labels[choice] || "";
selectedNote.classList.add("show");
location.hash = choice;
}
cards.forEach((card) => {
card.addEventListener("click", () => selectCard(card));
card.addEventListener("keydown", (event) => {
if (event.key === "Enter" || event.key === " ") {
event.preventDefault();
selectCard(card);
}
});
});
</script>
</body>
</html>