enterprise-saa-s-dashboard-.../.kiro/steering/frontend.md

28 KiB
Raw Blame History

前端技术规范

运行环境

  • Node.js >= 20.9
  • npm >= 10.x

项目结构

Monorepo 架构

  • 包管理npm workspaces + Turborepo 2.0
  • 项目根目录:geo_bsp/
  • 共享包命名空间:@geomative/*

应用划分

apps/
├── web/          # 公开网站 — Next.js 16 (Turbopack),端口 3000(国际站) / 3002(中文站)
├── admin/        # 后台管理系统 — Vite 6 + React 19 + React Router DOM 7端口 3003
└── api/          # 后端 API 服务 — Hono端口 3001

packages/
├── types/        # 共享 TypeScript 类型定义 (@geomative/types)
├── ui/           # 共享 UI 组件库 (@geomative/ui)
├── utils/        # 共享工具函数 (@geomative/utils)
└── config/       # 共享配置 — Tailwind、ESLint、Prettier、TSConfig (@geomative/config)

共享包依赖方向

config -> types -> utils -> ui -> apps/*
  • 禁止循环依赖
  • types 不依赖 ui
  • utils 不依赖 ui
  • ui 可依赖 typesutils

技术栈

类别 技术 版本
前端框架 Next.js (App Router) 16
后台管理 Vite + React Router DOM 6 / 7
UI 库 React 19
样式方案 Tailwind CSS 3.4
类型系统 TypeScript 5.0+
服务端状态 TanStack React Query API 数据获取、缓存、同步
客户端状态 Zustand 全局 UI 状态、认证状态、权限缓存(仅 admin
表单处理 React Hook Form + Zod -
富文本编辑 Tiptap -
国际化 next-intl 4.9
认证 JWT + RBAC -

apps/web — 公开网站

路由结构App Router

app/
├── page.tsx                     # 首页
├── layout.tsx                   # 根布局(国际化)
├── globals.css                  # 全局样式
│
├── about/                       # 关于我们
│   ├── company/                 #   公司介绍
│   ├── history/                 #   发展历程
│   ├── certifications/          #   资质认证
│   ├── partners/                #   合作伙伴
│   ├── dealers/                 #   经销商
│   └── contact/                 #   联系我们
│
├── products/                    # 产品中心
│   ├── [category]/              #   产品分类
│   └── [category]/[slug]/       #   产品详情
│
├── solutions/                   # 解决方案
│   ├── page.tsx                 #   方案总览
│   └── [slug]/                  #   方案详情
│
├── academy/                     # 技术学院
│   ├── product-operation/       #   产品操作
│   ├── case-library/            #   案例库
│   ├── geophysical-knowledge/   #   物探知识
│   └── certification/           #   认证培训
│
├── support/                     # 技术支持
│   ├── knowledge-base/          #   知识库
│   ├── faq/                     #   FAQ
│   ├── downloads/               #   下载中心
│   ├── software-updates/        #   软件更新
│   ├── after-sales/             #   售后服务
│   └── warranty/                #   保修政策
│
├── community/                   # 社区动态
├── geometa/                     # GeoMeta 平台
├── configurator/                # 报价配置器
├── cases/[slug]/                # 案例详情
├── pages/[slug]/                # 动态页面
├── privacy-policy/              # 隐私政策
└── terms-of-use/                # 使用条款

关键配置

  • ISR 策略:首页 30 分钟,产品页 1 小时
  • 动态路由参数为 Promise 类型:params: Promise<{ slug: string }>
  • 开发模式使用 --turbopack 标志
  • 多语言:中文站无前缀,国际站 /en 前缀

apps/admin — 后台管理系统

当前架构Vite + React Router

Admin 使用 Vite 6 + React 19 + React Router DOM 7非 Next.js。路由通过 createBrowserRouter 配置,所有页面使用 lazy() 懒加载实现代码分割。

apps/admin/src/
├── components/
│   ├── editor/                  # Tiptap 富文本编辑器
│   ├── help/                    # 帮助系统组件
│   ├── navigation/              # 导航管理组件
│   ├── seo/                     # SEO 管理组件
│   └── structured-editors/      # 结构化页面编辑器
├── data/help/                   # 帮助文档数据
├── hooks/                       # 自定义 Hooks
├── lib/
│   ├── auth.ts                  # JWT Token 管理
│   ├── api-client.ts            # API 客户端(自动刷新 Token
│   ├── help-utils.ts            # 帮助工具
│   └── utils.ts                 # 通用工具
├── pages/                       # 页面组件(全部懒加载)
├── providers/
│   ├── auth-provider.tsx        # 认证上下文(将迁移至 useAuthStore
│   └── query-provider.tsx       # React Query Provider
├── stores/                      # Zustand 全局状态管理
│   ├── useAuthStore.ts          # 认证状态(替代 AuthProvider Context
│   ├── useUIStore.ts            # 全局 UI 状态(侧边栏折叠、全局 loading持久化
│   ├── useLocaleStore.ts        # 编辑器语言偏好(持久化)
│   └── usePermissionStore.ts    # 权限数据缓存(为细粒度权限矩阵预留)
└── router/
    ├── index.tsx                # 路由配置createBrowserRouter
    ├── AppRouter.tsx            # 路由容器
    ├── DashboardLayout.tsx      # 仪表盘布局(侧边栏 + 内容区)
    ├── AuthLayout.tsx           # 登录页布局
    └── AuthGuard.tsx            # 路由守卫JWT 认证检查)

当前路由结构

/login                           # 登录页AuthLayout
/                                # 仪表盘首页AuthGuard 保护)
/navigation                      # 导航管理
/navigation/:menuId              # 菜单分支列表
/navigation/:menuId/:branchId    # 子分支列表
/navigation/:menuId/:branchId/sub/:subBranchId  # 子分支详情
/pages                           # 页面列表
/pages/:pageId                   # 页面编辑器
/pages/fixed/:slug               # 固定页面编辑器
/content                         # 内容管理首页
/content/events                  # 活动管理
/content/news                    # 新闻管理
/content/reveals                 # 发布管理
/downloads                       # 下载资源列表
/downloads/categories            # 下载分类管理
/downloads/:id                   # 下载资源编辑器
/analytics                       # 数据分析
/permissions                     # 权限管理
/settings                        # 系统设置
/about-me                        # 个人信息
/manual                          # 使用手册
/help/:pageId                    # 帮助详情

当前侧边栏菜单

导航管理    /navigation        module: navigation
页面管理    /pages             module: pages
内容管理    /content           module: content
权限管理    /permissions       module: permissions
系统设置    /settings          module: settings
使用手册    /manual            module: settings
About Me    /about-me          module: settings

多模块演进计划

Admin 将从当前单一 CMS 后台演进为统一企业管理平台,新增设备管理、报价管理、运输管理等模块。详见 docNew/12-Admin多模块架构设计.md

目标目录结构(演进后):

app/(dashboard)/
├── layout.tsx                  # 统一布局,侧边栏按权限动态渲染
├── (cms)/                      # 官网管理模块
│   ├── navigation/             #   导航管理
│   ├── pages/                  #   页面管理
│   ├── content/                #   内容管理
│   ├── downloads/              #   下载资源
│   └── seo/                    # SEO 管理
├── (devices)/                  # 设备管理模块(新增)
│   ├── list/                   #   设备列表
│   ├── [id]/                   #   设备详情
│   ├── maintenance/            #   维护记录
│   └── categories/             #   设备分类
├── (quotations)/               # 报价系统模块(新增)
│   ├── list/                   #   报价列表
│   ├── create/                 #   新建报价
│   ├── [id]/                   #   报价详情
│   └── templates/              #   报价模板
├── (shipping)/                 # 运输管理模块(新增)
│   ├── orders/                 #   运输工单
│   ├── tracking/               #   物流追踪
│   └── logistics/              #   物流商管理
└── (system)/                   # 系统管理(跨模块)
    ├── users/                  #   用户管理
    ├── roles/                  #   角色管理 + 权限矩阵配置
    ├── locales/                #   语言设置
    └── settings/               #   系统配置

目标侧边栏分组(按权限动态渲染):

官网管理
├── 导航管理
├── 页面管理
├── 内容管理
└── 下载资源

设备管理(新增)
├── 设备列表
├── 维护记录
└── 设备分类

报价管理(新增)
├── 报价列表
├── 新建报价
└── 报价模板

运输管理(新增)
├── 运输工单
├── 物流追踪
└── 物流商管理

系统设置
├── 用户管理
├── 角色权限
├── 语言设置
└── 系统配置

模块间隔离原则:

  • 路由隔离:每个模块独立路由分组 (module-name)/
  • 组件隔离:模块专用组件放模块目录内,跨模块复用的提取到 packages/ui
  • API 隔离:每个模块独立 API namespace/admin/devices/*
  • 类型隔离:每个模块独立类型文件,通过 packages/types 统一导出
  • 状态隔离React Query key 使用模块前缀(如 ['devices', 'list']Zustand store 按职责拆分不按模块拆分
  • 禁止跨模块直接引用,必须通过共享包通信

API 路由规划

/admin/auth/*              # 认证(现有)
/admin/navigation/*        # 导航管理(现有)
/admin/pages/*             # 页面管理(现有)
/admin/content/*           # 内容管理(现有)
/admin/analytics/*         # 数据分析(现有)
/admin/downloads/*         # 下载资源(现有)
/admin/users/*             # 用户管理(现有)

/admin/devices/*           # 设备管理(新增)
/admin/quotations/*        # 报价管理(新增)
/admin/shipping/*          # 运输管理(新增)
/admin/permissions/*       # 权限矩阵管理(新增)

编码规范

命名规范

文件命名

  • 组件文件PascalCaseButton.tsxHeroCarousel.tsx
  • 工具/钩子文件camelCaseuseAuth.tsfetchNavigation.ts
  • 类型文件camelCasemodels.tscms.ts
  • 样式文件kebab-caseglobals.css
  • 配置文件kebab-casetailwind.config.tsnext.config.ts
  • 页面目录kebab-caseproducts/solutions/tech-academy/
  • 测试文件:被测文件名 + .test.ts(x),如 Button.test.tsx

代码命名

  • 组件名PascalCaseLayoutShellHomeHero
  • 函数/变量名camelCasefetchNavigationactiveLocale
  • 常量UPPER_SNAKE_CASEMAX_RETRIESDEFAULT_LOCALE
  • 类型/接口名PascalCaseNavigationItemPageContent
  • 枚举值PascalCaseButtonVariant.Primary
  • 自定义 Hookuse 前缀,如 useAuthuseTranslations
  • 事件处理函数:handle 前缀,如 handleSubmithandleClick
  • 布尔变量/属性:is/has/should 前缀,如 isLoadinghasError

类型命名后缀约定

  • API 响应类型:XxxResponse,如 ProductsResponse
  • API 请求参数:XxxRequest,如 CreatePageRequest
  • Props 类型:XxxProps,如 ButtonProps
  • 状态类型:XxxState,如 FormState
  • 枚举类型:无后缀,如 LocaleButtonVariant

导入规范

导入顺序

// 1. React / Next.js 核心模块
import { useState, useEffect } from 'react';
import { NextRequest } from 'next/server';

// 2. 第三方库
import { useTranslations } from 'next-intl';
import { useForm } from 'react-hook-form';

// 3. 共享包 (@geomative/*)
import { NavigationItem, Product } from '@geomative/types';
import { Button, Card } from '@geomative/ui';

// 4. 应用内部模块(使用路径别名)
import { apiClient } from '@/lib/api';
import { AuthProvider } from '@/providers/auth-provider';

// 5. 相对路径导入
import { LayoutClientShell } from './components/LayoutClientShell';
import { fetchNavigation } from '../lib/navigation';

// 6. 类型导入(使用 type 关键字)
import type { Metadata } from 'next';

路径别名

  • apps/web:使用 @/ 前缀映射到 src/ 或根目录
  • apps/admin:使用 @/ 前缀映射到 src/
  • 共享包:使用 @geomative/* 命名空间

导出规范

  • 优先使用命名导出named export
  • 每个组件文件一个主组件导出
  • 使用 barrel exportindex.ts)整理模块导出
  • 类型导出使用 export type 语法
// 组件导出示例
export { Button } from './Button';
export type { ButtonProps, ButtonVariant } from './Button';

组件规范

Server Components vs Client Componentsapps/web

  • 默认使用 Server ComponentsNext.js App Router 约定)
  • 仅在需要交互state、effects、event handlers时使用 Client Components
  • Client Components 必须在文件顶部添加 "use client" 指令
  • 布局组件Layout默认为 Server Component
  • 数据获取优先在 Server Component 中完成
// Server Component — 默认,无需声明
export default async function ProductPage({ params }: { params: Promise<{ slug: string }> }) {
  const { slug } = await params;
  const product = await fetchProduct(slug);
  return <ProductDetail product={product} />;
}

// Client Component — 需要交互时使用
"use client"
import { useState } from 'react';
export function ProductFilter({ categories }: ProductFilterProps) {
  const [active, setActive] = useState<string>('all');
  // ...
}

组件结构顺序

// 1. "use client" 指令(如需要)
"use client"

// 2. 导入
import { useState } from 'react';

// 3. 类型定义
interface ExampleProps {
  title: string;
  children: React.ReactNode;
}

// 4. 组件定义
export function Example({ title, children }: ExampleProps) {
  // 4a. hooks
  const t = useTranslations('common');

  // 4b. 派生状态
  const formattedTitle = title.toUpperCase();

  // 4c. 事件处理
  const handleClick = () => { /* ... */ };

  // 4d. 渲染
  return (
    <div onClick={handleClick}>
      <h2>{formattedTitle}</h2>
      {children}
    </div>
  );
}

