MMD cfe5512ec7 فرانت‌اند: ویرایشگر WYSIWYG وبلاگ (TipTap) با آپلود تصویر در متن
- ArticleEditor: ویرایشگر TipTap v3 راست‌به‌چسب با نوار ابزار فارسی —
  بولد/ایتالیک/زیرخط/خط‌خورده، تیتر H2/H3، لیست نقطه‌ای/شماره‌ای،
  نقل‌قول، لینک (مسدودسازی javascript: با isAllowedUri)، واگرد/ازنو
- درج تصویر داخل متن: دکمه آپلود، چسباندن یا کشیدن فایل — ذخیره در
  MinIO از طریق /api/admin/upload و درج URL نسبی /media/...
- ذخیره خودکار: debounce ۸۰۰ms + flush هنگام بستن کشو
- کشوی مقاله عریض‌تر (max-w-3xl)؛ فیلد body مقالات به‌جای لیست متنی،
  ویرایشگر WYSIWYG رندر می‌کند
- رندر صفحه مقاله: تبدیل سند به HTML با @tiptap/static-renderer
  (فقط تگ‌های شناخته‌شده — بدون ریسک XSS) + استایل‌های .article-body
  (تیتر با خط مسی، لیست، نقل‌قول، تصویر) + پشتیبانی از ردیف‌های قدیمی
- وابستگی‌های جدید: @tiptap/react، @tiptap/pm، @tiptap/starter-kit،
  @tiptap/extension-image، @tiptap/extension-link، @tiptap/static-renderer
2026-09-06 23:33:08 +03:30

گروه ساختمانی آرامش — پروژه کامل (فرانت‌اند + بک‌اند)

مونوریپوی سایت گروه ساختمانی آرامش شامل:

  • 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 (ساده‌ترین راه)

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 را می‌سازد و خواندن عمومی را فعال می‌کند

اجرای محلی (توسعه)

بک‌اند

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

فرانت‌اند

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 هم می‌مانند

نکات امنیتی

  • فایل .env هرگز commit نمی‌شود (در .gitignore است)
  • رمز عبور ادمین با bcrypt هش می‌شود
  • توکن‌های JWT امضا دارند و مدت اعتبارشان قابل تنظیم است
  • تصاویر باکت MinIO عمومی (فقط خواندن) هستند؛ آپلود فقط با توکن ادمین ممکن است
S
Description
No description provided
Readme
61 MiB
Languages
TypeScript 53%
Python 37.6%
JavaScript 5.2%
Shell 2%
CSS 1.5%
Other 0.6%