Add frontend function reorg design

This commit is contained in:
王鹏
2026-05-28 22:42:12 +08:00
parent 7bec983900
commit fee7c80a27
2 changed files with 1096 additions and 0 deletions

View File

@@ -0,0 +1,840 @@
<!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>

View File

@@ -0,0 +1,256 @@
# EasyCode 前台功能重组设计
## 目标
重组 `easycode-web` 前台页面的信息架构,把当前堆在 `/generate` 的生成、编辑、页面设计入口、预览入口和 AI 状态拆成更清晰的项目内工作区。
本次选择方案 B新增项目详情枢纽功能按阶段分区。
目标体验:
- 用户从首页或项目列表进入项目后,先看到项目当前进度和下一步动作。
- 创建项目、项目内编辑、页面设计、预览运行有明确边界。
- 保留现有后端接口和主要组件能力,优先做前台结构重组,不做后端重构。
## 当前问题
当前前台主链路已经完整:
```text
首页 -> 生成工作台 -> 页面设计器 -> 项目预览/运行预览
```
问题不是功能缺失,而是功能增长后页面职责没有重新分层:
- `/generate` 同时承担创建项目、AI 生成、数据库编辑、业务动作编辑、页面设计入口、预览入口。
- 用户难判断当前处于哪一步,也不容易知道下一步动作。
- 页面设计器已经独立,但工作台仍保留过多页面设计状态和入口说明。
- 预览页已经包含结构预览和运行预览,入口应该从项目交付阶段统一进入。
## 设计决策
### 路由分层
保留平台级页面:
- `/`:首页,只负责产品介绍、关键词输入和引导创建。
- `/projects`:我的项目,负责项目列表、继续编辑、删除等项目级动作。
- `/generate`:创建/继续项目入口,负责新建项目草稿、填写基础需求、恢复最近项目。
- `/source-store``/source-store/:sourceId`:源码库相关页面,保持平台级入口。
- `/profile`:个人中心。
新增项目内工作区:
- `/project/:projectId/workspace`:项目详情枢纽,承载项目内主流程。
继续保留独立工具页面:
- `/project/:projectId/page-designer`:全屏页面设计器。
- `/project/:projectId/preview`:项目结构预览、运行预览和源码下载。
### 页面职责
#### GenerateView
改造成轻量创建页。
保留:
- 项目名称。
- 需求关键词。
- 补充说明。
- 是否生成用户前台。
- 后台功能模块选择。
- 创建项目并进入工作区。
- 打开最近项目。
移出:
- 系统模块设计面板。
- 数据库设计器。
- 业务流程设计面板。
- 页面设计入口卡片。
- 预览项目动作。
- AI 任务详情和历史列表。
#### ProjectWorkspaceView
新增项目工作区,作为项目内中控台。
左侧项目导航:
- 项目概览。
- 需求与 AI。
- 系统蓝图。
- 数据模型。
- 业务动作。
- 页面设计。
- 预览交付。
右侧内容区按当前导航展示功能:
- 项目概览:项目信息、完成度、下一步动作、关键入口。
- 需求与 AI基础需求表单、AI 配额、任务状态、生成历史。
- 系统蓝图系统模块设计摘要、模块图、JSON 调整。
- 数据模型数据库设计器、ER 图、保存表结构。
- 业务动作业务流程设计摘要、JSON 调整、保存。
- 页面设计:前台/后台页面设计统计、初始化页面、进入设计器。
- 预览交付:生成项目预览、进入结构预览、进入运行预览、下载提示。
#### PageDesignerView
保持独立页面,减少工作区干扰。
工作区只提供入口和状态,真正的页面树、画布、属性面板、业务块配置继续在页面设计器内完成。
#### PreviewView
保持独立页面,继续负责:
- 后端、前台前端、后台前端项目结构。
- 文件代码预览。
- 运行预览启动、停止、日志、iframe 预览。
- 源码下载。
工作区的预览交付页只负责进入这里,并在需要时先触发生成项目。
## 前端结构
新增:
- `easycode-web/src/views/ProjectWorkspaceView.vue`
调整:
- `easycode-web/src/router/index.js`
- 增加 `/project/:projectId/workspace`
- 创建成功、项目列表继续编辑入口指向工作区。
- `easycode-web/src/views/GenerateView.vue`
- 收敛为创建页。
- 创建或更新项目后跳转工作区。
- `easycode-web/src/views/ProjectListView.vue`
- 继续编辑进入工作区。
- `easycode-web/src/components/AppHeader.vue`
- 保持平台级导航,避免把项目内阶段塞进全局导航。
优先复用现有组件:
- `AiTaskStatusPanel.vue`
- `AppBlueprintPanel.vue`
- `DatabaseDesigner.vue`
- `ErDiagramView.vue`
- `BusinessBlueprintPanel.vue`
这些组件在 `ProjectWorkspaceView` 内按阶段组合。
## 数据流
项目创建:
```text
HomeView / GenerateView
-> createProject / updateProject
-> /project/:projectId/workspace
```
项目工作区加载:
```text
ProjectWorkspaceView
-> getProject
-> getDatabase
-> listPageDesigns(frontend/admin)
-> listBusinessBlocks
-> getAiQuota
-> listGenerations
```
AI 生成:
```text
ProjectWorkspaceView
-> createAiTask(app_blueprint/database/business_blueprint)
-> polling getAiTask
-> apply result to local state
-> saveDatabase when needed
```
页面设计:
```text
ProjectWorkspaceView
-> initPageDesigns
-> /project/:projectId/page-designer?scope=frontend|admin
```
预览交付:
```text
ProjectWorkspaceView
-> saveDatabase
-> generateProject
-> /project/:projectId/preview
```
## 状态与错误处理
项目工作区统一显示:
- 项目加载失败。
- AI 任务失败,可重试。
- 数据库为空时,引导先生成或手动添加表。
- 页面设计未初始化时,引导初始化。
- 预览生成失败时,显示错误并停留在工作区。
页面级原则:
- 创建页只校验创建项目所需字段。
- 工作区按阶段给出下一步动作。
- 页面设计器离开前继续保留未保存确认。
- 预览页继续自行处理结构、文件、运行预览错误。
## 测试
前端测试重点:
- 路由包含 `/project/:projectId/workspace` 并要求登录。
- `GenerateView` 创建项目后跳转工作区。
- `ProjectListView` 继续编辑指向工作区。
- `ProjectWorkspaceView` 能加载项目、数据库、页面设计和业务块。
- 工作区能触发系统蓝图、数据库、业务动作生成。
- 工作区能进入前台/后台页面设计器。
- 工作区能生成并进入预览页。
手工验收:
1. 首页输入关键词进入创建页。
2. 创建项目后进入项目工作区。
3. 在工作区能看到项目概览和阶段导航。
4. 生成系统蓝图、数据库、业务动作。
5. 初始化前台和后台页面设计。
6. 从工作区进入页面设计器并返回。
7. 从工作区进入预览页,查看结构和运行预览。
8. 从我的项目继续编辑时进入工作区。
## 分期实施
第一阶段:
- 新增 `ProjectWorkspaceView`
- 调整路由和项目入口。
-`GenerateView` 收敛为创建页。
- 在工作区复用现有生成、数据库、业务动作、页面设计入口和预览逻辑。
第二阶段:
- 根据工作区使用情况,继续拆出更小的阶段组件。
- 优化项目概览完成度和下一步规则。
- 清理 `GenerateView` 中迁移后不再需要的状态和样式。
## 自检
- 无未定义占位项。
- 范围聚焦在前台信息架构和页面职责重组。
- 不要求后端 API 改造。
- 页面设计器和预览页继续保持独立,避免一次改动过大。
- 设计和已确认的 B 方案一致。