Skip to content

Repository files navigation

VGate User Frontend

User-facing portal for VGate, built with Vue 3 + Vite + TypeScript. Customers use it to log in, subscribe to a node, browse plans, place and pay orders, and monitor their traffic. It talks to the manager's REST API under /api/v1.

When paying, the order's pay_mode drives the UX: a QR code is shown whenever pay_mode === 'qr' (with a provider-aware hint covering both Alipay and WeChat Pay), an iap (Apple in-app) mode sends the user to complete the purchase in the iOS app, and otherwise the portal opens a redirect link (e.g. Alipay / Stripe / PayPal Checkout). Note the iap handling applies to the plans, traffic-packages, and change-plan flows — the Orders page's "Pay" action only distinguishes qr from everything else, so an iap order there opens its pay_url in a new tab instead.

The dashboard shows the user's effective speed cap (sourced from the active plan or a manual override), and the orders page displays the payment platform (alipay / wechat / stripe / paypal / apple / manual, …) for each order.

Tech stack

Prerequisites

  • Node.js 18+
  • npm (this project ships package-lock.json only — there is no pnpm-lock.yaml, so use npm, not pnpm)

Getting started

# install dependencies
npm install

# start the dev server (http://localhost:5174)
npm run dev

# type-check without emitting (vue-tsc)
npm run typecheck

# production build → dist/
npm run build

# preview the production build locally
npm run preview

Dev proxy

In development, Vite proxies /api to the manager backend at http://localhost:8081 (see server.proxy in vite.config.ts), so the app talks to the backend without CORS issues during local development. The user dev server runs on port 5174 (the admin frontend uses 5173).

Configuring the API address

The API base URL is read at runtime from a global variable (window.__ENV__.API_BASE_URL) injected by public/env.js. The file is copied verbatim into dist/env.js on build and is not bundled, so you can edit the backend address after deployment without rebuilding.

src/api/http.ts uses it as the axios baseURL, falling back to the relative path /api/v1 when it is empty:

// dist/env.js  — edit this file on the deployed server
window.__ENV__ = { API_BASE_URL: '' }   // ''  → relative /api/v1 (reverse-proxy / same-origin)
// window.__ENV__ = { API_BASE_URL: 'http://192.168.1.10:8081/api/v1' }  // separate host:port
  • Leave API_BASE_URL empty when the frontend and backend are served from the same origin (e.g. behind an Nginx reverse proxy that routes /api to the manager).
  • Set the full backend URL (including the /api/v1 path) when the manager runs on a different host/port. In that case the manager must allow the frontend origin via its CORS allowed_origins system config.

Authentication model (different from the admin)

User sessions use JWT access tokens that are not refreshable. The axios response interceptor in src/api/http.ts treats a 401 as "session expired": it clears the stored token and redirects the user to /login (there is no silent auto-refresh, unlike the admin console). The login form also supports a Cloudflare Turnstile field (cf_turnstile_response) when the manager requires it.

Registration auto-logs-in: POST /user/register returns a session on both 201 (active) and 202 (pending email verification), so a new user lands straight on the dashboard's verify banner. The Register option appears inside the /login page only when the manager enables self-service registration (user.register_enabled). Email verification gates purchases and proxy traffic, not login — an unverified user can browse but cannot place orders or consume traffic until email_verified is true. The /verify-email page (also reachable while already logged in) completes verification and clears the banner.

Routes / pages

  • Public (no auth): /login, /verify-email
  • Protected (under UserLayout, require auth):
    • / — Dashboard
    • /subscription — current subscription + QR code
    • /plans — browse and pick a plan
    • /orders — order history and pending orders
    • /traffic — traffic usage
    • /traffic-packages — buy one-off traffic add-on packages (requires an active plan)
    • /invites — invite codes / referral
    • /redeem — redeem a redemption code (issued by the admin console)
    • /announcements — system announcements
    • /tickets — support tickets (open, reply, close; choose Telegram/email notifications)
    • /settings — account settings / change password, and link a Telegram account

Unauthenticated users hitting a protected route are redirected to /login (?redirect=…). The one public-route exception is /verify-email, which stays reachable while authenticated so a logged-in, unverified user can complete verification; every other public route sends an authenticated visitor to the dashboard.

Telegram & support tickets

  • Telegram binding — link a personal Telegram account from Settings through a /start deep link. Once linked, you can receive ticket alerts there.
  • Support tickets — open tickets from the Tickets page, reply in the thread, and close your own ticket once it is resolved. When creating a ticket you choose how you are notified of admin replies: Telegram (the default when your account is linked), Email, or None.

Deployment

  1. npm run build produces a static dist/ directory.
  2. Serve dist/ with any static file server (Nginx, Caddy, etc.).
  3. Edit dist/env.js to point API_BASE_URL at your manager backend.
  4. (Recommended) Put a reverse proxy in front so /api is forwarded to the manager — then API_BASE_URL can stay empty and no CORS configuration is needed.

About

Vue 3 customer portal where users log in, subscribe to a node, browse plans, place/pay orders, and monitor their traffic and invites.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages