# Frontend Page Designer Design

## Goal

Build a user-facing frontend page designer inside the EasyCode generation workbench. The designer lets a user configure generated portal pages visually, then stores the result in an independent `front_project_page_design` table so project generation can produce Vue frontend pages from the saved layout.

## Scope

The first phase covers generated user-facing frontend pages only.

Included:

- Initialize page design records from confirmed `appBlueprint.frontendPages`.
- Show a menu/page tree for frontend pages.
- Edit page metadata, bound table, route path, page type, layout regions, displayed fields, query fields, form fields, table row actions, and toolbar actions.
- Save page design records independently from `appBlueprint`.
- Use saved page designs during generated project preview and download.
- Keep existing generation behavior as a fallback when no page design exists.

Excluded from phase one:

- RuoYi admin page visual design.
- Free-form nested low-code containers.
- Runtime page rendering inside EasyCode beyond lightweight preview/wireframe.
- Page design version history beyond a simple `version` field for optimistic locking.
- Multi-user collaborative editing.

## Current Context

The project already has these concepts:

- `AppBlueprintDesign` contains roles, `frontendMenus`, `adminMenus`, and `frontendPages`.
- `AppPageDesign` names generated frontend pages with `code`, `menuCode`, `path`, `pageType`, and `tableName`.
- `BusinessActionDesign.uiBindings` can attach generated business actions to frontend page slots.
- `GenerateView.vue` already orchestrates app blueprint generation, database design, business blueprint generation, and preview generation.
- Qing templates already generate a Vue frontend shell and table-oriented frontend pages.

The new designer should sit between app blueprint/database design and project preview generation.

## Architecture

Add a persistent page design layer:

```text
appBlueprint.frontendPages
        |
        v
front_project_page_design
        |
        v
FrontendPageDesigner.vue
        |
        v
FrontProjectConverter / GenProject
        |
        v
Velocity templates
```

`appBlueprint` remains the source for application structure: menus, route entry points, and page codes. `front_project_page_design` becomes the source for how each generated frontend page is composed.

The generator reads page designs by project ID and exposes them to Velocity alongside tables, frontend pages, and business actions. If a page has no saved design, the generator builds a default design from the table columns and existing table CRUD flags.

## Database

Create `front_project_page_design`.

Columns:

- `design_id` bigint primary key.
- `project_id` bigint, required.
- `user_id` bigint, required.
- `page_code` varchar(100), required. Matches `AppPageDesign.code`.
- `menu_code` varchar(100), optional. Matches `AppMenuDesign.code`.
- `page_name` varchar(100), required.
- `route_path` varchar(255), required.
- `page_type` varchar(50), required. Supported values: `list`, `detail`, `form`, `current_user_list`.
- `table_name` varchar(100), required for table-backed pages.
- `layout_json` longtext, required.
- `action_json` longtext, optional.
- `status` char(1), default `0`.
- `version` int, default `1`.
- RuoYi audit columns: `create_by`, `create_time`, `update_by`, `update_time`, `remark`.

Indexes:

- Unique key on `(project_id, page_code)`.
- Normal index on `(project_id, menu_code)`.
- Normal index on `(project_id, table_name)`.

Deletion behavior:

- Deleting a project deletes its page designs.
- Regenerating app blueprint does not automatically delete existing designs. The user can run initialization again to add missing designs and mark orphaned designs as detached.

## Page Design DSL

`layout_json` stores layout composition:

```json
{
  "canvas": "frontend-list-v1",
  "regions": [
    {
      "id": "query",
      "type": "query",
      "fields": ["title", "category", "status"]
    },
    {
      "id": "toolbar",
      "type": "toolbar",
      "actions": ["create", "export", "batchDelete"]
    },
    {
      "id": "table",
      "type": "table",
      "fields": ["cover", "title", "author", "stock", "status"],
      "rowActions": ["view", "edit", "delete"]
    },
    {
      "id": "form",
      "type": "dialogForm",
      "fields": ["title", "author", "category", "price"]
    }
  ]
}
```

`action_json` stores button/action configuration that is local to the page:

```json
{
  "toolbarActions": [
    { "code": "create", "label": "Create", "type": "primary", "builtin": true },
    { "code": "export", "label": "Export", "type": "default", "builtin": true }
  ],
  "rowActions": [
    { "code": "view", "label": "View", "builtin": true },
    { "code": "borrow", "label": "Borrow", "businessActionCode": "borrow_book" }
  ]
}
```