组件设计原则

  • 单一职责:每个组件只做一件事
  • 组合优于继承:使用 children 和 props 组合
  • Props 解构:始终解构 props不要使用 props.xxx
  • Forward Ref可复用组件需要支持 ref 转发
  • 有意义的默认值:为可选 props 提供合理的默认值

样式规范

Tailwind CSS 使用约定

  • 使用 Tailwind 工具类,禁止手写 CSS除非 CSS 变量或动画关键帧)
  • 类名顺序遵循一致性(建议:布局 -> 尺寸 -> 间距 -> 排版 -> 颜色 -> 其他)
  • 超过 5 个类名时考虑提取为组件或使用 @apply(谨慎使用)
  • 响应式设计使用 Mobile-first 方式:md: -> lg:
  • 条件样式使用模板字符串或 clsx/cn 工具函数

设计令牌Design Tokens

令牌 用途
主色 #3a6b35 品牌绿CTA 按钮、强调元素
辅色 大地色系 深绿、岩石灰、矿物绿
字体 Inter 英文主字体
中文回退 Source Han Sans SC, PingFang SC 中文排版
断点 md: 769px, lg: 1025px 响应式分界
触摸目标 最小 44px 移动端可访问性
对比度 >= 4.5:1 WCAG 2.1 AA

