steelforesight/README_FA.md

16 KiB
Raw Blame History

راهنمای جامع پروژه اندیشکده فولاد آینده (Andishkade Foolad)

این سند، راهنمای فنی و معماریِ پروژه اندیشکده فولاد آینده است — یک پلتفرم تحلیلیِ صنعت فولاد، شاملِ یک وب‌سایتِ محتوایی و یک پنلِ مدیریت/بک‌اند. در این سند ساختار پوشه‌ها، پشته‌ی فناوری، پایگاه داده، احراز هویت، قابلیت‌ها و نحوه‌ی استقرار توضیح داده شده است.


فهرست مطالب


۱. ساختار کلی پروژه

پروژه یک مونوریپو با دو اپلیکیشنِ مستقل و کنارهم (sibling) است که هیچ build یا وابستگیِ مشترکی ندارند؛ فرانت‌اند فقط در زمانِ اجرا (runtime) و از طریق متغیر VITE_PANEL_API با پنل حرف می‌زند.

andishkade-foolad/
├── frontend/               # وب‌سایت عمومی — Vite + React 19 + TypeScript
│   ├── src/
│   │   ├── app/            # مسیریابی (router) و قالب اصلی (RootLayout)
│   │   ├── components/     # کامپوننت‌های اشتراکی و UI
│   │   ├── context/        # کانتکست‌ها: زبان (LangContext) و احراز هویت (AuthContext)
│   │   ├── content/ data/  # داده‌های اولیه/ماک + ماژول‌های bootstrap که از پنل واکشی می‌کنند
│   │   └── pages/          # صفحات سایت
│   ├── public/             # دارایی‌های استاتیک، فونت‌ها، manifest و service worker (PWA)
│   ├── index.html
│   ├── vite.config.ts  tsconfig*.json  eslint.config.js
│   ├── Dockerfile  nginx.conf  liara.json   # استقرار به‌صورت سرور استاتیک Nginx روی پورت ۷۸۶۰
│   └── package.json
├── panel/                  # بک‌اند (Express API) + پنلِ مدیریت (CMS) — یک اپ واحد
│   ├── server.js           # سرور و همه‌ی Routeهای API
│   ├── db.js               # اتصال PostgreSQL + facade شبیه better-sqlite3 + مپ ردیف‌ها
│   ├── public/             # رابط کاربری پنل (SPA با Vanilla JS، بدون build)
│   ├── uploads/            # آپلودِ محلی (در صورت نبودِ S3)
│   ├── liara.json
│   └── package.json
├── docker-compose.yml      # اجرای لوکالِ فرانت (context: ./frontend)
├── CLAUDE.md  README.md  README_FA.md  SECURITY.md  design-system.md

نکته: پنل هم بک‌اندِ API است و هم CMS (رابطِ مدیریت را از panel/public/ سرو می‌کند). این دو به‌هم گره خورده‌اند و یک اپلیکیشنِ واحدند.


۲. فرانت‌اند (frontend/)

پورتالِ محتواییِ فارسی‌محور (Persian-first)، دوزبانه (fa/en) و RTL با انیمیشن‌های غنی.

پشته‌ی فناوری

  • هسته: React 19 + TypeScript.
  • بیلد: Vite (HMR در توسعه، خروجی بهینه در پروداکشن). اعتبارسنجیِ سریع: npx tsc -b --noEmit.
  • استایل: عمدتاً style اینلاین + کلاس‌های Tailwind CSS v4 برای واکنش‌گرایی (max-md: …) + متغیرهای CSS در src/index.css. رنگِ سازمانی: طلایی #CD9E53 و سورمه‌ای #032340 (در بسیاری فایل‌ها به‌صورت const GOLD/const NAVY هاردکد شده‌اند).
  • مسیریابی: React Router DOM v7 (createBrowserRouter). RootLayout همه‌ی صفحات را با Header/Footer و موتورِ اسکرول می‌پیچد.
  • انیمیشن و اسکرول:
    • GSAP + ScrollTrigger: انیمیشن‌های مبتنی بر اسکرول.
    • Lenis: اسکرولِ نرم هماهنگ با تیکرِ GSAP — فقط دسکتاپ (روی لمسی به مومنتومِ بومیِ سیستم‌عامل واگذار می‌شود تا لگ نشود).
    • Framer Motion: میکروانیمیشن‌ها، پاپ‌آپ‌ها و ترنزیشن‌ها.
  • سه‌بعدی و نقشه: Three.js + React Three Fiber، three-globe و react-globe.gl برای کره‌ی زمینِ تعاملی.
  • نمودار: ApexCharts (صفحه‌ی Market).
  • مدیریت وضعیت: صرفاً React Context (زبان و احراز هویت). بدون کتابخانه‌ی state خارجی.

