generated from VLADIMIR/template_frontend
add rules
This commit is contained in:
@@ -1,104 +1,15 @@
|
||||
# AGENTS.md — Вечерний детектив (фронтенд)
|
||||
# Правила работы с фронтендом
|
||||
|
||||
Правила работы агента над этим репозиторием. Читай целиком перед началом любой задачи.
|
||||
Онлайн-детективная игра: команды проходят «дело» — сценарий из точек, дверей, ключей и улик.
|
||||
Единственный источник правил написания фронтенда —
|
||||
[`docs/FRONTEND_CODE_STANDARD.md`](docs/FRONTEND_CODE_STANDARD.md).
|
||||
|
||||
## 1. Стек и команды
|
||||
Перед изменением фронтенда прочитай этот документ целиком. Если задача требует
|
||||
отступить от стандарта, сначала получи разрешение пользователя и добавь
|
||||
письменное обоснование в описание задачи или code review.
|
||||
|
||||
- **Стек:** Vue 3.5 (`<script setup lang="ts">`), Vite 8, Pinia 3, Vue Router 5, Naive UI (тёмная тема), @vicons, axios.
|
||||
- **API:** клиенты генерируются из `proto/main.proto` → `src/api/generated/`.
|
||||
Операционные правила репозитория:
|
||||
|
||||
| Команда | Назначение |
|
||||
|---|---|
|
||||
| `npm run dev` | dev-сервер (Vite, `--host`) |
|
||||
| `npm run type-check` | проверка типов (vue-tsc) |
|
||||
| `npm run lint` | ESLint с автофиксами |
|
||||
| `npm run lint:css` | Stylelint (алфавитный порядок свойств) |
|
||||
| `npm run format` | Prettier (`src/`) |
|
||||
| `npm run build` | type-check + сборка |
|
||||
| `npm run proto:gen` | генерация API-клиентов из proto (после изменения proto) |
|
||||
|
||||
## 2. Структура и соглашения
|
||||
|
||||
- `src/views/*View.vue` — тонкие обёртки над страницами (только импорт и `<Page />`).
|
||||
- `src/components/*Page.vue` — страницы (GamesPage, OfficePage, TeamStoryPage…).
|
||||
- `src/components/*.vue` — переиспользуемые блоки (HeaderMenu, MessagePaper, PlaceBlock, IntroBlock…).
|
||||
- `src/api/generated/**` — **сгенерированный код, руками не редактировать.** Обновляется только через `npm run proto:gen`.
|
||||
- `src/stores/`, `src/composables/`, `src/utils/`, `src/types/` — по назначению.
|
||||
- Алиас `@/` → `src/`. Импорты: `@/components/...` для общих блоков, относительные для соседних файлов.
|
||||
- UI-тексты — на русском.
|
||||
|
||||
## 3. Правила выполнения задач
|
||||
|
||||
1. **Сначала изучи.** Прочитай `package.json`, `tsconfig.app.json`, релевантные компоненты и существующие паттерны. Следуй им; не вводи новый стек, механизмы и зависимости без согласования с пользователем.
|
||||
2. **Код:** `defineProps` с типами (`Object as PropType<T>`), типизированные `emit`, производные значения через `computed`. Не дублируй логику — выноси в `composables/`/`utils/`.
|
||||
3. **Импорты:** сортируй (simple-import-sort): сторонние → `@/` → относительные. Удаляй неиспользуемые (unused-imports). Точки с запятой не ставим, одинарные кавычки, ширина 100 (Prettier).
|
||||
4. **API:** только через сгенерированные клиенты (`getAuthClient()` и т.п.). После вызова проверяй `res.error` и показывай `message.error(res.error!)`. Поля из proto необязательны — бери с `!` как в существующем коде.
|
||||
5. **Ошибки и состояния:** используй `useMessage()` из naive-ui; загрузку — простым `ref` + асинхронная функция (существующий паттерн), поллинг — `useSimplePolling`.
|
||||
6. **Стили:** `scoped`, свойства по алфавиту (stylelint). Не добавляй новые цвета хардкодом — только палитра из раздела 4.
|
||||
7. **Адаптивность:** мобильная вёрстка по умолчанию, брейкпоинт `@media (width >= 1024px)` (существующий паттерн). Скрывай скроллбары как `.center-block-custom`.
|
||||
8. **Проверки перед сдачей (всегда):** `npm run type-check` → `npm run lint` → `npm run lint:css`. При затрагивании сборки — `npm run build`. Сообщи в ответе, какие проверки прошли.
|
||||
9. **Коммиты и push выполняет только пользователь:** агент никогда не запускает `git commit` и `git push`. Не переписывай чужой код без необходимости — минимальные целевые изменения.
|
||||
|
||||
## 4. Правила дизайна (канон «бумажного детектива»)
|
||||
|
||||
Стилистика проекта — тёмный «кабинет сыщика»: тёмный фон, «бумажные листы дел» с текстурой и шрифтом печатной машинки, бронзовые/золотые акценты, зелёный акцент интерактива.
|
||||
|
||||
### 4.1 Палитра (использовать только эти значения)
|
||||
|
||||
| Роль | Значение |
|
||||
|---|---|
|
||||
| Фон страницы | `#111` |
|
||||
| Панели / карточки / блоки | `#222` (border-radius: 10px) |
|
||||
| Основной текст | `#eee` |
|
||||
| Вторичный текст (подписи, служебное, в тёмных UI-панелях) | `#aaa`, `#777` |
|
||||
| Акцент hover/active | `#63e2b7` |
|
||||
| Бронза (PDF-ссылки) | `--second-color: rgb(97 74 22)` |
|
||||
| Золото (ключи, «требуемые ключи») | `gold` |
|
||||
| Кнопки-действия на бумаге | текст `#bfa07d`, фон — текстура `belt.png` |
|
||||
| Подписи улик/приложений | `burlywood` |
|
||||
| Текст на бумажном листе | `black` |
|
||||
|
||||
### 4.2 Типографика
|
||||
|
||||
- **UI (формы, панели, навигация):** системный стек из `base.css`, 15px.
|
||||
- **Бумажные листы дел:** `font-family: 'font_old_typer'` (шрифт подключён в `main.css`, файл `src/assets/fonts/a_OldTyper.ttf`). Контент — 18px, вес 500; заголовки всех карточек на экране игры (вступление, вопросы, точки, QR) — как заголовок точки: 18px, чёрный, по левому краю, без `letter-spacing`, вес 400.
|
||||
- Никогда не используй `font_old_typer` для UI-элементов (кнопки, формы, меню).
|
||||
|
||||
### 4.3 Бумажный лист (компонент MessagePaper)
|
||||
|
||||
Контент дел (вступление, точки, приложения) оборачивается в `MessagePaper`:
|
||||
|
||||
- Фон — текстура `paper.jpg` (`background-size: cover`), тень `0 0 5px black`, слои-подложки с поворотами `rotate(-3deg)` / `rotate(2deg)`.
|
||||
- Разделители — пунктирные `hr`: `border: dashed 1px` (на бумаге — `black`, в тёмных панелях — `#eee`).
|
||||
- **«Фотографии»** (картинка точки, картинки-улики): подложка с текстурой `paper_white.jpg`, паддинг 7px, `transform: rotate(-3deg)`, тень `0 3px 15px rgb(98 98 98)`, `cursor: zoom-in`, клик — просмотр в `n-modal` + `n-card`.
|
||||
- **Улики-картинки в потоке текста:** блок `float: right`, текст обтекает; контейнер — `display: flow-root` (BFC, чтобы не наезжало на двери).
|
||||
- **Кнопки действий («двери»):** фон `belt.png` (`background-size: cover`), текст `#bfa07d`, `border-radius: 5px`, inline-block, паддинг `5px 12px`.
|
||||
- **Сворачивание листа:** иконка `collapse.png` (45×28), развёрнутый лист — `rotate(-180deg)`.
|
||||
|
||||
### 4.4 Компоненты и иконки
|
||||
|
||||
- UI-контролы — только naive-ui (`n-*`): тёмная тема задана в `App.vue` (`NConfigProvider :theme="darkTheme"`). Не стилизуй нативные `<input>/<button>`.
|
||||
- Иконки — `@vicons` через обёртку `<Icon>` из `@vicons/utils`, размер через `size` (например `<Icon size="28"><MenuOutlined /></Icon>`).
|
||||
- Модальные окна просмотра — `n-modal` + `n-card`, ширина `min(94vw, 1200px)`, `role="dialog" aria-modal="true"`.
|
||||
|
||||
### 4.5 Раскладка страниц
|
||||
|
||||
- Фиксированный `HeaderMenu` сверху, высота 70px; контент — контейнер `.center-block-custom` (`margin-top: 70px`, высота `calc(100dvh - 70px)`, скрытый скроллбар).
|
||||
- Ширина контента: `.width700` — бумажные листы/дела, `.width1200` — списки и таблицы.
|
||||
- Карточки списков (игры, сценарии): фон `#222`, `border-radius: 10px`, hover — `color: #63e2b7` + `cursor: pointer`.
|
||||
- Интерактивные блоки-«листы» в редакторе: `.place-block-hover` — hover-рамка `1px solid #63e2b7`.
|
||||
|
||||
### 4.6 Поведение и состояния
|
||||
|
||||
- Hover интерактивных элементов — только `#63e2b7` (не изобретай новые цвета).
|
||||
- Заголовки и служебные подписи — вторичные цвета палитры (`#aaa`/`#777`), без ярких акцентов. На бумажных листах дел подписи и подсказки — чёрные (текст бумаги, раздел 4.1); `#aaa`/`#777` — для тёмных UI-панелей.
|
||||
- Новые цвета/токены добавлять только через `src/assets/base.css` в `:root` (существующие: `--main-color`, `--second-color`, `--main-back-color`, `--main-back-item-color`) — и только если без них нельзя обойтись палитрой.
|
||||
|
||||
## 5. Чек-лист перед сдачей
|
||||
|
||||
1. ✅ Соблюдены соглашения структуры и импортов (разделы 2–3).
|
||||
2. ✅ Использована только палитра и стилистика раздела 4.
|
||||
3. ✅ Адаптивность и скролл-контейнеры как в существующих страницах.
|
||||
4. ✅ `npm run type-check`, `npm run lint`, `npm run lint:css` — без ошибок (отчёт в ответе).
|
||||
5. ✅ Сгенерированный код не тронут; git commit/push не выполнялись.
|
||||
- не редактируй `src/api/generated/**` вручную;
|
||||
- после изменения `proto/main.proto` запускай `npm run proto:gen`;
|
||||
- перед сдачей запускай `npm run type-check`, `npm run lint` и `npm run lint:css`;
|
||||
- commit и push выполняет только пользователь.
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
# Стандарт написания фронтенда
|
||||
|
||||
Статус: обязательный стандарт.
|
||||
|
||||
Этот документ — единственный источник правил для нового и изменяемого кода в
|
||||
`evening_detective_frontend`. Существующий код не переписывается только ради
|
||||
соответствия стандарту: при изменении файла применяй правила к затронутому коду
|
||||
и не расширяй diff без необходимости.
|
||||
|
||||
## 1. Базовые решения
|
||||
|
||||
- Стек: Vue 3, `<script setup lang="ts">`, TypeScript, Vite, Pinia, Vue Router,
|
||||
Naive UI и `@vicons`.
|
||||
- UI-тексты пишутся на русском.
|
||||
- Новые зависимости, альтернативные UI-библиотеки и новый state manager не
|
||||
добавляются без явного разрешения пользователя.
|
||||
- Сначала переиспользуй существующий компонент, composable, util, store или
|
||||
токен. Новая абстракция нужна только при повторном использовании или когда
|
||||
без неё нарушается граница ответственности.
|
||||
- Не добавляй код «на будущее», универсальные обёртки с одним потребителем и
|
||||
дублирующие типы.
|
||||
|
||||
## 2. Куда класть новый код
|
||||
|
||||
| Что добавляется | Единственное основное место | Правило |
|
||||
|---|---|---|
|
||||
| Маршрутная страница | `src/views/*View.vue` | Только подключает страницу из `components` и не содержит бизнес-логики. |
|
||||
| Экран или крупный блок страницы | `src/components/*Page.vue` | Собирает экран, управляет его flow и передаёт данные дочерним компонентам. |
|
||||
| Переиспользуемый визуальный блок | `src/components/*.vue` | Не знает о конкретном маршруте; получает данные через props и сообщает событиями. |
|
||||
| Логика нескольких компонентов | `src/composables/use*.ts` | Состояние и lifecycle-композиция Vue; один composable — одна задача. |
|
||||
| Чистая функция без Vue-состояния | `src/utils/*.ts` | Форматирование, преобразование и вычисления; без компонентов и store. |
|
||||
| Общее состояние | `src/stores/*.ts` | Только данные и действия с общим жизненным циклом. |
|
||||
| Тип доменной модели или редактора | `src/types/*.ts` | Только типы приложения, которых нет в generated API. |
|
||||
| API-вызов | `src/api/*.ts` или store/page flow | Через сгенерированный клиент и существующий транспорт. |
|
||||
| Сгенерированный API | `src/api/generated/**` | Только результат `npm run proto:gen`; ручные правки запрещены. |
|
||||
| Глобальный CSS и токен | `src/assets/base.css` / `src/assets/main.css` | Только при действительно глобальном эффекте. |
|
||||
| Стиль компонента | `<style scoped>` компонента | Одноразовый стиль не выносить в глобальный CSS. |
|
||||
|
||||
Если код подходит под несколько строк, выбирай первую подходящую границу сверху.
|
||||
Нельзя прятать бизнес-логику в `utils`, API-вызовы в визуальном компоненте или
|
||||
локальное состояние в глобальном store.
|
||||
|
||||
## 3. Компоненты Vue
|
||||
|
||||
Каждый компонент имеет одну ответственность и читается сверху вниз: импорты;
|
||||
`props`, `emits` и локальные типы; state и `computed`; обработчики и
|
||||
асинхронные действия; template; scoped style.
|
||||
|
||||
- Используй `<script setup lang="ts">`.
|
||||
- Props и emits всегда типизируй. Для текущего проекта допустимы typed
|
||||
`defineProps` и `Object as PropType<T>`.
|
||||
- Производные значения оформляй через `computed`, не дублируй их в `ref`.
|
||||
- Локальное состояние держи в компоненте; родитель передаёт данные через props,
|
||||
ребёнок сообщает намерение через emits.
|
||||
- Не передавай весь store или необработанный API-ответ компоненту, которому
|
||||
нужен только небольшой набор полей.
|
||||
- Не делай компонент одновременно страницей, API-клиентом и универсальным
|
||||
контейнером.
|
||||
- Повторяемую логику выноси в composable только после появления реальной общей
|
||||
границы.
|
||||
|
||||
Маршрутный flow:
|
||||
|
||||
```text
|
||||
маршрут -> src/views/CatalogView.vue -> src/components/CatalogPage.vue
|
||||
```
|
||||
|
||||
`*View.vue` только подключает page-компонент. Page-компонент собирает экран,
|
||||
загружает его данные и управляет flow.
|
||||
|
||||
## 4. TypeScript и именование
|
||||
|
||||
- `PascalCase.vue` — компоненты; `camelCase.ts` — TypeScript; composable —
|
||||
`useName.ts`; store — `camelCase.ts`.
|
||||
- Компоненты, типы и интерфейсы — `PascalCase`; функции, переменные и props —
|
||||
`camelCase`; boolean — с префиксом `is`, `has`, `can` или `should`.
|
||||
- Типы protobuf импортируй из `src/api/generated/**` и не дублируй в `src/types`.
|
||||
- Типы форм и редакторов храни в `src/types` либо рядом с компонентом, если они
|
||||
не используются за его пределами.
|
||||
- Не используй `any`; неизвестное внешнее значение должно быть `unknown` с
|
||||
последующим сужением типа.
|
||||
- Не подавляй TypeScript через `as` без причины и не меняй API-контракт молча.
|
||||
- Импорты: внешние пакеты, затем `@/`, затем относительные; неиспользуемые
|
||||
импорты запрещены.
|
||||
- Без точек с запятой, одинарные кавычки, Prettier с шириной 100.
|
||||
|
||||
## 5. API, асинхронность и ошибки
|
||||
|
||||
- API вызывается только через generated clients и существующие обёртки
|
||||
(`getAuthClient()` и аналоги). Не создавай ручные fetch/axios-вызовы для уже
|
||||
описанного endpoint.
|
||||
- Ошибку обрабатывай в том же flow. Пользовательские сообщения показывай через
|
||||
`useMessage()` из Naive UI и пиши по-русски.
|
||||
- Загрузку держи в простом `ref(false)` с `try/finally`; повторную отправку
|
||||
блокируй, если она может испортить данные.
|
||||
- Поллинг делай через существующий `useSimplePolling`.
|
||||
- Ошибка не должна теряться в `catch`: покажи её или передай выше с контекстом.
|
||||
`console.error` оставляй для диагностики после пользовательской обработки.
|
||||
- Пустое, загрузочное и ошибочное состояния должны быть явными в template.
|
||||
- Не перезаписывай локальный черновик данными фонового обновления во время
|
||||
редактирования.
|
||||
|
||||
## 6. State и stores
|
||||
|
||||
- В store держи только состояние, которым пользуются разные маршруты или
|
||||
компоненты, и действия, изменяющие это состояние.
|
||||
- Не превращай store в контейнер всех запросов приложения.
|
||||
- Преобразуй API-ответ в форму для UI на границе store/page flow.
|
||||
- Секреты и токены не выводи в UI и не помещай в URL.
|
||||
- Локальный черновик держи в `ref`/`reactive`; серверное состояние
|
||||
синхронизируй явно после сохранения.
|
||||
|
||||
## 7. Стили и дизайн
|
||||
|
||||
- Компонентные стили по умолчанию пишутся в `<style scoped>`.
|
||||
- CSS-свойства располагаются в алфавитном порядке; это проверяет Stylelint.
|
||||
- Новые цвета не хардкодь: используй палитру и CSS-переменные из
|
||||
`src/assets/base.css`. Новый глобальный токен добавляй в `:root` только при
|
||||
необходимости и с понятным семантическим именем.
|
||||
- Для экранного UI используй компоненты Naive UI (`n-*`) и тему из `App.vue`, а
|
||||
не стилизацию нативных `<input>` и `<button>`.
|
||||
- Иконки подключай из `@vicons` через `Icon` из `@vicons/utils`; размер задавай
|
||||
через `size`.
|
||||
- Адаптивность проектируй mobile-first; desktop-брейкпоинт —
|
||||
`@media (width >= 1024px)`.
|
||||
- Сохраняй текущий flow: `HeaderMenu` сверху, `.center-block-custom` для
|
||||
прокрутки, `.width700` для дел и `.width1200` для списков.
|
||||
- Бумажные листы используют `MessagePaper` и `font_old_typer`; UI-формы, меню и
|
||||
кнопки этот шрифт не используют.
|
||||
- Не добавляй глобальный utility-класс для одного компонента.
|
||||
|
||||
## 8. Формы, доступность и состояния
|
||||
|
||||
- Валидируй ввод до API-вызова и учитывай серверную ошибку; клиентская проверка
|
||||
не заменяет серверную.
|
||||
- У обязательного поля есть понятная подпись и сообщение об ошибке.
|
||||
- Во время загрузки показывай состояние и не допускай повторной отправки.
|
||||
- Интерактивные элементы доступны с клавиатуры и имеют видимый focus. Не убирай
|
||||
outline без равноценной замены.
|
||||
- Модальные окна просмотра делай через `n-modal` + `n-card` с `role="dialog"`
|
||||
и `aria-modal="true"`; изображения имеют осмысленный `alt`.
|
||||
- Hover не единственный способ понять состояние: учитывай focus, disabled,
|
||||
loading, success и error.
|
||||
|
||||
## 9. Тесты и проверки
|
||||
|
||||
- Для чистой функции с нетривиальной логикой добавь небольшой тест рядом с ней
|
||||
или используй существующий механизм тестирования.
|
||||
- Не добавляй тесты для тривиального прокси или очевидной разметки; проверяй
|
||||
пользовательский flow, валидацию, преобразования и ошибки.
|
||||
- Перед передачей фронтенд-задачи запускай:
|
||||
|
||||
```bash
|
||||
npm run type-check
|
||||
npm run lint
|
||||
npm run lint:css
|
||||
```
|
||||
|
||||
- После изменений сборки, маршрутов или generated API дополнительно запускай
|
||||
`npm run build`; после изменения `proto/main.proto` сначала запускай
|
||||
`npm run proto:gen`.
|
||||
|
||||
## 10. Допустимое отклонение
|
||||
|
||||
Отклонение от стандарта требует до изменения кода: явного разрешения
|
||||
пользователя, короткого письменного обоснования и указания затронутых файлов.
|
||||
Если существующий код противоречит стандарту, не исправляй его попутно:
|
||||
исправь только необходимый участок и отдельно предложи миграцию.
|
||||
Reference in New Issue
Block a user