响应式断点

/* Mobile-first */
/* 默认:< 769px (Mobile) */
/* md: >= 769px (Tablet) */
/* lg: >= 1025px (Desktop) */

TypeScript 规范

  • 启用 strict 模式
  • 禁止使用 any,如必须使用需添加注释说明原因
  • 函数参数和返回值必须有明确的类型注解
  • 优先使用 interface 定义对象类型,type 用于联合类型、工具类型
  • 使用 as const 断言定义常量对象
  • 异步函数返回类型明确标注 Promise<T>
  • 使用 TypeScript 枚举或联合字面量类型替代魔法字符串
// 推荐
interface NavigationItem {
  id: string;
  title: Record<Locale, string>;
  path: string;
}

type Locale = 'zh-CN' | 'en';
type ButtonVariant = 'primary' | 'secondary' | 'outline';

// 避免
const config: any = {}; // 禁止
function handleClick(e) { /* ... */ } // 缺少类型

国际化规范next-intlapps/web

翻译文件

  • 翻译文件位于 apps/web/messages/ 目录
  • 文件格式JSONzh-CN.jsonen.json
  • 使用命名空间分隔:homeproductscommonnav

使用方式

// Server Component
import { useTranslations } from 'next-intl';
export default function Page() {
  const t = useTranslations('home');
  return <h1>{t('title')}</h1>;
}

