├── .dockerignore ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ ├── frontend-bundle-analysis.yml │ └── test-suite.yml ├── .gitignore ├── .node-version ├── LICENSE ├── README.md ├── README_CN.md ├── biome.json ├── docker-compose.yaml ├── docs ├── .gitignore ├── .node-version ├── biome.json ├── components.json ├── image-loader.ts ├── next.config.ts ├── package.json ├── pages │ ├── _meta.json │ ├── development │ │ ├── _meta.json │ │ └── auth.md │ ├── index.mdx │ ├── quickstart.mdx │ └── upgrade │ │ ├── log.mdx │ │ └── v1tov3.mdx ├── pnpm-lock.yaml ├── postcss.config.mjs ├── public │ ├── icon.png │ └── images │ │ ├── content-safe │ │ └── baidu.png │ │ ├── email │ │ ├── elastice-01.png │ │ ├── mailgun-01.png │ │ ├── mailgun-02.png │ │ ├── mailgun-03.png │ │ ├── mailgun-04.png │ │ ├── mailgun-05.png │ │ ├── mailgun-06.png │ │ ├── mailgun-07.png │ │ └── wechat-01.png │ │ ├── pay │ │ └── xunhu-01.png │ │ └── sms │ │ └── unisms-01.png ├── src │ ├── app │ │ ├── _meta.tsx │ │ ├── changelog │ │ │ ├── [...mdxPath] │ │ │ │ ├── action.ts │ │ │ │ ├── layout.tsx │ │ │ │ └── page.tsx │ │ │ ├── _meta.ts │ │ │ └── page.tsx │ │ ├── docs │ │ │ ├── _meta.tsx │ │ │ ├── alert │ │ │ │ └── page.mdx │ │ │ ├── analysis │ │ │ │ └── page.mdx │ │ │ ├── architecture │ │ │ │ ├── architecture.png │ │ │ │ └── page.mdx │ │ │ ├── develop │ │ │ │ ├── component.tsx │ │ │ │ └── page.mdx │ │ │ ├── import │ │ │ │ └── page.mdx │ │ │ ├── install │ │ │ │ └── page.mdx │ │ │ ├── manage │ │ │ │ ├── manage-dark.png │ │ │ │ ├── manage-light.png │ │ │ │ └── page.mdx │ │ │ ├── metrics │ │ │ │ ├── metrics-dark.png │ │ │ │ ├── metrics-light.png │ │ │ │ └── page.mdx │ │ │ ├── open-source │ │ │ │ └── page.mdx │ │ │ ├── page.mdx │ │ │ ├── roadmap │ │ │ │ └── page.mdx │ │ │ └── webpage │ │ │ │ └── page.mdx │ │ ├── faq │ │ │ ├── _meta.tsx │ │ │ └── page.mdx │ │ ├── layout.tsx │ │ ├── page.tsx │ │ ├── pricing │ │ │ └── page.tsx │ │ ├── self-hosting │ │ │ ├── _meta.tsx │ │ │ ├── install │ │ │ │ ├── _meta.ts │ │ │ │ ├── docker │ │ │ │ │ └── page.mdx │ │ │ │ ├── manual │ │ │ │ │ └── page.mdx │ │ │ │ ├── page.mdx │ │ │ │ └── serverless │ │ │ │ │ └── page.mdx │ │ │ └── page.mdx │ │ ├── showcase │ │ │ ├── _meta.tsx │ │ │ └── page.mdx │ │ ├── sponsor │ │ │ └── page.mdx │ │ └── support │ │ │ └── page.mdx │ ├── components │ │ ├── authors.tsx │ │ ├── background.tsx │ │ ├── changelog │ │ │ └── index.tsx │ │ ├── github-badge.tsx │ │ ├── icons │ │ │ ├── gcp.tsx │ │ │ ├── github.tsx │ │ │ ├── logo.tsx │ │ │ └── telegram.tsx │ │ ├── landing │ │ │ ├── feature-bento.tsx │ │ │ ├── feature-integrations.tsx │ │ │ ├── feature-notification.tsx │ │ │ ├── header.tsx │ │ │ ├── hero.tsx │ │ │ ├── home-section.tsx │ │ │ └── open-source.tsx │ │ ├── layout │ │ │ ├── footer.tsx │ │ │ └── hits.tsx │ │ ├── magicui │ │ │ ├── animated-beam.tsx │ │ │ ├── animated-list.tsx │ │ │ ├── bento-grid.tsx │ │ │ ├── dot-pattern.tsx │ │ │ ├── marquee.tsx │ │ │ └── shimmer-button.tsx │ │ ├── menu-switch.tsx │ │ ├── pricing │ │ │ ├── discount.tsx │ │ │ ├── faq.tsx │ │ │ ├── index.tsx │ │ │ ├── options.tsx │ │ │ ├── sections.ts │ │ │ └── tiers.tsx │ │ └── ui │ │ │ ├── button.tsx │ │ │ ├── calendar.tsx │ │ │ ├── card.tsx │ │ │ ├── input.tsx │ │ │ ├── link.tsx │ │ │ ├── pagination.tsx │ │ │ ├── table.tsx │ │ │ └── tabs.tsx │ ├── content │ │ └── 2025-03-25.mdx │ ├── globals.css │ ├── lib │ │ ├── utils.ts │ │ └── utils.tsx │ ├── mdx-components.tsx │ └── overrides.css ├── tailwind.config.ts └── tsconfig.json ├── package.json ├── packages ├── backend │ ├── database │ │ ├── drizzle.config.ts │ │ ├── drizzle │ │ │ └── .gitkeep │ │ ├── migrate.ts │ │ ├── package.json │ │ ├── src │ │ │ ├── index.ts │ │ │ ├── schema.ts │ │ │ ├── schema │ │ │ │ ├── auth.ts │ │ │ │ ├── auth │ │ │ │ │ ├── organization.ts │ │ │ │ │ ├── sso.ts │ │ │ │ │ └── user.ts │ │ │ │ ├── chat.ts │ │ │ │ ├── chat │ │ │ │ │ ├── conversation.ts │ │ │ │ │ └── message.ts │ │ │ │ ├── config.ts │ │ │ │ ├── provider.ts │ │ │ │ └── provider │ │ │ │ │ └── model.ts │ │ │ ├── utils.ts │ │ │ └── utils │ │ │ │ ├── columns.ts │ │ │ │ ├── fields.ts │ │ │ │ ├── id.ts │ │ │ │ └── table.ts │ │ └── tsconfig.json │ └── server │ │ ├── .env.example │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── esbuild.config.ts │ │ ├── package.json │ │ ├── src │ │ ├── factory.ts │ │ ├── hc.ts │ │ ├── index.ts │ │ ├── lib │ │ │ ├── auth.ts │ │ │ ├── database │ │ │ │ ├── index.ts │ │ │ │ └── utils.ts │ │ │ └── plugins │ │ │ │ ├── sentry.ts │ │ │ │ └── winston.ts │ │ ├── middleware │ │ │ ├── auth.ts │ │ │ ├── conn-info.ts │ │ │ ├── logger.ts │ │ │ └── provider-registry.ts │ │ └── routes │ │ │ ├── admin │ │ │ ├── index.ts │ │ │ └── model.ts │ │ │ ├── system │ │ │ ├── health.ts │ │ │ ├── index.ts │ │ │ ├── setup.ts │ │ │ └── webhook.ts │ │ │ └── user │ │ │ ├── chat.ts │ │ │ └── index.ts │ │ ├── test │ │ └── setup.ts │ │ ├── tsconfig.json │ │ └── vitest.config.ts ├── common │ ├── error │ │ ├── package.json │ │ ├── src │ │ │ ├── biz.ts │ │ │ └── index.ts │ │ └── tsconfig.json │ └── tsconfig │ │ ├── base.json │ │ ├── nextjs.json │ │ ├── node-library.json │ │ ├── package.json │ │ ├── react-library.json │ │ └── tsconfig.json └── frontend │ ├── email │ ├── .gitignore │ ├── package.json │ ├── src │ │ ├── _components │ │ │ ├── button.tsx │ │ │ ├── layout.tsx │ │ │ └── text.tsx │ │ ├── index.ts │ │ ├── mailer.ts │ │ ├── template.ts │ │ └── transactional │ │ │ ├── email-code.tsx │ │ │ ├── email-verification-link.tsx │ │ │ ├── order-cancelled.tsx │ │ │ ├── order-confirmed.tsx │ │ │ ├── order-receipt.tsx │ │ │ ├── ticket-created.tsx │ │ │ └── ticket-reply.tsx │ └── tsconfig.json │ ├── i18n │ ├── lingui.config.ts │ └── package.json │ └── web │ ├── .gitignore │ ├── README.md │ ├── components.json │ ├── eslint.config.js │ ├── index.html │ ├── package.json │ ├── public │ └── vite.svg │ ├── src │ ├── App.tsx │ ├── components │ │ └── ui │ │ │ ├── button.tsx │ │ │ ├── chat │ │ │ ├── chat-bubble.tsx │ │ │ ├── chat-input.tsx │ │ │ ├── chat-message-list.tsx │ │ │ ├── expandable-chat.tsx │ │ │ ├── hooks │ │ │ │ └── useAutoScroll.tsx │ │ │ └── message-loading.tsx │ │ │ ├── input.tsx │ │ │ ├── separator.tsx │ │ │ ├── sheet.tsx │ │ │ ├── sidebar.tsx │ │ │ ├── skeleton.tsx │ │ │ └── tooltip.tsx │ ├── hooks │ │ └── use-mobile.ts │ ├── index.css │ ├── lib │ │ ├── api-client.ts │ │ └── utils.ts │ ├── main.tsx │ ├── pages │ │ ├── auth │ │ │ └── index.ts │ │ ├── chat │ │ │ └── index.ts │ │ ├── console │ │ │ └── layout.tsx │ │ └── setup.tsx │ └── vite-env.d.ts │ ├── tsconfig.app.json │ ├── tsconfig.json │ ├── tsconfig.node.json │ └── vite.config.ts ├── patches └── hono.patch ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── prompts └── summarizer.prompt.yml └── turbo.json /.dockerignore: -------------------------------------------------------------------------------- 1 | **/node_modules 2 | **/.env 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/test-suite.yml: -------------------------------------------------------------------------------- 1 | name: Test Suite 2 | 3 | on: 4 | push: 5 | branches: [ 6 | "v3", 7 | "v3-dev" 8 | ] 9 | pull_request: 10 | types: [ 11 | opened, 12 | synchronize 13 | ] 14 | 15 | jobs: 16 | test: 17 | name: Build and Test 18 | timeout-minutes: 15 19 | runs-on: ubuntu-latest 20 | env: 21 | TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} 22 | TURBO_TEAM: ${{ vars.TURBO_TEAM }} 23 | 24 | steps: 25 | - uses: actions/checkout@v4 26 | 27 | - name: Cache turbo build setup 28 | uses: actions/cache@v3 29 | with: 30 | path: .turbo 31 | key: ${{ runner.os }}-turbo-${{ github.sha }} 32 | restore-keys: | 33 | ${{ runner.os }}-turbo- 34 | 35 | - uses: pnpm/action-setup@v2.4.0 36 | 37 | - name: Install Node.js 38 | uses: actions/setup-node@v4 39 | with: 40 | node-version: 18 41 | cache: 'pnpm' 42 | 43 | - name: Install dependencies 44 | run: pnpm install 45 | 46 | - name: Build 47 | run: pnpm build 48 | 49 | - name: Test 50 | run: pnpm test 51 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | config.yaml 2 | 3 | prisma/client/ 4 | 5 | .env 6 | config.json 7 | apps/server/.env 8 | 9 | # IDE 10 | .vscode/ 11 | .idea/ 12 | 13 | **/.next/ 14 | **/.vscode/ 15 | **/.idea/ 16 | **/.next/ 17 | **/dist/ 18 | # Turbopack 19 | .turbo 20 | 21 | **/node_modules/ 22 | 23 | # Env 24 | apps/server/.env 25 | -------------------------------------------------------------------------------- /.node-version: -------------------------------------------------------------------------------- 1 | 24 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 AprilNEA 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /biome.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", 3 | "vcs": { 4 | "enabled": false, 5 | "clientKind": "git", 6 | "useIgnoreFile": true 7 | }, 8 | "files": { 9 | "ignoreUnknown": false, 10 | "ignore": ["dist", ".next", ".turbo", "node_modules"] 11 | }, 12 | "formatter": { 13 | "enabled": true, 14 | "indentStyle": "space" 15 | }, 16 | "organizeImports": { 17 | "enabled": true 18 | }, 19 | "linter": { 20 | "enabled": true, 21 | "rules": { 22 | "recommended": true, 23 | "style": { 24 | "noInferrableTypes": "off" 25 | }, 26 | "a11y": { 27 | "useValidAriaRole": "off", 28 | "noSvgWithoutTitle": "off" 29 | } 30 | } 31 | }, 32 | "javascript": { 33 | "formatter": { 34 | "quoteStyle": "double" 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /docker-compose.yaml: -------------------------------------------------------------------------------- 1 | name: achat 2 | 3 | services: 4 | postgres: 5 | container_name: achat-postgres 6 | image: ${POSTGRES_IMAGE:-postgres:17} 7 | environment: 8 | POSTGRES_USER: ${POSTGRES_USER:-postgres} 9 | POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres} 10 | POSTGRES_DB: ${POSTGRES_DB:-postgres} 11 | expose: 12 | - 5432 13 | # ports: 14 | # - "5432:5432" 15 | volumes: 16 | - postgres-data:/var/lib/postgresql/data 17 | restart: always 18 | 19 | redis: 20 | container_name: achat-redis 21 | image: ${REDIS_IMAGE:-redis:7} 22 | environment: 23 | - "REDIS_ARGS=--appendonly yes" 24 | expose: 25 | - 6379 26 | # ports: 27 | # - "6379:6379" 28 | volumes: 29 | - redis-data:/data 30 | restart: always 31 | 32 | inngest: 33 | container_name: achat-inngest 34 | image: ${INNGEST_IMAGE:-inngest/inngest} 35 | command: ["inngest", "start", "--sdk-url", "http://host.docker.internal:3001/api/inngest"] 36 | environment: 37 | # INNGEST_EVENT_KEY: 38 | # INNGEST_SIGNING_KEY: 39 | INNGEST_SQLITE_DIR: /data 40 | expose: 41 | - 8288 42 | # ports: 43 | # - "8288:8288" 44 | volumes: 45 | - inngest-data:/data 46 | 47 | minio: 48 | container_name: achat-minio 49 | image: ${MINIO_IMAGE:-minio/minio} 50 | volumes: 51 | - minio-data:/data 52 | environment: 53 | - MINIO_ROOT_USER=minioadmin 54 | - MINIO_ROOT_PASSWORD=minioadmin 55 | command: server /data --console-address ":9001" 56 | expose: 57 | - 9000 58 | - 9001 59 | # ports: 60 | # - "9000:9000" 61 | # - "9001:9001" 62 | 63 | # loki: 64 | # image: grafana/loki:3.4.1 65 | # command: -config.file=/etc/loki/local-config.yaml 66 | # ports: 67 | # - "3100:3100" 68 | # volumes: 69 | # - nboard-loki-data:/loki 70 | # restart: always 71 | 72 | volumes: 73 | postgres-data: 74 | redis-data: 75 | inngest-data: 76 | minio-data: -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.* 7 | .yarn/* 8 | !.yarn/patches 9 | !.yarn/plugins 10 | !.yarn/releases 11 | !.yarn/versions 12 | 13 | # testing 14 | /coverage 15 | 16 | # next.js 17 | /.next/ 18 | /out/ 19 | 20 | # production 21 | /build 22 | 23 | # misc 24 | .DS_Store 25 | *.pem 26 | 27 | # debug 28 | npm-debug.log* 29 | yarn-debug.log* 30 | yarn-error.log* 31 | .pnpm-debug.log* 32 | 33 | # env files (can opt-in for committing if needed) 34 | .env* 35 | 36 | # vercel 37 | .vercel 38 | 39 | # typescript 40 | *.tsbuildinfo 41 | next-env.d.ts 42 | -------------------------------------------------------------------------------- /docs/.node-version: -------------------------------------------------------------------------------- 1 | 20 -------------------------------------------------------------------------------- /docs/biome.json: -------------------------------------------------------------------------------- 1 | { 2 | "linter": { 3 | "rules": { 4 | "a11y": { 5 | "noSvgWithoutTitle": "off" 6 | } 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /docs/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.ts", 8 | "css": "src/globals.css", 9 | "baseColor": "slate", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils", 16 | "ui": "@/components/ui", 17 | "lib": "@/lib", 18 | "hooks": "@/hooks" 19 | }, 20 | "iconLibrary": "lucide" 21 | } -------------------------------------------------------------------------------- /docs/image-loader.ts: -------------------------------------------------------------------------------- 1 | const normalizeSrc = (src: string) => { 2 | return src.startsWith("/") ? src.slice(1) : src; 3 | }; 4 | 5 | export default function cloudflareLoader({ 6 | src, 7 | width, 8 | quality, 9 | }: { src: string; width: number; quality?: number }) { 10 | if (process.env.NODE_ENV === "development") { 11 | return src; 12 | } 13 | const params = [`width=${width}`]; 14 | if (quality) { 15 | params.push(`quality=${quality}`); 16 | } 17 | const paramsString = params.join(","); 18 | return `/cdn-cgi/image/${paramsString}/${normalizeSrc(src)}`; 19 | } 20 | -------------------------------------------------------------------------------- /docs/next.config.ts: -------------------------------------------------------------------------------- 1 | import nextra from "nextra"; 2 | 3 | import type { NextConfig } from "next"; 4 | 5 | const withNextra = nextra({ 6 | contentDirBasePath: "/changelog", 7 | staticImage: true, 8 | search: { 9 | codeblocks: true, 10 | }, 11 | defaultShowCopyCode: true, 12 | }); 13 | const nextConfig: NextConfig = { 14 | assetPrefix: '/docs', 15 | images: { 16 | loader: "custom", 17 | loaderFile: "./image-loader.ts", 18 | }, 19 | }; 20 | 21 | export default withNextra(nextConfig); 22 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@achat/docs", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev -p 3333", 7 | "build": "next build", 8 | "start": "PORT=3333 next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "@lobehub/icons": "^1.94.0", 13 | "@radix-ui/react-icons": "^1.3.2", 14 | "@radix-ui/react-slot": "^1.1.2", 15 | "@radix-ui/react-tabs": "^1.1.3", 16 | "class-variance-authority": "^0.7.1", 17 | "clsx": "^2.1.1", 18 | "date-fns": "^4.1.0", 19 | "foxact": "^0.2.44", 20 | "lucide-react": "^0.482.0", 21 | "motion": "^12.6.0", 22 | "next": "15.2.2", 23 | "nextra": "^4.2.16", 24 | "nextra-theme-docs": "^4.2.16", 25 | "react": "^19.0.0", 26 | "react-day-picker": "8.10.1", 27 | "react-dom": "^19.0.0", 28 | "tailwind-merge": "^3.0.2", 29 | "tailwindcss-animate": "^1.0.7" 30 | }, 31 | "devDependencies": { 32 | "@achat/tsconfig": "workspace:*", 33 | "@biomejs/biome": "1.9.4", 34 | "@tailwindcss/postcss": "^4", 35 | "@types/node": "^20", 36 | "@types/react": "^19", 37 | "@types/react-dom": "^19", 38 | "tailwindcss": "^4", 39 | "typescript": "^5" 40 | } 41 | } -------------------------------------------------------------------------------- /docs/pages/_meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "index": "主页", 3 | "quickstart": "快速开始", 4 | "upgrade": { 5 | "title": "升级" 6 | }, 7 | "development": { 8 | "title": "开发" 9 | }, 10 | "-- More": { 11 | "type": "separator", 12 | "title": "More" 13 | }, 14 | "github_link": { 15 | "title": "Github ↗", 16 | "href": "https://github.com/AprilNEA/ChatGPT-Admin-Web", 17 | "newWindow": true 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /docs/pages/development/_meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "auth": "认证部分" 3 | } 4 | -------------------------------------------------------------------------------- /docs/pages/development/auth.md: -------------------------------------------------------------------------------- 1 | # 认证部分 2 | 3 | ```mermaid 4 | graph TD 5 | 6 | %% 开始节点 7 | start(用户选择) 8 | 9 | %% 密码方式 10 | start --> passwordChoice[选择密码方式] 11 | 12 | passwordChoice --> passwordLogin[密码登录] 13 | passwordLogin --> endPasswordLogin[登录完成] 14 | 15 | %% 验证码方式 16 | start --> codeChoice[选择验证码方式] 17 | 18 | codeChoice --> codeLogin[验证码登录] 19 | codeLogin --> checkPasswordCode[检查是否设置密码] 20 | 21 | 22 | codeChoice --> codeRegister[验证码注册] 23 | codeRegister --> checkPasswordCode[检查是否设置密码] 24 | checkPasswordCode --> setPasswordCodeRegister[提示设置密码] 25 | checkPasswordCode --> endCodeRegister[注册完成] 26 | 27 | %% 微信扫码方式 28 | start --> wechatChoice[选择微信扫码方式] 29 | 30 | wechatChoice --> wechatLogin[微信扫码登录] 31 | wechatLogin --> ifBind[判断是否绑定] 32 | ifBind --> alreadyBind[已绑定] 33 | ifBind --> notBind[未绑定] 34 | alreadyBind --> endWechatLogin[登录完成] 35 | notBind --> bind[绑定手机或邮箱] 36 | bind --> setPasswordWechat[设置密码] 37 | setPasswordWechat --> endWechatRegister[注册完成] 38 | ``` 39 | -------------------------------------------------------------------------------- /docs/pages/index.mdx: -------------------------------------------------------------------------------- 1 | import {useSSG} from 'nextra/ssg' 2 | import { Cards, Card } from 'nextra/components' 3 | 4 | export const getStaticProps = async ({params}) => { 5 | const githubRepo = await fetch(`https://api.github.com/repos/AprilNEA/ChatGPT-Admin-Web`) 6 | .then(res => res.json()) 7 | const afdianPage = await fetch(`https://afdian.net/api/creator/get-top-sponsors?user_id=612f691e0f1611ee97c152540025c377`) 8 | .then(res => res.json()) 9 | return { 10 | props: { 11 | // We add an `ssg` field to the page props, 12 | // which will be provided to the Nextra `useSSG` hook. 13 | ssg: { 14 | stars: githubRepo?.stargazers_count ?? 0, 15 | sponsors: afdianPage.data.list 16 | } 17 | }, 18 | // The page will be considered as stale and regenerated every 60 seconds. 19 | revalidate: 60 20 | } 21 | } 22 | 23 | export const Sponsors = () => { 24 | const {sponsors} = useSSG() 25 | return
{sponsors.map((sponsor) => ( 26 | {sponsor.name} 36 | ))}
37 | } 38 | 39 | export const Stars = () => { 40 | // Get the data from SSG, and render it as a component. 41 | const {stars} = useSSG() 42 | return {stars} 43 | } 44 | 45 | 46 | 47 | # ChatGPT-Admin-Web 48 | 49 | 这是一个由 [ChatGPT-Next-Web](https://github.com/Yidadaa/ChatGPT-Next-Web) 二次开发的项目。 50 | 51 | 52 | 53 | 54 | 55 | 56 | ## 捐赠 57 | 58 | [GitHub Sponsor](https://github.com/sponsors/AprilNEA) | [爱发电](https://afdian.net/a/aprilnea) 59 | 60 | ChatGPT-Admin-Web has stars on GitHub! 61 | 62 | ## 致谢 63 | 64 | 65 | -------------------------------------------------------------------------------- /docs/pages/quickstart.mdx: -------------------------------------------------------------------------------- 1 | import { Callout, Steps } from 'nextra/components' 2 | 3 | ## 快速开始 4 | 5 | **Prerequisite** You should have installed Node.js (version 18.10.0 or 6 | higher). 7 | 8 | 9 | 10 | ### 克隆项目并安装依赖 11 | 12 | ```bash 13 | git clone https://github.com/AprilNEA/ChatGPT-Admin-Web.git 14 | cd ChatGPT-Admin-Web 15 | pnpm install 16 | ``` 17 | > pnpm 安装:`npm i -g pnpm` 18 | 19 | ### 初始化数据库 20 | 21 | 设置`DATABASE_URL`环境变量,例如: 22 | ```bash 23 | export DATABASE_URL=postgres://postgres:your_password@localhost:5432/postgres 24 | ``` 25 | > 可通过 Docker 快速启动一个 PostgreSQL 数据库 26 | > 27 | > `docker run -itd --name caw -e POSTGRES_PASSWORD=your_password -p 5432:5432 -d postgres` 28 | 29 | 在项目根目录运行: 30 | 31 | ```bash 32 | pnpm run db:init 33 | ``` 34 | 35 | 你会看见如下输出,则表明数据库已经初始化成功: 36 | 37 | ```bash 38 | > chatgpt-admin-web@3.1.0 db:init /path/to/ChatGPT-Admin-Web 39 | > prisma db push && prisma db seed 40 | 41 | Environment variables loaded from .env 42 | Prisma schema loaded from prisma/schema.prisma 43 | Datasource "db": PostgreSQL database "postgres", schema "public" at "localhost:5434" 44 | 45 | 🚀 Your database is now in sync with your Prisma schema. Done in 245ms 46 | 47 | ✔ Generated Prisma Client (v5.3.1) to ./prisma/client in 297ms 48 | 49 | Environment variables loaded from .env 50 | Running seed command `ts-node prisma/seed.ts` ... 51 | { 52 | models: {count: 2}, 53 | categories: {count: 1}, 54 | products: {count: 1}, 55 | limits: {count: 1} 56 | } 57 | 58 | 🌱 The seed command has been executed. 59 | 60 | ``` 61 | 62 | 设置`REDIS_URL`环境变量,例如: 63 | ```bash 64 | export REDIS_URL=redis://localhost:6379/0 65 | ``` 66 | > 可通过 Docker 快速启动一个 Redis 数据库 67 | > 68 | > `docker run -p 6379:6379 -d redis/redis-stack:latest` 69 | 70 | 71 | ### 启动项目 72 | ```bash 73 | pnpm run start 74 | ``` 75 | 76 | 项目默认运行在 `http://localhost:3000`。 77 | 78 | 首次运行项目会自动生成`config.json`, 并导入`DATABASE_URL`和`REDIS_URL`环境变量,后续更改可直接修改`config.json`。 79 | 80 | 81 | Dashboard is coming soon. 82 | 83 | 84 | ~~首次打开应自动转跳`http://localhost:3000/install`设置管理员账户和密码,设置成功后即可登录。~~ 85 | 86 | 87 | 88 | ## 配置 89 | 90 | 91 | 邮件服务仅 Resend 通过测试。 92 | 短信服务仅 UniSMS 通过测试。 93 | 支付服务仅 Xunhu 通过测试。 94 | 95 | 96 | ```json 97 | { 98 | ...// 自动生成部分 99 | 100 | "openai": { 101 | "baseUrl": "https://api.openai.com/v1", 102 | "keys": [ 103 | "fff" 104 | ] 105 | }, 106 | "email": { 107 | "use": "resend", 108 | "domain": "example.com", 109 | "resend": { 110 | "apiKey": "fff" 111 | } 112 | }, 113 | "sms": { 114 | "use": "uni", 115 | "uni": { 116 | "signature": "XX科技", 117 | "apiKey": "ffffff" 118 | } 119 | }, 120 | "payment": { 121 | "use": "xunhu", 122 | "xunhu": { 123 | "wapName": "XX科技", 124 | "appId": "ffffff", 125 | "appSecret": "ffffff", 126 | "notifyUrl": "https://example.com", 127 | "returnUrl": "https://example.com" 128 | } 129 | } 130 | } 131 | ``` 132 | -------------------------------------------------------------------------------- /docs/pages/upgrade/log.mdx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AprilNEA/AChat/bd7e585c4d5d4773cbf80aae87dcfcec94a7d505/docs/pages/upgrade/log.mdx -------------------------------------------------------------------------------- /docs/pages/upgrade/v1tov3.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: '从v1升级' 3 | description: '' 4 | --- 5 | -------------------------------------------------------------------------------- /docs/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | const config = { 2 | plugins: ["@tailwindcss/postcss"], 3 | }; 4 | 5 | export default config; 6 | -------------------------------------------------------------------------------- /docs/public/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AprilNEA/AChat/bd7e585c4d5d4773cbf80aae87dcfcec94a7d505/docs/public/icon.png -------------------------------------------------------------------------------- /docs/public/images/content-safe/baidu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AprilNEA/AChat/bd7e585c4d5d4773cbf80aae87dcfcec94a7d505/docs/public/images/content-safe/baidu.png -------------------------------------------------------------------------------- /docs/public/images/email/elastice-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AprilNEA/AChat/bd7e585c4d5d4773cbf80aae87dcfcec94a7d505/docs/public/images/email/elastice-01.png -------------------------------------------------------------------------------- /docs/public/images/email/mailgun-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AprilNEA/AChat/bd7e585c4d5d4773cbf80aae87dcfcec94a7d505/docs/public/images/email/mailgun-01.png -------------------------------------------------------------------------------- /docs/public/images/email/mailgun-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AprilNEA/AChat/bd7e585c4d5d4773cbf80aae87dcfcec94a7d505/docs/public/images/email/mailgun-02.png -------------------------------------------------------------------------------- /docs/public/images/email/mailgun-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AprilNEA/AChat/bd7e585c4d5d4773cbf80aae87dcfcec94a7d505/docs/public/images/email/mailgun-03.png -------------------------------------------------------------------------------- /docs/public/images/email/mailgun-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AprilNEA/AChat/bd7e585c4d5d4773cbf80aae87dcfcec94a7d505/docs/public/images/email/mailgun-04.png -------------------------------------------------------------------------------- /docs/public/images/email/mailgun-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AprilNEA/AChat/bd7e585c4d5d4773cbf80aae87dcfcec94a7d505/docs/public/images/email/mailgun-05.png -------------------------------------------------------------------------------- /docs/public/images/email/mailgun-06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AprilNEA/AChat/bd7e585c4d5d4773cbf80aae87dcfcec94a7d505/docs/public/images/email/mailgun-06.png -------------------------------------------------------------------------------- /docs/public/images/email/mailgun-07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AprilNEA/AChat/bd7e585c4d5d4773cbf80aae87dcfcec94a7d505/docs/public/images/email/mailgun-07.png -------------------------------------------------------------------------------- /docs/public/images/email/wechat-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AprilNEA/AChat/bd7e585c4d5d4773cbf80aae87dcfcec94a7d505/docs/public/images/email/wechat-01.png -------------------------------------------------------------------------------- /docs/public/images/pay/xunhu-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AprilNEA/AChat/bd7e585c4d5d4773cbf80aae87dcfcec94a7d505/docs/public/images/pay/xunhu-01.png -------------------------------------------------------------------------------- /docs/public/images/sms/unisms-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AprilNEA/AChat/bd7e585c4d5d4773cbf80aae87dcfcec94a7d505/docs/public/images/sms/unisms-01.png -------------------------------------------------------------------------------- /docs/src/app/_meta.tsx: -------------------------------------------------------------------------------- 1 | import type { MetaRecord } from "nextra"; 2 | 3 | export default { 4 | index: { 5 | type: "page", 6 | title: "VMBoard", 7 | display: "hidden", 8 | theme: { 9 | layout: "full", 10 | }, 11 | }, 12 | docs: { 13 | type: "page", 14 | title: "文档", 15 | }, 16 | pricing: { 17 | title: "定价", 18 | type: "page", 19 | theme: { 20 | layout: "full", 21 | }, 22 | }, 23 | sponsor: { 24 | type: "page", 25 | title: "赞助", 26 | }, 27 | changelog: { 28 | type: "page", 29 | title: "变更日志", 30 | theme: { 31 | breadcrumb: false, 32 | sidebar: false, 33 | timestamp: false, 34 | toc: false, 35 | }, 36 | }, 37 | forum: { 38 | type: "page", 39 | title: "社区论坛", 40 | href: "https://forum.vmboard.io", 41 | }, 42 | "self-hosting": { 43 | type: "page", 44 | title: "自托管", 45 | // hidden from main menu via overrides.css, nextra display:hidden otherwise breaks type:page 46 | }, 47 | showcase: { 48 | type: "page", 49 | title: "展示", 50 | // hidden from main menu via overrides.css, nextra display:hidden otherwise breaks type:page 51 | }, 52 | faq: { 53 | type: "page", 54 | title: "FAQ", 55 | // hidden from main menu via overrides.css, nextra display:hidden otherwise breaks type:page 56 | }, 57 | support: { 58 | type: "page", 59 | title: "支持", 60 | display: "hidden", 61 | }, 62 | // about: { 63 | // title: "About us", 64 | // type: "page", 65 | // display: "hidden", 66 | // theme: { 67 | // typesetting: "article", 68 | // timestamp: false, 69 | // }, 70 | // }, 71 | // "404": { 72 | // type: "page", 73 | // theme: { 74 | // typesetting: "article", 75 | // timestamp: false, 76 | // }, 77 | // }, 78 | } satisfies MetaRecord; 79 | -------------------------------------------------------------------------------- /docs/src/app/changelog/[...mdxPath]/action.ts: -------------------------------------------------------------------------------- 1 | import { generateStaticParamsFor, importPage } from "nextra/pages"; 2 | 3 | export type Props = { 4 | params: Promise<{ 5 | mdxPath: string[]; 6 | }>; 7 | }; 8 | 9 | export const getPage = async (props: Props) => { 10 | const params = await props.params; 11 | const mdxPath = params.mdxPath ?? []; 12 | const result = await importPage(mdxPath); 13 | // const result = await importPage([mergeParams(mdxPath)]); 14 | return result; 15 | }; 16 | 17 | // export const splitParams = (name: string): string[] => { 18 | // return name.split("-", 3); 19 | // }; 20 | 21 | // export const mergeParams = (params: string[]): string => { 22 | // return params.length > 1 ? params.join("-") : params[0]; 23 | // }; 24 | 25 | export const generateChangelogParams = async () => { 26 | const params = await generateStaticParamsFor("mdxPath")(); 27 | return params; 28 | // return params.map(({ mdxPath: param }) => { 29 | // if (param[0] === "") 30 | // return { 31 | // mdxPath: param, 32 | // }; 33 | // return { 34 | // mdxPath: splitParams(param[0]), 35 | // }; 36 | // }); 37 | }; 38 | -------------------------------------------------------------------------------- /docs/src/app/changelog/[...mdxPath]/layout.tsx: -------------------------------------------------------------------------------- 1 | import { Link } from "nextra-theme-docs"; 2 | 3 | import { generateChangelogParams, getPage, type Props } from "./action"; 4 | import { useMDXComponents as getMDXComponents } from "@/mdx-components"; 5 | import { Author } from "@/components/authors"; 6 | 7 | // biome-ignore lint/style/noNonNullAssertion: 8 | const Wrapper = getMDXComponents().wrapper!; 9 | 10 | export const generateStaticParams = generateChangelogParams 11 | 12 | export default async function Layout({ 13 | children, 14 | ...props 15 | }: Props & { 16 | children: React.ReactNode; 17 | }) { 18 | const { toc, metadata } = await getPage(props); 19 | const { title, description, author, date } = metadata; 20 | return ( 21 | 22 | {title !== "Index" ? ( 23 |
24 | 25 | ← Back to changelog 26 | 27 |
28 |
29 | {date && 30 | new Date(date).toLocaleDateString("zh-CN", { 31 | year: "numeric", 32 | month: "long", 33 | day: "numeric", 34 | timeZone: "Asia/Shanghai", 35 | })} 36 | {/* {!!badge && ` | ${badge}`} */} 37 |
38 |
39 |
40 |

41 | {title} 42 |

43 |
44 | 45 |
46 |
47 |

{description}

48 | {children} 49 |
50 | ) : ( 51 | children 52 | )} 53 |
54 | ); 55 | } 56 | 57 | export const dynamic = "force-static"; 58 | -------------------------------------------------------------------------------- /docs/src/app/changelog/[...mdxPath]/page.tsx: -------------------------------------------------------------------------------- 1 | import type { Props } from "./action"; 2 | import { generateChangelogParams, getPage } from "./action"; 3 | 4 | export const generateStaticParams = generateChangelogParams; 5 | 6 | export async function generateMetadata(props: Props) { 7 | const { metadata } = await getPage(props); 8 | return metadata; 9 | } 10 | 11 | export default async function Page(props: Props) { 12 | const { default: MDXContent } = await getPage(props); 13 | 14 | return ; 15 | } 16 | 17 | export const dynamic = "force-static"; 18 | -------------------------------------------------------------------------------- /docs/src/app/changelog/_meta.ts: -------------------------------------------------------------------------------- 1 | import type { MetaRecord } from "nextra"; 2 | 3 | export default { 4 | index: { 5 | theme: { 6 | layout: "full", 7 | }, 8 | }, 9 | } satisfies MetaRecord; 10 | -------------------------------------------------------------------------------- /docs/src/app/changelog/page.tsx: -------------------------------------------------------------------------------- 1 | import { Link } from "nextra-theme-docs"; 2 | import { Header } from "@/components/landing/header"; 3 | import ChangelogIndex from "@/components/changelog"; 4 | 5 | export default function Page() { 6 | return ( 7 |
8 |
9 |
13 | 来自 VMBoard 团队的最新版本更新. 查看我们的{" "} 14 | 15 | 路线图 16 | {" "} 17 | 了解下一步计划。 18 | 19 | } 20 | className="mb-8" 21 | h="h1" 22 | /> 23 |
24 | {/* */} 25 |
26 |
27 | 28 |
29 | ); 30 | } 31 | -------------------------------------------------------------------------------- /docs/src/app/docs/_meta.tsx: -------------------------------------------------------------------------------- 1 | import { MenuSwitcher } from "@/components/menu-switch"; 2 | import { MetaRecord } from "nextra"; 3 | 4 | export default { 5 | "-- Switcher": { 6 | type: "separator", 7 | title: , 8 | }, 9 | index: "概述", 10 | install: "安装探针", 11 | // mobile: "移动端", 12 | "-- Features": { 13 | type: "separator", 14 | title: "功能", 15 | }, 16 | manage: "主机管理", 17 | metrics: "指标监控", 18 | analysis: "数据分析", 19 | alert: "报警规则", 20 | webpage: "页面分享", 21 | import: "迁移导入", 22 | "-- Develop": { 23 | type: "separator", 24 | title: "开发", 25 | }, 26 | architecture: "系统架构", 27 | develop: "本地开发", 28 | "-- More": { 29 | type: "separator", 30 | title: "更多", 31 | }, 32 | roadmap: "路线图", 33 | "open-source": "开源", 34 | support: { 35 | href: "/support", 36 | title: "支持", 37 | }, 38 | } satisfies MetaRecord; 39 | -------------------------------------------------------------------------------- /docs/src/app/docs/alert/page.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 报警规则 3 | --- 4 | 5 | # 报警规则 6 | 7 | 报警规则是用于定义告警的规则,当满足规则时,会触发告警。 8 | 9 | --- 10 | 11 | > [!NOTE] 12 | > 13 | > 该功能仍在开发中,尚未正式发布。 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /docs/src/app/docs/analysis/page.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 监控 3 | --- 4 | 5 | # 数据分析 6 | 7 | > [!NOTE] 8 | > 9 | > 该功能仍在开发中,尚未正式发布。 10 | -------------------------------------------------------------------------------- /docs/src/app/docs/architecture/architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AprilNEA/AChat/bd7e585c4d5d4773cbf80aae87dcfcec94a7d505/docs/src/app/docs/architecture/architecture.png -------------------------------------------------------------------------------- /docs/src/app/docs/architecture/page.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 系统架构 3 | --- 4 | 5 | import { Image } from 'nextra/components' 6 | import architectureImage from './architecture.png' 7 | 8 | # 系统架构 9 | --- 10 | 11 | ## 整体结构 12 | 13 | architecture 14 | 15 | ### 1. 管理面板 16 | 17 | - 前端界面:提供统一的 VPS 管理视图 18 | - API 集成层:对接各大主机商 API 19 | - 数据处理层:聚合和分析来自不同来源的数据 20 | 21 | ### 2. Rust 探针系统 22 | 23 | - 轻量级服务器端组件 24 | - 通过 WebSockets 协议进行实时数据传输 25 | - 低资源占用,高性能监控 26 | 27 | ### 3. 通信架构 28 | 29 | - WebSockets 作为核心通信协议 30 | - 双向实时数据流 31 | - 支持断线重连和数据缓存机制 32 | -------------------------------------------------------------------------------- /docs/src/app/docs/develop/component.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useEffect, useRef } from "react"; 4 | import { Input } from "@/components/ui/input"; 5 | 6 | export function DatabasePassword({ children }: { children: React.ReactNode }) { 7 | const ref = useRef(null); 8 | const nameRef = useRef(null); 9 | const portRef = useRef(null); 10 | const volumeRef = useRef(null); 11 | const passwordRef = useRef(null); 12 | 13 | useEffect(() => { 14 | if (ref.current) { 15 | if (!nameRef.current) { 16 | const token = [...ref.current.querySelectorAll("code span")].find( 17 | (el) => (el as HTMLElement).innerText === " vmboard-db", 18 | ); 19 | nameRef.current = token as HTMLElement; 20 | } 21 | if (!portRef.current) { 22 | const token = [...ref.current.querySelectorAll("code span")].find( 23 | (el) => (el as HTMLElement).innerText === " 5432:5432", 24 | ); 25 | portRef.current = token as HTMLElement; 26 | } 27 | if (!volumeRef.current) { 28 | const token = [...ref.current.querySelectorAll("code span")].find( 29 | (el) => 30 | (el as HTMLElement).innerText === 31 | " vmboard-db-data:/home/postgres/pgdata/data", 32 | ); 33 | volumeRef.current = token as HTMLElement; 34 | } 35 | if (!passwordRef.current) { 36 | const token = [...ref.current.querySelectorAll("code span")].find( 37 | (el) => 38 | (el as HTMLElement).innerText === " POSTGRES_PASSWORD=postgres", 39 | ); 40 | passwordRef.current = token as HTMLElement; 41 | } 42 | } 43 | }, []); 44 | 45 | return ( 46 |
47 |
48 | { 51 | if (!nameRef.current) return; 52 | if (e.currentTarget.value.trim().length === 0) { 53 | nameRef.current.innerText = " vmboard-db"; 54 | } else { 55 | nameRef.current.innerText = ` ${e.currentTarget.value}`; 56 | } 57 | }} 58 | /> 59 | { 62 | if (!portRef.current) return; 63 | if (e.currentTarget.value.trim().length === 0) { 64 | portRef.current.innerText = " 5432:5432"; 65 | } else { 66 | portRef.current.innerText = ` ${e.currentTarget.value}:5432`; 67 | } 68 | }} 69 | /> 70 | { 73 | if (!volumeRef.current) return; 74 | if (e.currentTarget.value.trim().length === 0) { 75 | volumeRef.current.innerText = " vmboard-db-data:/home/postgres/pgdata/data"; 76 | } else { 77 | volumeRef.current.innerText = ` ${e.currentTarget.value}:/home/postgres/pgdata/data`; 78 | } 79 | }} 80 | /> 81 | { 84 | if (!passwordRef.current) return; 85 | if (e.currentTarget.value.trim().length === 0) { 86 | passwordRef.current.innerText = " POSTGRES_PASSWORD=postgres"; 87 | } else { 88 | passwordRef.current.innerText = ` POSTGRES_PASSWORD=${e.currentTarget.value}`; 89 | } 90 | }} 91 | /> 92 |
93 | {children} 94 |
95 | ); 96 | } 97 | -------------------------------------------------------------------------------- /docs/src/app/docs/develop/page.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 开发 3 | --- 4 | 5 | import { DatabasePassword } from "./component"; 6 | 7 | # 开发 8 | 9 | ## 设置数据库 10 | 11 | 12 | 13 | ```bash 14 | docker run -d --name vmboard-db -p 5432:5432 \ 15 | -v vmboard-db-data:/home/postgres/pgdata/data \ 16 | -e POSTGRES_PASSWORD=postgres \ 17 | timescale/timescaledb-ha:pg17 18 | ``` 19 | 20 | 21 | 22 | 23 | ### 克隆仓库 24 | ```bash 25 | git clone https://github.com/achat/vmboard.git && cd vmboard 26 | ``` 27 | 28 | ### 安装依赖 29 | ```bash 30 | pnpm install 31 | ``` 32 | 33 | ### 同步数据库 34 | ```bash 35 | pnpm prisma:migrate 36 | ``` 37 | 38 | ### 启动服务 39 | ```bash 40 | pnpm dev 41 | ``` 42 | 43 | 服务将会在 `http://localhost:3000` 启动。 -------------------------------------------------------------------------------- /docs/src/app/docs/import/page.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 导入迁移 3 | --- 4 | 5 | # 导入迁移 6 | 7 | ## 导入主机 8 | 9 | ## 迁移主机 10 | 11 | ### 从哪吒迁移 -------------------------------------------------------------------------------- /docs/src/app/docs/install/page.mdx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AprilNEA/AChat/bd7e585c4d5d4773cbf80aae87dcfcec94a7d505/docs/src/app/docs/install/page.mdx -------------------------------------------------------------------------------- /docs/src/app/docs/manage/manage-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AprilNEA/AChat/bd7e585c4d5d4773cbf80aae87dcfcec94a7d505/docs/src/app/docs/manage/manage-dark.png -------------------------------------------------------------------------------- /docs/src/app/docs/manage/manage-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AprilNEA/AChat/bd7e585c4d5d4773cbf80aae87dcfcec94a7d505/docs/src/app/docs/manage/manage-light.png -------------------------------------------------------------------------------- /docs/src/app/docs/manage/page.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 主机管理 3 | --- 4 | 5 | import { Image } from 'nextra/components' 6 | import manageDark from './manage-dark.png' 7 | import manageLight from './manage-light.png' 8 | 9 | 10 | # 主机管理 11 | 12 | --- 13 | 14 | manage-light 15 | 16 | manage-dark 17 | 18 | 19 | ## SSH 远程连接 20 | 21 | ## 主机列表 22 | 23 | ## 主机详情 24 | 25 | -------------------------------------------------------------------------------- /docs/src/app/docs/metrics/metrics-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AprilNEA/AChat/bd7e585c4d5d4773cbf80aae87dcfcec94a7d505/docs/src/app/docs/metrics/metrics-dark.png -------------------------------------------------------------------------------- /docs/src/app/docs/metrics/metrics-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AprilNEA/AChat/bd7e585c4d5d4773cbf80aae87dcfcec94a7d505/docs/src/app/docs/metrics/metrics-light.png -------------------------------------------------------------------------------- /docs/src/app/docs/metrics/page.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 指标监控 3 | --- 4 | 5 | import { Image } from 'nextra/components' 6 | import metricsDark from './metrics-dark.png' 7 | import metricsLight from './metrics-light.png' 8 | 9 | 10 | # 指标监控 11 | 12 | --- 13 | 14 | metrics-light 15 | 16 | metrics-dark 17 | 18 | -------------------------------------------------------------------------------- /docs/src/app/docs/open-source/page.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 开源 3 | --- 4 | 5 | # 开源 6 | 7 | ## 动态 8 | 9 | ![Alt](https://repobeats.axiom.co/api/embed/dc5524c6e91cb38261e30d733649b0734688ced9.svg "Repobeats analytics image") -------------------------------------------------------------------------------- /docs/src/app/docs/page.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: VMBoard 文档 3 | --- 4 | 5 | import { PlayIcon, DownloadIcon, BoltIcon, ServerIcon } from 'lucide-react' 6 | import { Cards } from 'nextra/components' 7 | 8 | # VMBoard 9 | 10 | VMBoard 旨在创建一个集中式 VPS 管理面板,用于聚合和管理来自不同主机商的服务器信息。 11 | 12 | 系统集成了 Rust 编写的服务器探针,通过 WebSockets 与面板实时交互,提供强大的监控和管理功能。 13 | 14 | 面板支持多种主机商 API 集成,提供流量监控、资源使用情况、远程 SSH 连接以及自动通知等功能。 15 | 16 | ## 背景 17 | 18 | 团队成员正在管理大量来自不同提供商的 VPS 资源。 19 | 20 | 该项目旨在简化这一流程,提供统一的管理界面,同时通过高性能探针提供实时监控数据。 21 | 22 | ## 开始使用 23 | 24 | 25 | } 27 | title="快速开始" 28 | href="/docs/get-started" 29 | /> 30 | } 32 | title="探针安装" 33 | href="/docs/probe-installation" 34 | /> 35 | } 37 | title="探针配置" 38 | href="/docs/probe-configuration" 39 | /> 40 | } 42 | title="自托管" 43 | href="/docs/self-hosting" 44 | /> 45 | 46 | -------------------------------------------------------------------------------- /docs/src/app/docs/webpage/page.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 页面分享 3 | --- 4 | 5 | # 页面分享 6 | 7 | 8 | ## 自定义前缀 [#custom-handle] 9 | 10 | ## 自定义主机名 [#custom-hostname] -------------------------------------------------------------------------------- /docs/src/app/faq/_meta.tsx: -------------------------------------------------------------------------------- 1 | import { MenuSwitcher } from "@/components/menu-switch"; 2 | 3 | export default { 4 | "-- Switcher": { 5 | type: "separator", 6 | title: , 7 | }, 8 | index: "Overview", 9 | }; 10 | -------------------------------------------------------------------------------- /docs/src/app/faq/page.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: VMBoard1 3 | --- 4 | 5 | # VMBoard 6 | 7 | VMBoard is a platform for creating and managing virtual machines. 8 | -------------------------------------------------------------------------------- /docs/src/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import "@/globals.css"; 2 | import "nextra-theme-docs/style.css"; 3 | import "@/overrides.css"; 4 | 5 | import { Layout, Link, Navbar } from "nextra-theme-docs"; 6 | import Footer from "@/components/layout/footer"; 7 | import { Banner, Head, Search } from "nextra/components"; 8 | import { getPageMap } from "nextra/page-map"; 9 | import { Background } from "@/components/background"; 10 | import Telegram from "@/components/icons/telegram"; 11 | import { ForumLink } from "@/components/ui/link"; 12 | import Logo from "@/components/icons/logo"; 13 | import { Button } from "@/components/ui/button"; 14 | import { GithubMenuBadge } from "@/components/github-badge"; 15 | 16 | export const metadata = { 17 | title: { 18 | default: "VMBoard", 19 | template: "%s | VMBoard", 20 | }, 21 | description: 22 | "VMBoard 是一个强大且轻量的服务器监控平台,实时获取服务器指标数据,支持 SSH 连接管理。", 23 | icons: { 24 | icon: "/icon.svg", 25 | }, 26 | }; 27 | 28 | const banner = 即将发布...; 29 | const navbar = ( 30 | 33 | 34 | VMBoard 35 | 36 | } 37 | projectLink="https://github.com/achat/vmboard" 38 | chatLink="https://t.me/vmboard" 39 | chatIcon={} 40 | > 41 | 42 | 43 | 46 | 47 | 48 | ); 49 | const footer =