8.6 KiB
تدریسینو — اپِ ریاضی (فرانتاند)
اپِ وبِ موبایلمحورِ تدریسینو، آموزشِ ریاضی به سبکِ دولینگو برای پایهی سوم تا دوازدهم: نقشهای از جزیرهها برای هر
کتاب، آزمونهای کوتاه از مسئلههای خودِ کتابِ درسی، دستیارِ هوشِ مصنوعی، همراهها، زنجیرهی روزانه و اشتراک. همین
مخزن پوستهی اندرویدِ اپ را هم دارد (android/).
بکاند مخزنِ جداگانهای است (Tadrisino/MathApp) و قراردادِ API
اسکیمای OpenAPIِ همانجاست. این اپ تنها کلاینتِ آن API است.
| سایتِ زنده | https://math.tadrisino2.ir · API: https://mathapi.tadrisino2.ir |
| فناوری | React 18 · TypeScript (strict) · Vite 6 · Tailwind 4 · Motion |
| وابستگیها | عمداً کم: بیکتابخانهی router و state؛ ناوبری و دادهی مشترک در خودِ کد |
| اندروید | پوستهی WebView روی همین سایت، با پرداختِ درونبرنامهایِ کافهبازار (Poolakey)؛ بستهی com.tadrisino.math.app |
راهاندازی
npm install
npm run dev # http://localhost:5173
در حالتِ توسعه، Vite درخواستهای /api را به بکاند پاس میدهد، پس CORS مطرح نیست. پیشفرض بکاندِ محلی است
(python manage.py runserver روی پورتِ ۸۰۰۰). بدونِ بکاندِ محلی، فایلِ .env.development.local بسازید:
VITE_DEV_PROXY_TARGET=https://mathapi.tadrisino2.ir
⚠️ در این حالت هر کاری در اپ بکنید روی دیتابیسِ واقعی نوشته میشود.
| دستور | کار |
|---|---|
npm run dev |
سرورِ توسعه |
npm run typecheck |
بررسیِ نوعها (strict) |
npm run build |
type-check و بعد build در dist/ |
npm run preview |
اجرای همان build |
ساختار
src/
config.ts آدرسِ API (بخشِ پایین)
api/ تنها درِ ارتباط با سرور — هیچ جای دیگر fetch نمیزند
http.ts توکن، timeout، تکرارِ GET، refreshِ تکنسخهای، SSE، Idempotency-Key
index.ts یک تابع برای هر اندپوینت
types.ts شکلِ پاسخها، از روی پاسخِ واقعیِ سرور
app/ App (جریانِ ورود) و MainApp (تبها و صفحهها)
nav/ ناوبریِ پشتهای، هماهنگ با دکمهی back گوشی
state/ دادهی مشترک (پروفایل، نقشه، کتابِ انتخابشده، همراه) و گفتگوی دستیار
screens/ یک فایل برای هر صفحه
components/ اجزای مشترک: مسیرِ جزیرهها، نوارِ کتابها، برگهی پایین، بازخورد، …
mascots/ همراهها (سیگما، دلتا، پی، امگا): SVG از کد، شش حالتِ چهره
diagram/ شکلِ درس و جوابِ دستیار: توصیفِ JSON از بکاند → SVG؛ همهی مختصات اینجا حساب میشود
lib/ اعدادِ فارسی، تاریخِ شمسی، MathText، پیامِ خطا، صدا، پلِ کافهبازار، روشهای پرداخت
android/ پوستهی اندروید (README خودش)
pay.html · src/pay.ts صفحهی واسطِ پرداختِ زرینپال برای اپِ اندرویدِ فعلی
قاعدهها:
- کلاینت را از حافظه ننویسید. قرارداد را از اسکیمای بکاند بخوانید
(
python manage.py spectacular --file schema.yaml --format openapi) و هر تغییرِtypes.tsرا با پاسخِ واقعیِ سرور بسنجید. - صفحهها هرگز مستقیم سرور را صدا نمیزنند: همیشه
screens/* → api/index.ts → api/http.ts. - اعداد: برای نمایش
toFa، برای ورودیdigitsOnly(کیبوردِ فارسی ارقامِ۰-۹میفرستد و\dدر JS آنها را نمیشناسد). - رنگها در
src/styles/index.css(@theme) تعریف شدهاند:bg-coral،text-ink، … - خطا: پیامِ کاربر همیشه از
friendlyErrorمیآید، نه متنِ خامِ سرور. - متنِ فارسی بیاعراب و بی «ی»ِ اضافهی نوشتهشده («پایهی سوم») است (تصمیمِ شرکت)؛ تنوین («قبلاً») میماند. متنِ تازه
را همینطور بنویسید. متنِ سرور را بکاند هنگامِ ساختنِ پاسخ پاک میکند و
plainPersianدرMathTextهمان کار را برای پاسخِ زندهی دستیار.lib/plainMath.tsهر LaTeX یا markdownی را که برسد ساده میکند و باید باcontent/plain_math.pyِ بکاند همرفتار بماند.
آدرسِ بکاند و عوض کردنِ دامنه
دامنه هیچجای کد نیامده. آدرسِ API به این ترتیب خوانده میشود (src/config.ts):
dist/config.js(ازpublic/config.js) — در زمانِ اجرا؛ بعد از build هم روی سرور ویرایششدنی است.VITE_API_BASE_URL— در زمانِ build، از.env.production./api— همدامنه، وقتی nginxِ دامنهی فرانت مسیرِ/apiرا به بکاند پراکسی کند.
برای جابهجاییِ دامنه:
- سریع، بدونِ build: روی سرور در
dist/config.jsبنویسیدapiBaseUrl: "https://<دامنهی تازه>/api"و کشِ آروان را برای همین فایل پاک کنید. - ماندگار: خطِ
VITE_API_BASE_URLدر.env.productionرا عوض کنید و build بگیرید. - سمتِ بکاند دامنهی تازهی فرانت باید مجاز باشد (
FRONTEND_URL)، و در CSPِ nginx (connect-src) دامنهی تازهی API بیاید. رویهی کامل:docs/operations.mdِ بکاند، بخشِ «عوض کردنِ دامنه».
روشهای پرداخت
برگهی پرداخت روشها را از paymentMethods در dist/config.js میخواند (src/lib/paymentMethods.ts)، جدا برای مرورگر
(web) و داخلِ اپِ اندروید (app)؛ مقدارها "zarinpal" و "bazaar". پیشفرض: مرورگر فقط زرینپال، اپ هر دو. نسخهای که
فقط در کافهبازار است: paymentMethods: { app: ["bazaar"] }؛ build لازم نیست، فقط کشِ آروانِ این فایل را پاک کنید.
انتشار
روی سرور (~/mathapp_frontend_new، که nginxِ math.tadrisino2.ir از dist/ش سرو میکند):
cd ~/mathapp_frontend_new && ./deploy.sh # fetch، npm ci، type-check، build در dist.next و جابهجاییِ بیوقفه
buildِ قبلی در dist.prev میماند (برگشت: rm -rf dist && mv dist.prev dist) و dist/config.jsِ ویرایششده روی سرور به
buildِ تازه منتقل میشود. سرور مشترکِ شرکت است: پیش از هر کار آنجا قواعدِ CLAUDE.mdِ بکاند (بخشِ «Working on the
servers») را بخوانید.
جای دیگر: npm ci && npm run build و سرو کردنِ dist/. اپ مسیرِ جدا (route) ندارد و همهچیز از / بار میشود؛ فقط
index.html و config.js نباید طولانی کش شوند (باقیِ فایلها نامِ hashدار دارند). درگاهِ پرداخت کاربر را به
/?orderId=…&status=… برمیگرداند و لینکِ دعوت /?ref=CODE است؛ هر دو را خودِ اپ میخواند.
CSPِ سایت در nginx است (ops/nginx/zareian-front-headers.conf در مخزنِ بکاند). اگر اسکریپتِ درونخطیِ index.html عوض
شود، هشِ تازهاش باید در همان فایل بنشیند، وگرنه مرورگر آن را اجرا نمیکند.