Field names in `layout_json` reference `DatabaseColumnDesign.javaField`. The backend accepts database column names too, normalizes them to Java field names, and rejects unknown fields.

## Backend API

Add routes under `FrontProjectController`:

- `GET /front/project/{projectId}/page-designs`
  Returns all active page designs for the project, sorted by menu/page order.

- `POST /front/project/{projectId}/page-designs/init`
  Creates missing page design records from `appBlueprint.frontendPages`. Existing records are preserved. Detached records are returned so the UI can show them separately.

- `GET /front/project/{projectId}/page-designs/{designId}`
  Returns one page design with normalized layout and field metadata.

- `PUT /front/project/{projectId}/page-designs/{designId}`
  Validates and saves metadata, `layout_json`, `action_json`, and `version`.

Validation rules:

- The project must belong to the current frontend user.
- `page_code` must be unique per project.
- `page_type` must be one of the supported values.
- `table_name` must exist in the saved database design when the page type is table-backed.
- Region IDs must be unique inside a page.
- Region types must be supported by the selected page type.
- Fields must exist in the bound table.
- Built-in actions must be allowed by table operation flags.
- `businessActionCode` must exist in saved business blueprint when present.
- Save rejects stale `version` values.

## Frontend UI

Add `FrontendPageDesigner.vue` and integrate it into `GenerateView.vue` after database design and before business blueprint/preview.

Layout:

- Left panel: frontend menu/page tree from page designs, grouped by menu and child pages.
- Center panel: canvas with fixed first-phase regions based on page type.
- Right panel: property editor for page metadata, bound table, fields, and actions.
- Bottom toolbar: initialize from blueprint, save, reset to default, and show JSON.

First-phase interactions:

- Select a page.
- Add missing page designs from blueprint.
- Reorder fields inside query/table/form regions.
- Toggle fields visible/hidden.
- Configure action labels and placement.
- Bind business actions already present in `businessActions.uiBindings`.
- View JSON for debugging and advanced edits.

Drag-and-drop is scoped to field/action ordering in phase one. The region list itself is fixed by page type to keep templates deterministic.

## Generation

Extend project conversion/generation so `GenProject` includes page designs.

Generation behavior:

- `FrontProjectConverter` loads saved page designs for the project.
- `GenProjectServiceImpl` exposes page designs to Velocity context.
- Qing frontend templates resolve the current table page design by page code or table name.
- If a page design exists, templates render query fields, table columns, form fields, toolbar actions, and row actions from `layout_json` and `action_json`.
- If no page design exists, templates use current behavior based on table columns and operation flags.

This keeps old projects compatible and lets users opt into page design gradually.

## Error Handling

UI behavior:

- If initialization cannot find `frontendPages`, show a warning asking the user to generate or apply the system module blueprint first.
- If no database tables exist, allow menu/page metadata editing but disable table field regions.
- If a bound table was deleted, mark the page as needing repair and block preview generation until fixed.
- If save returns a stale version error, ask the user to reload the page design before saving again.

Backend behavior:

- Return clear `ServiceException` messages for invalid field, table, page type, action, or stale version errors.
- Do not mutate existing page designs when initialization fails midway.

## Tests

Backend tests:

- SQL schema script includes `front_project_page_design`.
- Mapper inserts, updates, lists, and deletes project page designs.
- Initialization creates designs from `frontendPages` and preserves existing records.
- Validation rejects unknown fields, unknown tables, invalid page types, and stale versions.
- Project deletion removes page designs.
- Generator uses saved page design when present and falls back when absent.

Frontend tests:

- Designer initializes and renders page tree from API data.
- Field visibility and ordering update `layout_json`.
- Saving sends normalized payload with `version`.
- Generate page disables preview when page design validation reports repair-required state.

Template tests:

- Qing `index.vue.vm` renders query fields, table columns, form fields, toolbar actions, and row actions from page design.
- Existing template output remains valid when no page design exists.

## Rollout

1. Add database script and backend domain/mapper/service/API.
2. Add frontend API functions and `FrontendPageDesigner.vue`.
3. Integrate the designer into `GenerateView.vue`.
4. Extend conversion and template generation.
5. Add tests around validation and template output.
6. Keep existing JSON editor paths available for app and business blueprints.
