Appearance
Техническая архитектура сервиса портфолио
Общее описание
Сервис портфолио — клиентский модуль приложения Pirate Place для отслеживания криптовалютных инвестиций. Ключевая особенность — работа без авторизации: все данные хранятся в localStorage браузера. Рыночные данные поступают с бекенда через REST API и WebSocket (Centrifuge).
Стек технологий
- Vue.js 2.7 + Nuxt.js 2.17 — фреймворк
- Vuex — управление состоянием (модули
transactions,assetsColors) - vee-validate 2.2 — валидация форм
- amCharts 4 / eCharts 5.6 — графики
- CryptoJS — шифрование экспорта
- file-saver — скачивание файлов
- localStorage — персистентное хранилище
Структура модуля
app/landings/portfolio/
├── pages/ # Маршруты
│ ├── portfolio.vue # Layout-обёртка
│ ├── portfolio/index.vue # Главная страница
│ └── portfolio/_overview.vue # Внутренняя страница монеты
├── modules/ # 22 UI-модуля
│ ├── assetsTable/ # Таблица активов
│ ├── transactionsTable/ # Таблица транзакций
│ ├── transactionsChart/ # График транзакций
│ ├── portfolioChart/ # График портфолио
│ ├── holdingsChart/ # Круговая диаграмма холдингов
│ ├── holdingWidget/ # Виджет холдинга
│ ├── gainLossCards/ # Карточки прибыли/убытка
│ ├── portfolioHeader/ # Шапка портфолио
│ ├── coinHeader/ # Шапка монеты (внутренняя страница)
│ ├── infoShortGeneral/ # Карточки показателей
│ ├── portfolioHoldings/ # Блок распределения холдингов
│ ├── portfolioPoster/ # Постер (пустое состояние)
│ ├── fomoAssetsPopup/ # FOMO-оповещения
│ ├── importTransactionsPopup/ # Импорт транзакций
│ ├── exportTransactionsPopup/ # Экспорт транзакций
│ ├── deleteAssetPopup/ # Удаление одного актива
│ ├── deleteAssetsPopup/ # Удаление всех активов
│ ├── viewTransactionPopup/ # Просмотр транзакции
│ ├── coinWithPortfolioButton/ # Кнопка на странице монеты
│ └── featuresController/ # Управление feature-флагами
├── components/ # Компоненты
│ ├── ui/ # UI-элементы
│ ├── transaction/ # Компоненты транзакций
│ ├── sections/ # Импорт/экспорт секции
│ ├── toasts/ # Уведомления
│ └── popups/AssetPopups/ # Попапы создания/редактирования
│ ├── AddAssetPopup.vue
│ ├── EditTransactionPopup.vue
│ ├── AddAssetFormsPopup.vue
│ └── forms/
│ ├── AddTransactionForm.vue
│ └── AddAssetTransferForm.vue
├── tools/ # Бизнес-логика
│ ├── transactions/
│ │ ├── transaction/
│ │ │ ├── BaseTransaction.js
│ │ │ ├── BuySellTransaction.js
│ │ │ ├── OtherTransaction.js
│ │ │ ├── transactionBuy.js
│ │ │ ├── transactionSell.js
│ │ │ ├── transactionMining.js
│ │ │ ├── transactionTransferIn.js
│ │ │ ├── transactionTransferOut.js
│ │ │ └── transactionAggregator.js
│ │ ├── transactionLink.js
│ │ ├── transactionMath.js
│ │ ├── transactionAssets.js
│ │ ├── transactionType.js
│ │ ├── utils.js
│ │ └── validation/
│ │ ├── validationTransaction.js
│ │ └── validationRules.js
│ └── helpers.js
├── mixins/ # Миксины с логикой
│ ├── transactions/
│ │ ├── index.js # Главный миксин: CRUD, импорт/экспорт
│ │ └── transactionData.js
│ ├── transactionPeriod.js
│ ├── filteredCoins.js
│ ├── portfolioFile.js # Шифрование/дешифрование файлов
│ ├── hideData.js # Скрытие данных
│ ├── assetDataAdapter.js
│ ├── featuresManagement.js
│ └── onboardingPortfolioPopup.js
├── store/ # Vuex-модули
│ ├── transactions.js # Состояние транзакций и ассетов
│ └── assetsColors.js # Цвета для графиков
├── services/
│ └── assetsColorsHelpers.js
├── subdomains/
│ └── notes/ # Независимые заметки
│ ├── modules/noteCard/, notePopup/, userNotes/
│ ├── store/notes.js
│ ├── tools/notes/
│ └── mixins/notes.js
└── ui/
└── UiDataRow.vueДиаграмма архитектуры
mermaid
graph TB
subgraph "Клиент (Браузер)"
UI["Vue-компоненты<br/>Страницы портфолио"]
Store["Vuex Store<br/>transactions / assetsColors / notes"]
Tools["Tools Layer<br/>TransactionMath, TransactionAssets,<br/>TransactionAggregator, Validation"]
Mixins["Mixins Layer<br/>transactions, portfolioFile,<br/>hideData, filteredCoins"]
LS["localStorage<br/>transactions / notes"]
end
subgraph "Бекенд"
API["REST API<br/>Данные о криптовалютах"]
WS["WebSocket (Centrifuge)<br/>Обновления цен"]
end
UI -->|"dispatch/commit"| Store
Store -->|"getters"| UI
Mixins -->|"методы"| UI
Mixins -->|"actions/mutations"| Store
Store -->|"расчёты"| Tools
Tools -->|"результат"| Store
Store <-->|"чтение/запись"| LS
API -->|"цены, графики"| Store
WS -->|"real-time"| StoreПотоки данных
mermaid
flowchart LR
LS["localStorage"] -->|"JSON.parse"| Vuex["Vuex Store"]
Vuex -->|"JSON.stringify"| LS
Backend["Backend API"] -->|"цены монет"| Vuex
Vuex -->|"TransactionAssets"| Calc["Расчёт ассетов"]
Calc -->|"setAssetData"| Vuex
Vuex -->|"getters"| Pages["Страницы"]
User["Пользователь"] -->|"формы"| Pages
Pages -->|"handlers"| Vuex