shop-web/doc/开发指南.md

11 KiB
Raw Blame History

开发指南

开发环境设置

1. 环境要求

  • Node.js: 20.x 或 22+
  • 包管理器: pnpm 9.x 或 10+
  • 编辑器: Visual Studio Code (推荐)
  • 浏览器: Chrome 或 Safari (移动端调试)

2. 推荐 VS Code 插件

  • Vue Language Features (Volar)
  • TypeScript Vue Plugin (Volar)
  • ESLint
  • UnoCSS
  • Auto Rename Tag
  • GitLens

3. 项目初始化

# 克隆项目
git clone <repository-url>

# 安装依赖
pnpm i

# 启动开发服务器
pnpm dev

项目架构

目录结构详解

src/
├── common/              # 通用模块
│   ├── apis/           # API 接口定义
│   │   ├── users/      # 用户相关接口
│   │   ├── shop/       # 店铺相关接口
│   │   ├── cabinet/    # 柜机相关接口
│   │   ├── approval/   # 审批相关接口
│   │   └── ab98/       # AB98系统接口
│   ├── assets/         # 静态资源
│   │   └── styles/     # 样式文件
│   ├── composables/    # 组合式函数
│   │   ├── useDark.ts          # 暗黑模式
│   │   ├── useWatermark.ts     # 水印功能
│   │   └── useGrayscaleAndColorblind.ts # 无障碍模式
│   ├── components/     # 通用组件
│   └── utils/          # 工具函数
│       ├── cache/      # 缓存工具
│       ├── permission.ts       # 权限工具
│       └── wx.ts               # 微信工具
├── layout/             # 布局组件
│   ├── index.vue       # 主布局
│   ├── components/
│   │   ├── NavBar.vue  # 导航栏
│   │   ├── Tabbar.vue  # 标签栏
│   │   └── Footer.vue  # 底部
├── pages/              # 页面组件
│   ├── product/        # 商品相关页面
│   ├── order/          # 订单相关页面
│   ├── cabinet/        # 柜机相关页面
│   ├── approval/       # 审批相关页面
│   ├── me/             # 个人中心
│   └── error/          # 错误页面
├── pinia/              # 状态管理
│   ├── index.ts        # Pinia 实例
│   └── stores/         # Store 定义
│       ├── user.ts             # 用户状态
│       ├── ab98-user.ts        # AB98用户状态
│       ├── wx.ts               # 微信状态
│       ├── product.ts          # 商品状态
│       ├── cart.ts             # 购物车状态
│       ├── order.ts            # 订单状态
│       └── approval.ts         # 审批状态
├── router/             # 路由配置
│   ├── index.ts        # 路由定义
│   ├── guard.ts        # 路由守卫
│   └── whitelist.ts    # 白名单
├── http/               # HTTP 请求
│   └── axios.ts        # Axios 配置
└── plugins/            # 插件配置
    ├── index.ts        # 插件安装
    ├── permission-directive.ts # 权限指令
    └── console.ts              # 控制台工具

开发规范

1. 代码风格

TypeScript 规范

  • 使用严格模式,避免 any 类型
  • 为所有函数和变量提供明确的类型定义
  • 使用接口定义复杂的数据结构
// ✅ 推荐
interface UserInfo {
  id: number;
  name: string;
  email: string;
}

const getUserInfo = async (id: number): Promise<UserInfo> => {
  // ...
}

// ❌ 避免
const getUserInfo = async (id: any): Promise<any> => {
  // ...
}

Vue 组件规范

  • 使用 script setup 语法
  • 组件名使用 PascalCase
  • Props 和 Emits 使用 TypeScript 定义
<script setup lang="ts">
interface Props {
  title: string;
  count?: number;
}

interface Emits {
  (e: 'update:count', value: number): void;
}

const props = defineProps<Props>();
const emit = defineEmits<Emits>();

const handleClick = () => {
  emit('update:count', (props.count || 0) + 1);
};
</script>

<template>
  <div class="my-component">
    <h3>{{ title }}</h3>
    <button @click="handleClick">
      点击 {{ count }}
    </button>
  </div>
</template>

2. 状态管理规范

Store 定义

  • Store 名使用 camelCase
  • 使用组合式 API 风格
  • 提供清晰的类型定义
import { pinia } from "@/pinia";

export const useProductStore = defineStore("product", () => {
  // State
  const products = ref<Product[]>([]);
  const loading = ref(false);

  // Getters
  const availableProducts = computed(() =>
    products.value.filter(p => p.stock > 0)
  );

  // Actions
  const fetchProducts = async () => {
    loading.value = true;
    try {
      const response = await getProductListApi();
      if (response.code === 0) {
        products.value = response.data.products;
      }
    } finally {
      loading.value = false;
    }
  };

  return {
    products,
    loading,
    availableProducts,
    fetchProducts
  };
});

3. API 开发规范

API 文件结构

// src/common/apis/product/index.ts
import { request } from "@/http/axios";
import type { ProductListResponse, ProductDetailResponse } from "./type";

export const getProductListApi = (params?: { page?: number; size?: number }) => {
  return request<ProductListResponse>({
    url: "/api/v1/product/list",
    method: "GET",
    params
  });
};

export const getProductDetailApi = (id: number) => {
  return request<ProductDetailResponse>({
    url: `/api/v1/product/${id}`,
    method: "GET"
  });
};

类型定义文件

// src/common/apis/product/type.ts
export interface Product {
  id: number;
  name: string;
  price: number;
  image: string;
  description: string;
  stock: number;
  category: string;
}

export interface ProductListResponse {
  products: Product[];
  total: number;
  page: number;
  size: number;
}

export interface ProductDetailResponse extends Product {
  specifications: Specification[];
  images: string[];
  details: string;
}

