4. Vue3プロジェクト構造

1. 技術スタック

  • フレームワーク: Vue 3.4+ with Composition API
  • ビルドツール: Vite 5.x
  • UIコンポーネント: Ant Design Vue 4.2+
  • 状態管理: Pinia 2.1+
  • ルーティング: Vue Router 4(動的ルーティング)
  • HTTP: Axios(カスタムカプセル化)
  • スタイル: Less
  • 国際化: Vue I18n
  • チャート: ECharts
  • リッチテキスト: WangEditor
  • Node.js: >= 18

2. ディレクトリ構造

src/
├── api/              # APIインターフェースモジュール、領域別分類
├── components/       # 再利用可能Vueコンポーネント
│   ├── business/     # 業務別コンポーネント(OA、ERP等)
│   ├── framework/    # フレームワークレベルコンポーネント(列挙、アイコン、フォーム)
│   ├── support/      # サポートコンポーネント(辞書、ファイルアップロード、テーブル操作)
│   └── system/       # システムコンポーネント(従業員、部門、メニューセレクター)
├── config/           # アプリケーション設定
├── constants/        # 定数と列挙、領域別編成
├── directives/       # Vueカスタムディレクティブ(privilege等)
├── i18n/            # 国際化(zh-CN、en-US)
├── layout/          # レイアウトコンポーネント(side、top、side-expandレイアウト)
├── lib/             # コアツールライブラリ(axios、暗号化、透かし)
├── plugins/         # Vueプラグイン(辞書、権限、スマート列挙)
├── router/          # ルーティング設定と動的ルーティング構築
├── store/           # Pinia状態管理モジュール
├── theme/           # テーマとスタイル設定
├── utils/           # ツール関数
└── views/           # ページコンポーネント、領域別編成
    ├── business/    # ビジネスページ(OA、ERP)
    ├── support/     # サポートページ(設定、辞書、ログ等)
    └── system/      # システムページ(従業員、部門、ホーム、ログイン)

3. 初期化フロー(重要)

アプリケーションは遅延初期化モードを使用してバックエンドからの動的ルーティングを処理します。src/main.jsを参照:

// 1. Tokenがない場合:即座にVueを初期化、ログインルートのみ含む
if (!userToken) {
    initVue(baseRoutes);
}

// 2. Tokenがある場合:
if (userToken) {
    // 2.1 バックエンドからユーザー情報とメニュールートを取得
    const loginInfo = await loginApi.getLoginInfo();

    // 2.2 全辞書データを取得
    const allDictData = await dictApi.getAllDictData();

    // 2.3 動的ルートを構築
    const menuRouterList = buildRoutes(loginInfo.menuRouterList);

    // 2.4 完全なルート設定でVueを初期化
    initVue(baseRoutes.concat(menuRouterList));
}

このアプローチにより、ルートがVueマウント前にロードされ、複雑なナビゲーションガードを回避できます。

4. 動的ルーティングシステム

ルートはバックエンドデータから動的に構築されます(src/router/index.js):

  • バックエンドはメニューリストを返し、path、component、menuId、menuName等を含む
  • import.meta.glob('../views/**/*.vue')ですべてのビューコンポーネントをロード
  • 各メニューがルートとなり、menuIdをルート名として使用
  • コンポーネントは../views/${component}.vueに一致するパスから動的ロード
  • ルートメタデータには:keepAlive、frameFlag、hideInMenu、icon等が含まれる

5. 状態管理(Pinia)

Storeモジュールはsrc/store/modules/system/で領域別に編成されています:

  • user.js - ユーザー認証、メニュールート、タブナビゲーション、keep-aliveキャッシュ
  • dict.js - データ辞書キャッシュとアクセス
  • role.js - ロール権限
  • app-config.js - アプリケーション設定(レイアウト、テーマ等)
  • spin.js - グローバルローディング状態

6. HTTP層

カスタムaxiosカプセル化はsrc/lib/axios.jsにあります:

  • Base URLはimport.meta.env.VITE_APP_API_URLから取得
  • リクエストインターセプター: Authorization: Bearer {token}ヘッダーを追加
  • レスポンスインターセプター: 暗号化、エラーコード、トークン期限切れを処理

特殊エラーコード:

  • 30007/30008: トークン期限切れ、自動ログアウト
  • 30010/30011: セキュリティ警告
  • 30012: セッションタイムアウト、自動ログアウト

リクエストメソッド:

getRequest(url, params)      // GETリクエスト
postRequest(url, data)        // POSTリクエスト
postEncryptRequest(url, data) // 暗号化POSTリクエスト
getDownload(url, params)      // GETファイルダウンロード
postDownload(url, data)       // POSTファイルダウンロード

7. APIモジュールパターン

APIはsrc/api/で領域別に編成されています:

import { getRequest, postRequest } from '/@/lib/axios';

export const employeeApi = {
  query: (params) => postRequest('/api/employee/query', params),
  add: (data) => postRequest('/api/employee/add', data),
  update: (data) => postRequest('/api/employee/update', data),
  delete: (id) => postRequest('/api/employee/delete', { employeeId: id }),
  getDetail: (id) => getRequest(`/api/employee/detail/${id}`),
};

8. コンポーネント編成

コンポーネントは階層構造に従います:

  • business/ - 業務機能のドメイン固有コンポーネント
  • framework/ - 汎用フレームワークコンポーネント(列挙、アイコン、領域セレクター)
  • support/ - システムサポートコンポーネント(辞書、ファイルアップロード、テーブル)
  • system/ - システム管理コンポーネント(従業員、部門セレクター)

9. 定数と列挙

src/constants/で領域別に編成されています:

  • common-const.js - 共有列挙(FLAG_NUMBER_ENUM、GENDER_ENUM、USER_TYPE_ENUM)
  • layout-const.js - レイアウト列挙(LAYOUT_ENUM)
  • 特定領域の定数はサブディレクトリ内

src/constants/index.jsからエクスポートされ、smartEnumPluginを通じて提供されます。

10. プラグインシステム

src/plugins/のプラグイン:

  • privilege-plugin - hasPrivilege(privilege)メソッドを注入
  • dict-plugin - 辞書アクセスメソッドを注入
  • smart-enums-plugin - 定数をグローバルに利用可能にする

11. 国際化

  • 設定はsrc/i18n/にあります
  • サポート言語:zh-CN、en-US
  • 言語はユーザー設定に保存されます

12. 権限システム

  • ディレクティブ: v-privilege="'permission:code'" で権限のない要素を非表示
  • メソッド: hasPrivilege('permission:code') でプログラム的チェック
  • 権限はバックエンドからロードされ、user storeに保存されます

13. データ辞書

  • 辞書データはアプリケーション初期化時に取得
  • Pinia dict storeにキャッシュ
  • dict pluginメソッドまたはdict store経由でアクセス

14. Keep-Alive

  • ルートメタのkeepAliveフラグで制御
  • キャッシュ動作にはコンポーネント名が一致する必要があります
  • user storeのkeepAliveIncludes配列で管理

15. レイアウトシステム

3つのレイアウトモードがあります:

  • side - 伝統的なサイドバーナビゲーション
  • side-expand - 展開可能なサイドバー
  • top - トップナビゲーションバー

アプリケーション設定またはユーザー設定で変更可能です。