Files
urbanLifeline/docs/前端完整指南.md
2025-12-02 15:55:30 +08:00

11 KiB
Raw Blame History

泰豪电源 AI 数智化平台 - 前端完整指南

📖 目录

  1. 技术架构
  2. 共享组件方案
  3. 快速开始
  4. 开发指南
  5. 构建部署
  6. 常见问题

1. 技术架构

1.1 技术栈

前端框架

  • Vue 3.5+ (<script setup>)
  • TypeScript 5.7+
  • Vite 6.0+
  • Pinia 2.2+
  • Element Plus 2.9+

工程化

  • pnpm 9.0+ Monorepo
  • Turborepo 2.0+ 构建加速
  • unplugin-auto-import 自动导入
  • ESLint 9 + Prettier

通信层

  • ofetch (替代 Axios)
  • @vueuse/core

1.2 项目结构

urbanLifelineWeb/
├── packages/
│   ├── shared/                  # 共享包 ⭐核心
│   │   ├── components/          # UI组件
│   │   ├── utils/               # 工具函数
│   │   ├── api/                 # API封装
│   │   └── composables/         # 组合函数
│   ├── portal/                  # 主应用
│   ├── app-bidding/             # 招投标应用
│   ├── app-customer-service/    # 智能客服应用
│   └── app-knowledge/           # 知识协同应用
├── pnpm-workspace.yaml
└── turbo.json

2. 共享组件方案

2.1 核心理念