4. 路由配置规范

路由定义

// src/router/index.ts
export const routes: RouteRecordRaw[] = [
  {
    path: "/product/:id",
    component: () => import("@/pages/product/ProductDetail.vue"),
    name: "ProductDetail",
    meta: {
      title: "商品详情",
      keepAlive: true,
      layout: {
        navBar: {
          showNavBar: true,
          showLeftArrow: true
        },
        tabbar: {
          showTabbar: false
        }
      },
      requiresAuth: true
    }
  }
];

5. 样式开发规范

UnoCSS 使用

  • 优先使用预设的原子类
  • 自定义规则在 uno.config.ts 中定义
  • 使用属性化模式un-前缀)
<template>
  <div class="product-card un-p-4 un-bg-white un-rounded-lg un-shadow-sm">
    <img
      :src="product.image"
      class="un-w-full un-h-40 un-object-cover un-rounded"
    />
    <h3 class="un-text-lg un-font-medium un-mt-2 un-text-gray-900">
      {{ product.name }}
    </h3>
    <p class="un-text-primary un-font-bold un-mt-1">
      ¥{{ product.price }}
    </p>
  </div>
</template>

CSS 变量

src/common/assets/styles/variables.css 中定义主题变量:

:root {
  --mobvue-primary-color: #1989fa;
  --mobvue-bg-color: #ffffff;
  --mobvue-text-color: #323233;
}

html.dark {
  --mobvue-primary-color: #2d8cf0;
  --mobvue-bg-color: #1a1a1a;
  --mobvue-text-color: #e5e5e5;
}

功能开发指南

1. 添加新页面

步骤 1: 创建页面组件

<!-- src/pages/example/ExamplePage.vue -->
<script setup lang="ts">
import { useRoute } from "vue-router";

const route = useRoute();

// 页面逻辑...
</script>

<template>
  <div class="example-page">
    <h1>示例页面</h1>
    <!-- 页面内容 -->
  </div>
</template>

<style scoped>
.example-page {
  padding: 16px;
}
</style>

步骤 2: 配置路由

// src/router/index.ts
export const routes: RouteRecordRaw[] = [
  {
    path: "/example",
    component: () => import("@/pages/example/ExamplePage.vue"),
    name: "ExamplePage",
    meta: {
      title: "示例页面",
      layout: {
        navBar: {
          showNavBar: true,
          showLeftArrow: true
        }
      }
    }
  }
];

2. 添加新 Store

// src/pinia/stores/example.ts
import { pinia } from "@/pinia";

export const useExampleStore = defineStore("example", () => {
  const data = ref<string[]>([]);
  const loading = ref(false);

  const fetchData = async () => {
    loading.value = true;
    try {
      // API 调用...
    } finally {
      loading.value = false;
    }
  };

  return {
    data,
    loading,
    fetchData
  };
});

3. 添加新 API

// src/common/apis/example/index.ts
import { request } from "@/http/axios";
import type { ExampleResponse } from "./type";

export const getExampleDataApi = () => {
  return request<ExampleResponse>({
    url: "/api/v1/example/data",
    method: "GET"
  });
};

// src/common/apis/example/type.ts
export interface ExampleResponse {
  data: string[];
}

调试技巧

1. 移动端调试

  • 使用 Chrome DevTools 的设备模拟
  • 启用移动端触摸模拟
  • 测试不同屏幕尺寸

2. 微信调试

  • 使用微信开发者工具
  • 配置正确的回调域名
  • 检查 openid 获取逻辑

3. 状态调试

  • 使用 Vue DevTools
  • 查看 Pinia Store 状态
  • 监控组件生命周期

性能优化

1. 代码分割

  • 路由级别的懒加载
  • 组件按需导入
  • 第三方库独立打包

2. 图片优化

  • 使用 WebP 格式
  • 实现懒加载
  • 压缩图片大小

3. 缓存策略

  • 合理使用浏览器缓存
  • API 响应缓存
  • 组件 keep-alive

测试指南

1. 单元测试

// tests/example.test.ts
import { describe, it, expect } from "vitest";
import { mount } from "@vue/test-utils";
import ExampleComponent from "@/components/ExampleComponent.vue";

describe("ExampleComponent", () => {
  it("renders correctly", () => {
    const wrapper = mount(ExampleComponent, {
      props: {
        title: "Test Title"
      }
    });

    expect(wrapper.text()).toContain("Test Title");
  });
});

2. E2E 测试

  • 使用 Playwright 或 Cypress
  • 模拟用户操作流程
  • 测试关键业务路径

部署指南

1. 环境变量配置

# .env.production
VITE_BASE_URL=https://api.example.com
VITE_PUBLIC_PATH=/
VITE_ROUTER_HISTORY=hash

2. 构建优化

# 生产环境构建
pnpm build

# 预发布环境构建
pnpm build:staging

3. 部署检查清单

  • 环境变量配置正确
  • 静态资源路径正确
  • API 接口可访问
  • 路由配置正确
  • 移动端适配正常

常见问题解决

1. 微信认证失败

  • 检查回调域名配置
  • 验证 corpid 和 secret
  • 查看网络请求日志

2. 路由跳转问题

  • 检查路由守卫逻辑
  • 验证权限配置
  • 查看路由历史模式

3. 样式显示异常

  • 检查 UnoCSS 配置
  • 验证 CSS 变量定义
  • 测试不同主题模式

贡献指南

1. 代码提交

  • 遵循提交信息规范
  • 一个功能一个提交
  • 提供清晰的提交描述

2. 代码审查

  • 检查代码规范
  • 验证功能完整性
  • 测试边界情况

3. 文档更新

  • 更新相关文档
  • 添加使用示例
  • 记录变更内容