# گروه ساختمانی آرامش — پروژه کامل (فرانت‌اند + بک‌اند) مونوریپوی سایت گروه ساختمانی آرامش شامل: - **`frontend/`** — سایت React + Vite + Tailwind (تمام متن‌ها و تصاویر از API خوانده می‌شود) - **`backend/`** — بک‌اند FastAPI + SQLAlchemy 2 + PostgreSQL + JWT + MinIO ## معماری ``` Traefik (پورت ۵۱۷۳ — تنها نقطه ورود) ├── / → Caddy (فایل‌های استاتیک SPA) ├── /api → FastAPI (بک‌اند) └── /media → MinIO (باکت aramesh-media — تصاویر آپلودی) ``` - **همه محتوای متنی سایت در PostgreSQL است** — هیچ متنی در کد فرانت‌اند هاردکد نشده؛ با یک درخواست `GET /api/site` بارگذاری و از پنل مدیریت ویرایش می‌شود - **تصاویر آپلودی در MinIO** (Object Storage سازگار با S3) ذخیره می‌شوند و با مسیر نسبی `/media/...` برگردانده می‌شوند — بک‌اند ذخیره‌سازی بدون تغییر محتوای دیتابیس قابل تعویض است - مسیریابی همه‌چیز روی **Traefik** است (با Docker labels) — nginx در پروژه وجود ندارد ## ساختار ``` ├── frontend/ # سایت React │ ├── src/ # کد منبع (api.tsx = لایه اتصال به بک‌اند) │ ├── Dockerfile # بیلد Node + سرو استاتیک با Caddy │ └── Caddyfile # فقط سرو فایل‌های استاتیک (مسیریابی روی Traefik است) ├── backend/ # بک‌اند FastAPI │ ├── app/ # کد منبع (آپلود تصویر: app/api/admin.py) │ ├── requirements.txt │ ├── Dockerfile │ └── .env.example └── docker-compose.yml # اجرای کامل با یک دستور ``` ## اجرا با Docker (ساده‌ترین راه) ```bash docker compose up --build ``` - سایت: http://localhost:5173 (از طریق Traefik) - مستندات API: http://localhost:8001/docs (با `docker-compose.override.yml` محلی) - کنسول MinIO: http://localhost:9001 — کاربر/رمز از متغیرهای `MINIO_ROOT_*` در compose - دیتابیس PostgreSQL و آبجکت‌استور MinIO هر دو در کانتینر جدا با volume دائمی - بک‌اند هنگام شروع، خودش جداول را می‌سازد و **فقط جدول‌های خالی** را seed می‌کند — ارتقای نسخه داده‌های فعلی را از بین نمی‌برد - در اولین اجرا، سرویس `minio-setup` باکت `aramesh-media` را می‌سازد و خواندن عمومی را فعال می‌کند ## اجرای محلی (توسعه) ### بک‌اند ```bash cd backend python -m venv .venv .venv\Scripts\activate # ویندوز — در لینوکس: source .venv/bin/activate pip install -r requirements.txt # فایل .env از روی .env.example بسازید و DATABASE_URL را تنظیم کنید python -m app.seed # ساخت جداول + محتوای اولیه uvicorn app.main:app --reload ``` ### فرانت‌اند ```bash cd frontend npm install npm run dev ``` در حالت توسعه، Vite درخواست‌های `/api` و `/media` را به Traefik (پورت ۵۱۷۳) پروکسی می‌کند؛ پس استک Docker باید در حال اجرا باشد. آدرس بک‌اند در `frontend/src/config.ts` از `VITE_API_URL` خوانده می‌شود — پیش‌فرض خالی یعنی درخواست‌های هم‌مبدأ. ## امکانات بک‌اند - **API عمومی**: برند، منو، هیرو، خدمات، پروژه‌ها، مقالات، نظرات، سوالات متداول، تیم، تایم‌لاین، آمار، دفاتر، مدل‌های سرمایه‌گذاری و... — همه در دیتابیس - **فرم تماس** `POST /api/contact` و **خبرنامه** `POST /api/newsletter` - **پنل مدیریت** با JWT: ورود `POST /api/auth/login` (پیش‌فرض: `admin` / `aramesh123`) و سپس CRUD کامل همه محتواها در `/api/admin/...` - **آپلود تصویر** `POST /api/admin/upload` (فقط توکن ادمین، حداکثر ۱۰MB) — فایل در MinIO ذخیره و URL نسبی `/media/...` برمی‌گردد - **ویرایش جزئی** `PATCH /api/admin/{resource}/{id}` — فقط فیلدهای ارسال‌شده عوض می‌شوند - **ترتیب‌بندی** `POST /api/admin/{resource}/reorder` — با `{"ids": [...]}` - همه محتوا در یک درخواست: `GET /api/site` > در محیط واقعی حتماً `SECRET_KEY`، `ADMIN_PASSWORD` و `MINIO_ROOT_PASSWORD` را تغییر دهید. ## ویرایش زنده سایت (دوقلوی دیجیتال) ادمین‌ها نیازی به داشبورد جدا ندارند — خود سایت ویرایشگر است: 1. به `/admin/login` بروید و وارد شوید 2. نوار شناور پایین صفحه ظاهر می‌شود؛ **حالت ویرایش** را روشن کنید 3. روی هر متن کلیک کنید و ویرایش کنید — **خروج از کادر، بلافاصله ذخیره می‌شود** (Enter ذخیره، Esc لغو)؛ وضعیت ذخیره در نوار پایین دیده می‌شود 4. آیتم‌های مجموعه‌ها (خدمات، پروژه‌ها، مقالات، نظرات، تیم و...) با هاور، دکمه‌های ویرایش / حذف / جابه‌جایی ترتیب نشان می‌دهند؛ دکمه «افزودن» هم انتهای هر لیست هست 5. تصویرها از همان کشوها به MinIO آپلود می‌شوند - در حالت ویرایش، لینک‌ها کلیک نمی‌شوند تا ویرایش متن ممکن باشد - بازدیدکننده‌های عادی هیچ اثری از این لایه نمی‌بینند (بدون توکن، همه درخواست‌های مدیریتی `401` برمی‌گردند) - تمام تغییرها بلافاصله در PostgreSQL ثبت می‌شوند — با Ctrl+F5 هم می‌مانند ## وبلاگ — نوشتن با ویرایشگر WYSIWYG مقالات با ویرایشگر غنی **TipTap** نوشته می‌شوند (همان تجربه Medium): - در حالت ویرایش، روی هر مقاله در صفحه وبلاگ دکمه ویرایش را بزنید — کشوی نوشتن باز می‌شود - تیتر (H2/H3)، بولد/ایتالیک/زیرخط، لیست نقطه‌ای و شماره‌ای، نقل‌قول، لینک و واگرد - **درج تصویر داخل متن**: دکمه تصویر، یا چسباندن/کشیدن تصویر داخل نوشته — فایل مستقیم در MinIO ذخیره و در متن قرار می‌گیرد - راست‌به‌چپ کامل با فونت و تم سایت - ذخیره خودکار: هر مکث کوتاه در تایپ، تغییرها را ذخیره می‌کند؛ بستن کشو هم ذخیره می‌کند **فرمت ذخیره**: بدنه مقاله یک سند ساختاریافته TipTap (JSON) در PostgreSQL است — نه HTML خام. صفحه مقاله آن را با رندر استاتیک TipTap به HTML تبدیل می‌کند، پس فقط تگ‌های شناخته‌شده (پاراگراف، تیتر، لیست، نقل‌قول، تصویر، لینک) تولید می‌شوند. مقالات قدیمی (لیست پاراگراف) در اولین اجرا به‌صورت خودکار به این فرمت تبدیل می‌شوند. ## نکات امنیتی - فایل `.env` هرگز commit نمی‌شود (در `.gitignore` است) - رمز عبور ادمین با bcrypt هش می‌شود - توکن‌های JWT امضا دارند و مدت اعتبارشان قابل تنظیم است - تصاویر باکت MinIO عمومی (فقط خواندن) هستند؛ آپلود فقط با توکن ادمین ممکن است