قابلیت‌های کلیدی

  1. دوزبانه/RTL: هوک useLang() (src/context/LangContext) مقدار { lang, toggle } می‌دهد؛ کامپوننت‌ها دیکشنریِ درون‌خطیِ { fa, en } دارند و جهتِ صفحه با dir تنظیم می‌شود.
  2. اعدادِ فارسی: یک «بومی‌سازِ ارقام» در RootLayout همه‌ی ارقامِ لاتینِ نمایش‌داده‌شده را در حالتِ فارسی به فارسی تبدیل می‌کند (با MutationObserver برای محتوای دیرلودشده).
  3. تاریخ شمسی: بدون کتابخانه‌ی تاریخ — مستقیماً با Intl.DateTimeFormat('fa-IR-u-ca-persian', …).
  4. PWA و موبایل: manifest + service worker (نصب‌پذیری + کشِ آفلاین)؛ صفحه روی موبایل غیرقابلِ زوم است (viewport + بلوکِ pinch/double-tap برای iOS).
  5. جستجوی سراسری: آیکونِ سرچِ هدر → صفحه‌ی /search که به‌صورت کلاینت‌ساید روی همه‌ی محتوا (گزارش‌ها، مطالب، «در یک نگاه»، رادار آینده، ویدیوکست/پادکست، رویدادها) می‌گردد و به صفحه‌ی جزئیاتِ هر مورد لینک می‌دهد.

دستورات (در پوشه‌ی frontend/)

cd frontend
npm install
npm run dev            # سرورِ توسعه‌ی Vite (HMR)
npx tsc -b --noEmit    # فقط type-check (سریع‌ترین حلقه‌ی اعتبارسنجی)
npm run lint           # ESLint
npm run build          # tsc -b && vite build → خروجی در dist/
npm run preview        # پیش‌نمایشِ بیلدِ پروداکشن

برای دیدنِ دادهٔ واقعیِ پنل در حالتِ توسعه:

VITE_PANEL_API=https://cms-steelforesight.liara.run npm run dev

هیچ فریم‌ورکِ تستی پیکربندی نشده؛ «تأیید» یعنی tsc تمیز + بازدیدِ سرورِ در حالِ اجرا.


۳. پنل مدیریت و بک‌اند (panel/)

سرورِ Express که هم API می‌دهد و هم رابطِ مدیریت (CMS) را سرو می‌کند.

پشته‌ی فناوری

  • سرور: Express 4 روی Node.js.
  • پایگاه داده: PostgreSQL (لیارا) با ماژول pg (Pool روی DATABASE_URL). در db.js یک facadeِ شبیهِ better-sqlite3 ساخته شده: db.prepare(sql).get/all/run(...)همه async و باید await شوند. جداول و ایندکس‌ها در زمانِ استارت‌آپ به‌صورت idempotent ساخته/مهاجرت می‌شوند.
  • امنیت/احراز هویت: bcryptjs (هشِ گذرواژه)، jsonwebtoken (کوکیِ HttpOnly با Secure/SameSite پشتِ TLS)، helmet (هدر/CSP)، express-rate-limit (محدودسازیِ ورود و فرمِ تماس). CORS با ALLOWED_ORIGINS کنترل می‌شود (و در توسعه هر localhost).
  • آپلود و تصویر: multer (بافرِ حافظه) + sharp (چرخشِ EXIF، ریسایز تا ۲۰۰۰px و خروجیِ WebP). pdf-parse برای استخراجِ متنِ PDF.
  • ذخیره‌سازی: S3-compatible (object storage لیارا) در صورتِ تنظیمِ متغیرها؛ وگرنه fallback به دیسکِ محلی panel/uploads/.
  • هوش مصنوعی: SDKهای OpenAI و Anthropic (Claude) برای خلاصه‌سازی و استخراجِ دادهٔ کلیدی از اسناد.
  • رابطِ مدیریت: SPA با Vanilla JS در panel/public/ (بدون build). تب‌ها در دو گروه: محتوا (در یک نگاه، رادار آینده، ویدیوکست/پادکست، رویدادها، بنرها) و کاربران (کاربران سایت، خبرنامه).