// Client Component
"use client"
import { useTranslations } from 'next-intl';
export function ProductCard() {
  const t = useTranslations('products');
  return <span>{t('addToCart')}</span>;
}

内容回退机制

  • 回退链:请求语言 -> 基准语言 -> en
  • 多语言内容使用 Record<Locale, string> 类型存储
  • 导航项通过 visible_locales 控制语言可见性

URL 策略

  • 中文站:无语言前缀(如 /products
  • 国际站:/en 前缀(如 /en/products
  • SEO 自动生成 hreflang 替代链接

API 调用规范

数据获取apps/web

  • Server Components 中直接使用 fetch 或 API 客户端
  • Client Components 中使用 TanStack React Query
  • API 调用超时设置5 秒
  • API 不可用时使用本地回退内容
// Server Component 数据获取
async function getProduct(slug: string) {
  try {
    const res = await fetch(`${API_URL}/api/products/${slug}`, { next: { revalidate: 3600 } });
    if (!res.ok) throw new Error('Failed to fetch');
    return await res.json();
  } catch {
    return getFallbackProduct(slug); // 回退机制
  }
}

API 客户端apps/admin

  • 使用 src/lib/api-client.ts 统一管理 API 请求
  • JWT Token 存储在 localStorage
  • 自动刷新过期 TokenAccess Token + Refresh Token 双令牌)
  • API 请求前缀:/admin/*(需认证)

React Query 约定

  • 使用 Query Key 工厂模式
  • 避免在组件中直接调用 fetch,通过 hooks 封装
  • 乐观更新用于即时反馈操作

路由规范

Next.js App Routerapps/web

  • 使用文件系统路由:app/ 目录
  • 动态路由参数为 Promise 类型:params: Promise<{ slug: string }>
  • 布局使用 layout.tsx,页面使用 page.tsx
  • 加载状态使用 loading.tsx
  • 错误处理使用 error.tsx
  • ISR 策略:首页 30 分钟,产品页 1 小时

React Routerapps/admin

  • 使用 createBrowserRouter 配置路由
  • 所有页面使用 lazy() 懒加载实现代码分割
  • AuthGuard 组件保护需要认证的路由
  • 路由守卫在 src/router/AuthGuard.tsx
  • 布局结构:DashboardLayout(侧边栏 + 内容区)和 AuthLayout(登录页)

表单规范

  • 使用 React Hook Form 管理表单状态
  • 使用 Zod 定义验证 schema
  • 通过 zodResolver 连接 React Hook Form 和 Zod
import { useForm } from 'react-hook-form';
import { z } from 'zod';
import { zodResolver } from '@hookform/resolvers/zod';

const schema = z.object({
  email: z.string().email(),
  password: z.string().min(8),
});

type LoginForm = z.infer<typeof schema>;

export function LoginForm() {
  const { register, handleSubmit, formState: { errors } } = useForm<LoginForm>({
    resolver: zodResolver(schema),
  });
  // ...
}

注释规范

  • 公共组件和 Hook 必须有 JSDoc 注释
  • 复杂业务逻辑处需有行内注释说明意图
  • 禁止保留无意义的注释和注释掉的废弃代码
  • // TODO: 标注待办事项,需包含上下文说明
  • // NOTE: 标注重要设计决策或注意事项

错误处理规范

  • 页面级错误使用 error.tsx 捕获
  • API 调用失败必须提供回退方案
  • 禁止捕获错误后不做任何处理(空 catch
  • 用户操作失败时展示友好的错误提示
  • 使用 TypeScript 的 discriminated union 处理不同状态

性能规范

  • Server Components默认使用减少客户端 JS 体积
  • 代码分割:路由级自动分割,大型组件使用 dynamic() 懒加载
  • 图片优化:使用 OptimizedImage 组件或 Next.js <Image>
  • ISR合理设置页面重新验证时间
  • Bundle 分析:定期检查包体积
  • Standalone 输出:生产构建使用 output: 'standalone'

无障碍规范A11y

  • 语义化 HTML使用正确的标签<nav><main><article>
  • 图片必须提供 alt 属性
  • 表单控件必须关联 <label>
  • 交互元素必须有键盘操作支持
  • 焦点管理:模态框打开时捕获焦点,关闭时恢复焦点
  • 颜色对比度 >= 4.5:1WCAG 2.1 AA
  • 触摸目标最小 44px

共享类型定义packages/types

文件结构

packages/types/src/
├── models.ts         # 核心数据模型User, Product, Quotation 等)
├── cms.ts            # CMS 内容类型Navigation, Pages, SEO 等)
├── api.ts            # API 请求/响应类型
├── admin.ts          # 后台管理相关类型RBAC 等)
├── configurator.ts   # 报价配置器类型
├── device.ts         # 设备管理相关类型(规划中)
├── quotation.ts      # 报价系统相关类型(规划中)
├── shipping.ts       # 运输管理相关类型(规划中)
├── permission.ts     # 细粒度权限矩阵类型(规划中)
└── index.ts          # 统一导出

多语言内容类型模式

type Locale = 'zh-CN' | 'en';

// 多语言内容统一使用 Record 类型
interface Product {
  id: string;
  name: Record<Locale, string>;
  description: Record<Locale, string>;
}

API 响应类型模式

interface ApiResponse<T> {
  data: T;
  message?: string;
  meta?: {
    total: number;
    page: number;
    pageSize: number;
  };
}

共享组件库packages/ui

组件层级Atomic Design

packages/ui/src/
├── atoms/          # 原子组件Button, Card, Typography, Icon, Input, Select, Textarea
├── navigation/     # 导航组件Navbar, MobileNav, LanguageSwitcher, StickySubNav, Breadcrumb
├── layout/         # 布局组件Footer, MapEmbed
├── content/        # 内容组件HeroCarousel, ImageGallery, Accordion, VideoEmbed, ScrollAnimation
├── forms/          # 表单组件ContactForm, ContactFormValidation
├── auth/           # 认证组件AuthProvider, useAuth, NavbarAvatar, LoginPrompt
├── analytics/      # 分析组件GoogleAnalytics, BaiduAnalytics, trackEvent
├── performance/    # 性能组件OptimizedImage
└── index.ts        # Barrel export

计划新增组件(多模块演进)

packages/ui/src/
├── data-table/        # 通用数据表格(设备列表、报价列表等复用)
│   ├── DataTable.tsx
│   ├── DataTablePagination.tsx
│   ├── DataTableFilter.tsx
│   └── DataTableExport.tsx
└── module-shell/      # 模块通用外壳(列表页、详情页模板)
    ├── ListPageShell.tsx
    └── DetailPageShell.tsx

组件开发规范

  • 每个组件独立文件,文件名与组件名一致
  • 组件必须包含 TypeScript 类型定义
  • Props 接口必须导出
  • 可复用组件支持 className prop 以允许样式扩展
  • 可交互组件支持 ref 转发

共享工具函数packages/utils

packages/utils/src/
├── admin.ts         # 管理后台工具函数(权限判断、数据转换等)
├── api.ts           # API 相关工具
├── cms.ts           # CMS 内容处理工具
├── configurator.ts  # 报价配置器工具
├── models.ts        # 数据模型工具
└── index.ts         # 统一导出

认证与权限

管理员认证apps/admin

  • JWT 双令牌Access Token短期+ Refresh Token长期
  • Token 存储在 localStorage
  • API 客户端自动刷新过期 Token
  • AuthGuard 保护路由

状态管理分层apps/admin

详见 docNew/13-Admin状态管理设计.md

服务端状态 → TanStack React QueryAPI 数据、缓存、失效)
全局客户端状态 → Zustand认证、UI 偏好、语言偏好、权限缓存)
表单状态 → React Hook Form + Zod表单字段、验证
组件内临时状态 → React useState / useReducer弹窗开关等局部状态

关键原则API 返回的数据绝不放进 ZustandZustand 只放客户端独有状态。

Zustand Store 结构

  • useAuthStore — 认证状态user、login、logout替代现有 AuthProvider Context
  • useUIStore — 全局 UI 状态sidebarCollapsed 持久化、globalLoading
  • useLocaleStore — 编辑器语言偏好activeLocale 持久化,统一各编辑器组件的语言切换)
  • usePermissionStore — 权限缓存permissions 列表、hasPermission 判断,为细粒度权限矩阵预留)

Store 开发规范

  • 文件名:use + 名称 + Store.ts,如 useAuthStore.ts
  • 使用 selector 精确选择避免不必要重渲染:const user = useAuthStore((s) => s.user)
  • 持久化使用 zustand/middlewarepersist 中间件,partialize 只持久化需要的字段
  • 敏感数据不持久化,每次登录重新获取

用户认证apps/web

  • GeoPlatform OAuth 统一登录
  • 环境变量配置 OAuth 参数

当前 RBAC 角色

角色 标识 说明
超级管理员 super_admin 全部权限
内容编辑 content_editor 内容相关权限
市场营销 marketing 内容 + 分析权限
查看者 viewer 只读权限

权限模块navigation, pages, analytics, permissions, settings, content

权限矩阵演进(规划中)

从固定四级角色升级为 角色 + 细粒度权限矩阵

角色(可自定义创建)
  └── 绑定权限项

权限项 = 模块 + 资源 + 操作
  模块:  cms | devices | quotations | shipping | system
  资源:  各模块下的具体资源
  操作:  view | create | edit | delete | export

权限标识命名规范{module}.{resource}.{action}

  • cms.pages.view — 查看页面
  • devices.list.export — 导出设备数据
  • quotations.create.view — 查看新建报价页面
  • system.roles.edit — 编辑角色权限

前端权限控制层级

  • 侧边栏:根据用户权限动态渲染
  • 页面级:路由守卫检查模块访问权限
  • 操作级:PermissionGate 组件包裹按钮
  • API 级:后端中间件校验,前端仅做 UI 层控制
// 按钮级权限控制示例
<PermissionGate permission="devices.list.export">
  <Button onClick={handleExport}>导出设备列表</Button>
</PermissionGate>

环境变量

apps/web

NEXT_PUBLIC_DEFAULT_LOCALE=zh-CN
NEXT_PUBLIC_SITE_URL=http://localhost:3002
NEXT_PUBLIC_API_URL=http://localhost:3001

apps/admin

VITE_API_URL=http://localhost:3001
PORT=3003

常用命令

# 安装依赖
npm install

# 启动开发(全部)
npm run dev

# 启动开发(指定应用)
npm run dev --filter=web       # 前端网站
npm run dev --filter=admin     # 后台管理

# 构建
npm run build
npm run build --filter=web
npm run build:cn               # 中文站
npm run build:en               # 国际站

# 代码检查
npm run lint

# 测试
npm run test
npm run test --filter=admin

部署

Web 应用Next.js

  • 生产构建使用 output: 'standalone' 优化
  • ISR 增量静态再生平衡性能与内容时效性
  • Nginx 反向代理,中英文站点独立部署

Admin 应用Vite

  • 静态资源构建,部署至 CDN 或 Nginx
  • API 请求代理至后端服务