业务应用只需关心 @shared/* 导入无需关心底层依赖Vue、Element Plus 等)

业务应用: import { UlTable } from '@shared/components'
              ↓
浏览器: GET /shared/components.js
              ↓
共享服务: 返回包含 Vue + Element Plus 的 ES Module
              ↓
✅ 所有应用共用,浏览器缓存

2.2 配置方式

业务应用配置(极简)

<!-- index.html -->
<script type="importmap">
{
  "imports": {
    "@shared/components": "/shared/components.js",
    "@shared/utils": "/shared/utils.js",
    "@shared/api": "/shared/api.js"
  }
}
</script>

Vue 组件使用

<script setup lang="ts">
// ✅ 直接从 HTTP URL 加载
import { UlTable } from '@shared/components'
import { http } from '@shared/utils'
import { authApi } from '@shared/api'
import { useTable } from '@shared/composables'

const { loading, tableData } = useTable({
  fetchData: authApi.getUserList
})
</script>

<template>
  <UlTable :data="tableData" :loading="loading" />
</template>

2.3 优势

特性 传统方式 Import Maps 方案
代码共享 每个应用打包一份 所有应用共用一份
构建体积 重复打包 减少 30-50%
依赖管理 每个应用配置 共享服务统一管理
版本升级 所有应用改 只改共享服务
浏览器缓存 ⚠️ 独立缓存 统一缓存

3. 快速开始

3.1 Docker 环境(推荐)

# 1. 启动所有服务
make up

# 2. 查看状态
make ps

# 3. 访问应用
open http://localhost

访问地址

3.2 本地开发

# 1. 安装依赖
pnpm install

# 2. 启动所有应用
pnpm dev

# 或启动单个应用
pnpm --filter portal dev
pnpm --filter app-bidding dev

4. 开发指南

4.1 创建页面

<!-- packages/portal/src/views/UserList.vue -->
<script setup lang="ts">
import { UlTable } from '@shared/components'
import { authApi } from '@shared/api'
import { useTable } from '@shared/composables'

interface User {
  id: string
  username: string
  email: string
}

const { loading, tableData, pagination, handlePageChange } = useTable<User>({
  fetchData: authApi.getUserList
})

const columns = [
  { prop: 'username', label: '用户名', minWidth: 150 },
  { prop: 'email', label: '邮箱', minWidth: 200 }
]
</script>

<template>
  <div class="user-list">
    <UlTable
      :data="tableData"
      :columns="columns"
      :loading="loading"
      :pagination="pagination"
      @page-change="handlePageChange"
    />
  </div>
</template>

4.2 API 调用

// 使用封装的 API
import { authApi, systemApi } from '@shared/api'

// GET 请求
const users = await authApi.getUserList({ page: 1, size: 10 })

// POST 请求
await authApi.createUser({ username: 'test', email: 'test@example.com' })

// 直接使用 http
import { http } from '@shared/utils'
const data = await http.get('/custom/endpoint')

4.3 状态管理

// store/user.ts
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { authApi } from '@shared/api'

export const useUserStore = defineStore('user', () => {
  // State
  const userInfo = ref(null)
  const permissions = ref([])
  
  // Getters
  const isLoggedIn = computed(() => !!userInfo.value)
  
  // Actions
  const login = async (loginData) => {
    const res = await authApi.login(loginData)
    userInfo.value = res.userInfo
    permissions.value = res.permissions
  }
  
  return { userInfo, permissions, isLoggedIn, login }
})

4.4 路由配置

// router/index.ts
import { createRouter, createWebHistory } from 'vue-router'

const routes = [
  {
    path: '/',
    component: () => import('@/layouts/MainLayout.vue'),
    children: [
      {
        path: 'home',
        component: () => import('@/views/home/index.vue'),
        meta: { title: '首页' }
      }
    ]
  }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router

4.5 常用命令

# 查看日志
make logs-portal       # 主应用日志
make logs-gateway      # 网关日志
make logs-shared       # 共享包日志

# 重启服务
make restart-portal    # 重启主应用
make restart           # 重启所有服务

# 进入容器
make shell-portal      # 进入容器调试

# 数据库
make db                # 连接数据库
make db-init           # 初始化数据

5. 构建部署

5.1 本地构建

# 构建所有应用
pnpm build

# 构建单个应用
pnpm --filter portal build
pnpm --filter shared build

# 预览
pnpm preview

5.2 部署到生产

方式1: Docker 部署

# 构建生产镜像
docker build -t urban-lifeline-web .

# 运行
docker run -p 80:80 urban-lifeline-web

方式2: CDN 部署

# 部署共享包到 CDN
cd packages/shared
pnpm build
ossutil cp -r dist/esm/ oss://cdn/shared/v1.0.0/

# 部署业务应用
cd packages/portal
pnpm build
ossutil cp -r dist/ oss://cdn/portal/

方式3: Nginx 静态部署

server {
    listen 80;
    server_name taihao.com;
    
    # 主应用
    location / {
        root /var/www/portal/dist;
        try_files $uri $uri/ /index.html;
    }
    
    # 共享包
    location /shared/ {
        root /var/www/shared/dist;
        add_header Access-Control-Allow-Origin "*";
        expires 1y;
    }
    
    # API 代理
    location /api/ {
        proxy_pass http://gateway:8080/;
    }
}

5.3 环境变量

# .env.development
VITE_API_BASE_URL=http://localhost/api
VITE_SHARED_URL=http://localhost/shared

# .env.production
VITE_API_BASE_URL=https://api.taihao.com/api
VITE_SHARED_URL=https://cdn.taihao.com/shared/v1.0.0

5.4 CI/CD

# .github/workflows/deploy.yml
name: Deploy

on:
  push:
    branches: [main]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v4
        with:
          version: 9
      
      - name: Build
        run: pnpm install && pnpm build
      
      - name: Deploy
        run: ./scripts/deploy-production.sh

6. 常见问题

6.1 为什么使用 Import Maps

优势

  • 浏览器原生支持,无需额外库
  • 真正的运行时共享
  • 开发体验好(支持 HMR
  • 减小构建体积

对比 Module Federation

  • Import Maps 更简单,配置少
  • Module Federation 功能更强大,但复杂
  • 两者可以结合使用

6.2 如何处理 TypeScript 类型?

// packages/portal/src/types/shared.d.ts
declare module '@shared/components' {
  export * from '../../../shared/src/components'
}

declare module '@shared/utils' {
  export * from '../../../shared/src/utils'
}

6.3 如何更新共享组件?

# 1. 修改共享组件代码
vim packages/shared/src/components/UlTable/index.vue

# 2. 重启共享服务HMR 自动生效)
make restart-shared

# 3. 浏览器刷新,所有应用自动获得最新版本

6.4 生产环境如何缓存?

# Nginx 配置
location /shared/ {
    # 基于版本号的长期缓存
    expires 1y;
    add_header Cache-Control "public, immutable";
}

# HTML 不缓存
location ~* \.html$ {
    add_header Cache-Control "no-cache";
}

6.5 如何调试共享组件?

# 方式1: 查看网络请求
浏览器 F12 → Network → 筛选 JS → 查看 /shared/components.js

# 方式2: 查看日志
make logs-shared

# 方式3: 进入容器
make shell-shared

6.6 为什么不用 Webpack

Vite 优势:

  • 开发启动快(秒级)
  • 🔥 HMR 更快
  • 📦 生产构建基于 Rollup体积更小
  • 🎯 原生 ES Module 支持

6.7 如何处理样式?

<!-- 组件级样式 -->
<style scoped>
.ul-table {
  width: 100%;
}
</style>

<!-- 全局样式 -->
<style>
@import '@shared/styles/variables.scss';
</style>

共享包会自动处理 CSS 提取和分割。

6.8 如何添加新的业务应用?

# 1. 复制现有应用作为模板
cp -r packages/portal packages/app-newapp

# 2. 修改 package.json
{
  "name": "@apps/newapp",
  "scripts": {
    "dev": "vite --port 3003"
  }
}

# 3. 添加到 pnpm-workspace.yaml已自动包含

# 4. 启动
pnpm --filter app-newapp dev

附录

A. 常用脚本

# Makefile 命令
make up          # 启动
make down        # 停止
make logs        # 日志
make ps          # 状态
make restart     # 重启
make clean       # 清理

# pnpm 命令
pnpm dev         # 开发
pnpm build       # 构建
pnpm preview     # 预览
pnpm lint        # 检查
pnpm format      # 格式化

B. 目录说明

urbanLifeline/
├── urbanLifelineServ/    # 后端Java Spring Boot
├── urbanLifelineWeb/     # 前端Vue 3 Monorepo
├── docker-compose.dev.yml # Docker 开发环境
├── Makefile              # 快捷命令
└── docs/                 # 文档
    └── 前端完整指南.md   # 📖 本文档

C. 技术支持

  • 项目文档:/docs
  • 问题反馈GitHub Issues
  • 开发规范ESLint + Prettier
  • 提交规范Conventional Commits

Happy Coding! 🚀

最后更新2025-12-02