دستورات (در پوشه‌ی panel/)

cd panel
npm install
npm run seed     # ساختِ ادمینِ اولیه از روی .env (ADMIN_USERNAME/PASSWORD)
npm start        # node server.js → http://localhost:3001
npm run dev      # node --watch server.js

۴. پایگاه داده

جداولِ اصلی (PostgreSQL):

جدول کاربرد
users ادمین‌های پنل با نقشِ admin یا owner
articles مقالات/گزارش‌ها (مدلِ منعطف؛ با category/type تفکیک می‌شود)
radar_items آیتم‌های «در یک نگاه» در ۵ دسته: market/tech/commodity/geo/energy
radar_pages صفحاتِ «رادار آینده» (مقاله‌ی بلوکیِ هر زیرمنو)
risk_signals سیگنال‌های ریسک با سطوحِ critical…opportunity
events رویدادهای تقویم
team_members اعضای تیم/خبرگان
market_prices, market_chart_points قیمت‌ها و نمودارهای صفحه‌ی Market (دستی، ادیت‌شونده در پنل)
banners, integrations, institute_stats, vision_items, advisory_board, plans, factory_reports بخش‌های مختلفِ محتواییِ سایت
members اعضای ثبت‌نامیِ سایت (موبایل/OTP) + last_login, is_active
purchases خریدِ گزارش‌های غیررایگانِ اعضا
member_activity لاگِ فعالیتِ اعضا (بازدیدِ صفحه + کلیک)
subscribers ایمیل‌های عضویت در خبرنامه (فرمِ فوتر)

جدولِ prices (اسکرپرِ قدیمیِ tgju) دیگر استفاده نمی‌شود؛ اسکرپرِ زنده حذف شده و صفحه‌ی Market از market_prices می‌خواند.


۵. احراز هویت و اعضا

دو نشستِ مجزا:

  • ادمینِ پنل: کوکیِ session (جدولِ users). نقشِ owner می‌تواند ادمین‌ها و اعضا را حذف کند.
  • عضوِ سایت: کوکیِ member_session (جدولِ members).

ورود/ثبت‌نامِ اعضا با موبایل + کدِ یک‌بارمصرف (OTP): ارسالِ پیامک با کاوه‌نگار (KAVENEGAR_API_KEY). در نبودِ کلید (محیطِ لوکال) کد در کنسولِ سرور چاپ می‌شود تا تست ممکن باشد. بازنشانیِ رمز هم از طریقِ SMS ممکن است.

