- پنل «بررسی سئو» در صفحه نوشتن مقاله — سبز/نارنجی/قرمز سازگار با فارسی: طول عنوان، کلمه کلیدی هدف (در عنوان/پاراگراف اول/تیتر H2)، طول چکیده، تعداد واژه، تیتربندی، متن جایگزین تصاویر، پیوندها و slug. کلمه کلیدی در localStorage نگه داشته میشود (راهنمای ویرایشگر است، نه محتوا) - جدول seo_meta: عنوان و توضیح متای هر صفحه (page_key برای هر ۸ صفحه، seed خودکار، CRUD در /api/admin/seo-meta، خواندن در GET /api/site) - تزریق عنوان/توضیح متا در فرانتاند: صفحههای فهرست از دیتابیس؛ صفحه مقاله و پروژه از محتوای خودشان (بدون تداخل با اثر سطح والد) - دکمه سئو روی هیرو هر صفحه و کنار هیرو صفحه اصلی (فقط حالت ویرایش)
179 lines
8.9 KiB
Markdown
179 lines
8.9 KiB
Markdown
# بکاند گروه ساختمانی آرامش (Aramesh Building Group API)
|
||
|
||
بکاند سایت گروه ساختمانی آرامش — ساختهشده با **FastAPI** + **PostgreSQL** + **SQLAlchemy 2** + **JWT** + **MinIO** (ذخیره تصاویر) + **Traefik** (مسیریابی).
|
||
|
||
## امکانات
|
||
|
||
- **API عمومی محتوا**: برند، منو، هیرو، داستان، تیتر بخشها، هیرو صفحات، خدمات، پروژهها، مقالات، نظرات مشتریان، سوالات متداول، تیم، تایملاین، آمار، چرا آرامش، قبل/بعد، مدلهای سرمایهگذاری، مراحل کار، دفاتر، گالری، فرم تماس، خبرنامه و فوتر — **تمام متنهای سایت در دیتابیس است**
|
||
- **فرم تماس**: ثبت پیام مشتریان از سایت (`POST /api/contact`)
|
||
- **خبرنامه**: عضویت و مدیریت مشترکین (`POST /api/newsletter`)
|
||
- **پنل مدیریت**: ورود با نام کاربری/رمز عبور و دریافت توکن JWT، سپس CRUD کامل همه محتواها، مدیریت پیامهای تماس و مشترکین
|
||
- **آپلود تصویر**: `POST /api/admin/upload` — فایل در MinIO ذخیره و URL نسبی `/media/...` برمیگردد
|
||
- **Seed خودکار**: همه محتوای فعلی سایت با یک دستور در دیتابیس قرار میگیرد (فقط جدولهای خالی پر میشوند — ارتقا بدون از دست رفتن داده)
|
||
- مستندات تعاملی Swagger در مسیر `/docs`
|
||
|
||
## راهاندازی
|
||
|
||
### ۱. پیشنیازها
|
||
|
||
- Python 3.11 یا جدیدتر
|
||
- PostgreSQL در حال اجرا (پورت پیشفرض 5432)
|
||
|
||
### ۲. نصب وابستگیها
|
||
|
||
```bash
|
||
cd arameshplaza-backend
|
||
python -m venv .venv
|
||
|
||
# ویندوز
|
||
.venv\Scripts\activate
|
||
# لینوکس / مک
|
||
source .venv/bin/activate
|
||
|
||
pip install -r requirements.txt
|
||
```
|
||
|
||
### ۳. تنظیمات
|
||
|
||
فایل `.env.example` را به نام `.env` کپی کنید و مقادیر را تنظیم کنید:
|
||
|
||
```bash
|
||
cp .env.example .env # لینوکس / مک
|
||
copy .env.example .env # ویندوز
|
||
```
|
||
|
||
مهمترین تنظیم `DATABASE_URL` است:
|
||
|
||
```
|
||
DATABASE_URL=postgresql+psycopg://postgres:YOUR_PASSWORD@localhost:5432/arameshplaza_api
|
||
```
|
||
|
||
### ۴. ساخت دیتابیس و Seed
|
||
|
||
```bash
|
||
# ساخت دیتابیس (یکبار):
|
||
psql -U postgres -c "CREATE DATABASE arameshplaza_api;"
|
||
|
||
# ساخت جداول + وارد کردن محتوای سایت + ساخت ادمین پیشفرض:
|
||
python -m app.seed
|
||
|
||
# بازنشانی کامل دادهها در صورت نیاز:
|
||
python -m app.seed --force
|
||
```
|
||
|
||
### ۵. اجرا
|
||
|
||
```bash
|
||
uvicorn app.main:app --reload
|
||
```
|
||
|
||
سپس:
|
||
- مستندات API: http://localhost:8000/docs
|
||
- بررسی سلامت: http://localhost:8000/api/health
|
||
|
||
## ورود به پنل مدیریت
|
||
|
||
```
|
||
POST /api/auth/login
|
||
{ "username": "admin", "password": "aramesh123" }
|
||
```
|
||
|
||
پاسخ شامل `access_token` است. توکن را در هدر همه درخواستهای مدیریتی قرار دهید:
|
||
|
||
```
|
||
Authorization: Bearer <access_token>
|
||
```
|
||
|
||
> نام کاربری و رمز عبور پیشفرض از تنظیمات `.env` خوانده میشود — حتماً در محیط تولید تغییرشان دهید.
|
||
|
||
## فهرست انتهاپوینتها
|
||
|
||
### عمومی (بدون نیاز به توکن)
|
||
|
||
| متد | مسیر | توضیح |
|
||
|---|---|---|
|
||
| GET | `/api/health` | وضعیت سرور |
|
||
| GET | `/api/brand` | اطلاعات برند و تماس |
|
||
| GET | `/api/services` | خدمات |
|
||
| GET | `/api/projects` | همه پروژهها |
|
||
| GET | `/api/projects/{slug}` | جزئیات یک پروژه |
|
||
| GET | `/api/articles` | همه مقالات |
|
||
| GET | `/api/articles/{slug}` | جزئیات یک مقاله |
|
||
| GET | `/api/testimonials` | نظرات مشتریان |
|
||
| GET | `/api/faqs` | سوالات متداول |
|
||
| GET | `/api/team` | اعضای تیم |
|
||
| GET | `/api/timeline` | تایملاین شرکت |
|
||
| GET | `/api/stats` | آمار |
|
||
| GET | `/api/why-us` | چرا گروه ساختمانی آرامش |
|
||
| GET | `/api/before-after` | بخش قبل/بعد |
|
||
| GET | `/api/site` | **همه محتوا در یک درخواست** |
|
||
| POST | `/api/contact` | ثبت پیام تماس |
|
||
| POST | `/api/newsletter` | عضویت در خبرنامه |
|
||
| POST | `/api/auth/login` | ورود ادمین و دریافت توکن |
|
||
|
||
### مدیریت (نیاز به توکن Bearer)
|
||
|
||
برای هر یک از این مسیرها، CRUD کامل در دسترس است:
|
||
`brand`، `services`، `projects`، `articles`، `testimonials`، `faqs`، `team`، `timeline`، `stats`، `why-us`، `before-after`
|
||
|
||
| متد | مسیر | توضیح |
|
||
|---|---|---|
|
||
| GET/POST | `/api/admin/{resource}` | لیست / ساخت |
|
||
| GET/PUT/DELETE | `/api/admin/{resource}/{id}` | دریافت / ویرایش کامل / حذف |
|
||
| PATCH | `/api/admin/{resource}/{id}` | **ویرایش جزئی** — فقط فیلدهای ارسالشده بهروزرسانی میشوند |
|
||
| POST | `/api/admin/{resource}/reorder` | ذخیره ترتیب: `{"ids": [3, 1, 2, ...]}` |
|
||
| GET | `/api/admin/messages` | پیامهای تماس (با `?unread_only=true` فقط خواندهنشدهها) |
|
||
| PATCH | `/api/admin/messages/{id}` | تغییر وضعیت خواندهشدن |
|
||
| DELETE | `/api/admin/messages/{id}` | حذف پیام |
|
||
| GET | `/api/admin/subscribers` | مشترکین خبرنامه |
|
||
| DELETE | `/api/admin/subscribers/{id}` | حذف مشترک |
|
||
| POST | `/api/admin/upload` | آپلود تصویر (multipart، حداکثر ۱۰MB — jpg/png/webp/gif/avif) → `{"url": "/media/..."}` |
|
||
|
||
### بدنه مقاله — سند TipTap
|
||
|
||
`body` مقاله یک سند ساختاریافته TipTap (ProseMirror JSON) است: `{"type": "doc", "content": [...]}`.
|
||
- فقط ساختار اعتبارسنجی میشود (`type: "doc"` + `content` لیست)؛ امنیت رندر بر عهده
|
||
رندر استاتیک TipTap در فرانتاند است که فقط تگهای شناختهشده تولید میکند
|
||
- ردیفهای قدیمی (لیست پاراگراف) با مهاجرت idempotent `migrate_article_bodies`
|
||
در startup/seed خودکار به سند تبدیل میشوند
|
||
- seed هم بدنههای لیستی را قبل از درج تبدیل میکند
|
||
|
||
| POST/PATCH | `/api/admin/seo-meta` | عنوان و توضیح متای صفحات — `page_key`: home / about / services / projects / investment / blog / faq / contact |
|
||
|
||
منابعی که `reorder` دارند (ستون `position`): `services`، `projects`، `articles`، `testimonials`، `faqs`، `team`، `timeline`، `stats`، `why-us`، `investment-models`، `process-steps`، `offices`، `gallery`، `nav`. ستون با مهاجرت سبک idempotent هنگام startup/seed به دیتابیسهای موجود اضافه میشود.
|
||
|
||
### تصاویر و MinIO
|
||
|
||
فایلهای آپلودشده در باکت `aramesh-media` روی MinIO ذخیره میشوند و با مسیر نسبی `/media/<سال>/<ماه>/<فایل>` برگردانده میشوند. Traefik مسیر `/media` را به MinIO میبرد، پس URLها مستقل از بکاند ذخیرهسازی هستند — بعداً برای مهاجرت به R2/S3 فقط تنظیمات را عوض کنید، نه محتوای دیتابیس را.
|
||
|
||
- کنسول MinIO: `http://localhost:9001` (کاربر/رمز از `MINIO_ROOT_USER` / `MINIO_ROOT_PASSWORD` در compose)
|
||
- تصاویر عمومی و قابل نمایشاند؛ آپلود فقط با توکن ادمین انجام میشود.
|
||
|
||
## اتصال به فرانتاند
|
||
|
||
در پروژه React (پوشه `ArameshPlaza`)، فایل `src/config.ts` آدرس بکاند را نگه میدارد:
|
||
|
||
```ts
|
||
export const API_URL = import.meta.env.VITE_API_URL ?? 'http://localhost:8000'
|
||
```
|
||
|
||
در محیط تولید مقدار `VITE_API_URL` را روی آدرس عمومی API تنظیم کنید و مطمئن شوید آدرس سایت در `CORS_ORIGINS` فایل `.env` بکاند قرار دارد.
|
||
|
||
## ساختار پروژه
|
||
|
||
```
|
||
app/
|
||
├── main.py # نقطه ورود FastAPI، CORS، ثبت روترها
|
||
├── config.py # تنظیمات از .env
|
||
├── database.py # اتصال PostgreSQL و نشستها
|
||
├── models.py # مدلهای SQLAlchemy
|
||
├── schemas.py # اسکیماهای Pydantic (ورودی/خروجی)
|
||
├── auth.py # هش رمز عبور و JWT
|
||
├── seed.py # اسکریپت seed
|
||
├── seed_data.py # دادههای اولیه سایت
|
||
└── api/
|
||
├── public.py # انتهای عمومی محتوا
|
||
├── forms.py # فرم تماس و خبرنامه
|
||
└── admin.py # ورود و پنل مدیریت
|
||
```
|