مدیریتِ کاربران در پنل (تب «کاربران سایت»): فهرستِ اعضا با شماره و آخرین ورود، صفحه‌ی جزئیات (خریدها + تایم‌لاینِ فعالیت: بازدید/کلیکمسدودسازی/رفعِ مسدودی (is_active) و حذف. عضوِ مسدودشده در سمتِ سایت هم اثر می‌گیرد: AuthContext نشست را هنگامِ لود و بازگشتِ فوکوسِ تب با /api/members/me اعتبارسنجی می‌کند و در صورتِ 403 کاربر را خارج می‌کند.


۶. اتصال فرانت‌اند به پنل (Wiring)

فرانت‌اند هنگامِ استارت‌آپ، محتوای چند بخش را از پنل واکشی می‌کند (در frontend/src/main.tsx توابعِ bootstrap* فراخوانی می‌شوند) و در صورتِ در دسترس نبودنِ پنل به دادهٔ ایستای داخلِ src/content و src/data به‌عنوان fallback برمی‌گردد. نمونه‌ها: /api/articles (گزارش‌ها)، /api/radar (در یک نگاه)، /api/events، /api/market-prices و غیره. احراز هویتِ اعضا از طریقِ AuthContext و مسیرهای /api/members/* انجام می‌شود.

آدرسِ پنل از متغیرِ VITE_PANEL_API خوانده می‌شود (در پروداکشن هنگامِ build در Dockerfile مقدارِ https://cms-steelforesight.liara.run به باندل تزریق می‌شود).


۷. فهرست APIها

خواندنی‌ها عمومی‌اند؛ نوشتنی‌ها (POST/PUT/PATCH/DELETE) نیازمندِ کوکیِ نشست یا هدرِ Authorization: Bearer <token> هستند.

متد مسیر احراز هویت توضیح
POST /api/auth/login /logout — / — ورود/خروجِ ادمین
GET /api/auth/me ادمین مشخصاتِ ادمینِ جاری
GET/POST/PUT/DELETE /api/articles[...] خواندن آزاد / نوشتن ادمین CRUD مقالات
GET/POST/PUT/DELETE /api/radar, /api/radar-pages, /api/events, /api/banners, /api/risks, /api/team, /api/market-prices خواندن آزاد / نوشتن ادمین CRUD بخش‌های محتوایی
POST /api/uploads, /api/uploads/raw ادمین آپلودِ تصویر (→WebP) / ویدیو و PDF (→S3)
POST /api/admin/import ادمین ایمپورتِ دادهٔ تحلیلیِ هوش مصنوعی
POST /api/members/otp/send /otp/verify ورود/ثبت‌نام با OTP
POST /api/members/register-verify تکمیلِ ثبت‌نام پس از تأییدِ کد
GET/PUT /api/members/me عضو پروفایلِ عضو
GET /api/members/me/purchases[...] عضو خریدها و دانلودِ گزارش
POST /api/members/activity عضو ثبتِ فعالیت (بازدید/کلیک)
GET /api/members /api/members/:id /:id/activity ادمین فهرست/جزئیات/فعالیتِ اعضا
PATCH/DELETE /api/members/:id ادمین/owner مسدودسازی/حذفِ عضو
POST/GET/DELETE /api/newsletter[...] نوشتن آزاد / خواندن ادمین عضویت در خبرنامه و مدیریتِ آن
POST /api/contact فرمِ تماس با ما
GET /api/health سلامتِ سرور

۸. استقرار (Deployment)

هر دو اپ روی لیارا (Liara) مستقر می‌شوند (دو اپِ جدا).

فرانت‌اند — اپِ steelforesight

خروجیِ استاتیک، با Dockerfileِ دو‌مرحله‌ای: مرحله‌ی Node برای vite build و سپس Nginxِ سبک برای سروِ dist/ روی پورتِ ۷۸۶۰ (سازگار با Hugging Face Spaces).

cd frontend
liara deploy --app steelforesight --platform docker --port 7860 --build-location iran

VITE_PANEL_API هنگامِ build از طریقِ ARG در Dockerfile تزریق می‌شود.

پنل — اپِ cms-steelforesight

cd panel
liara deploy --app cms-steelforesight --platform node --build-location iran

متغیرهای محیطیِ لازم (در کنترل‌پنلِ هاست):

  • DATABASE_URL — اتصالِ PostgreSQL.
  • JWT_SECRET — رشته‌ی تصادفیِ بلند (≥۳۲ کاراکتر).
  • ADMIN_USERNAME / ADMIN_PASSWORD — برای npm run seed.
  • ALLOWED_ORIGINS — دامنه‌ی فرانت برای عبور از CORS.
  • KAVENEGAR_API_KEY — ارسالِ پیامکِ OTP.
  • اختیاری: متغیرهای ایمیل و object storage (LIARA_ENDPOINT, LIARA_BUCKET, LIARA_ACCESS_KEY, LIARA_SECRET_KEY).