Files
school2/.ai/guidelines/xinadmin.md
T
2026-07-13 15:23:29 +08:00

7.8 KiB

XinAdmin

XinAdmin is a full-stack development framework: PHP8.2 + Laravel12 + React19 + TypeScript + Ant Design6 + Zustand + Tailwind CSS4. Licensed under MIT, free for commercial use without authorization.

Built-in Features

  • Dashboard: Echarts-based dashboards with demo pages
  • Administrators: Backend user management with groups, permissions, and settings
  • Role & Department Management: Role-based menu permission control, enterprise org structure
  • System Settings: Visual form-based server variable configuration
  • File Management: Backend file manager with folders, multi-select, grouping
  • Dictionary Management: Maintenance of frequently used static data
  • Mail & Storage Configuration: Visual config and testing for Laravel mail/filesystem
  • AI Configuration: Visual config and testing for Laravel AI SDK
  • Frontend Members: Permission, grouping, lists, balance records

AnnoRoute

AnnoRoute is a PHP 8 Attribute-based route registration module. Routes are declared via controller annotations — no manual route files needed. Sanctum auth and permission verification are auto-integrated.

Usage

  • #[GetRoute] / #[PostRoute] / #[PutRoute] / #[DeleteRoute] on methods declare HTTP routes
  • The authorize parameter controls access: 'query' becomes ability prefix.query, false makes a route public
  • #[RequestAttribute] params: routePrefix, abilitiesPrefix, middleware (string|array), authGuard (?string)
  • Method attributes share: route (path appended to prefix), authorize (string|bool), middleware, where (regex array)
  • Final route = routePrefix + route; final ability = abilitiesPrefix + '.' + authorize
  • When authorize is not falsy, auth:sanctum + authGuard + abilities: middleware are auto-assembled
  • Extend Modules\Common\Http\Controllers\BaseController for success() / error() response helpers

Frontend

Source lives in web/. Bundled with Vite, outputting to public/. Package manager: pnpm.

Directory Structure

Directory Purpose
web/api/ Typed Axios wrappers per backend module
web/components/ Reusable UI: AuthButton, DictTag, IconFont, XinForm, XinTable
web/domain/ TypeScript interfaces for API models
web/hooks/ useAuth, useLanguage, useMobile, useRequest
web/layout/ Layout engine (4 modes), menu, header, breadcrumbs, theme
web/locales/ i18n (i18next), zh_CN + en_US
web/pages/ Auto-discovered page components (file-system routing)
web/router/ React Router v7 createBrowserRouter
web/stores/ Zustand: global (app/theme), user (auth/perms), dict (cache)
web/utils/ Axios instance with dedup, auth headers, error handling

Key Conventions

  • Path alias @/web/
  • Zustand stores: State + Actionspersist + devtools → localStorage
  • Access stores via selector: useXxxStore(state => state.field)
  • All user-facing text via useTranslation() (react-i18next)
  • Locale files mirror page paths: pages/system/user.tsxlocales/zh_CN/system/user.ts, key prefix system.user
  • All keys dot-separated, double quotes, 2-space indent. See @skill:xinadmin-development for details
  • Permission checks: <AuthButton auth="system.user.create"> or useAuth().auth('permission')
  • HTTP client auto-attaches Authorization: Bearer, User-Language, handles 401 auto-logout
  • Pages in web/pages/ are auto-routed; index.tsx maps to parent directory; root //dashboard/analysis
  • Pages outside layout: add to excludePaths array in router config

Antd

Ant Design 6 is the UI component library. Components are imported from antd and themed via <ConfigProvider> with tokens from web/layout/theme.ts.

Key Conventions

  • Use antd MCP tools (antd_info, antd_doc, antd_demo) to verify component APIs before writing code
  • Never use deprecated props or components — check with antd_changelog when upgrading or referencing older examples
  • Theme tokens flow: web/layout/theme.ts<ConfigProvider theme={...}> → Ant Design components
  • Common components: Table, Form, Modal, Drawer, Button, Input, Select, DatePicker, Switch, Tag, Card, App ...

Layout

Wraps authenticated pages. Supports 4 modes set via global store: side (default), top, mix, columns.

Menus are fetched from /system/menu and stored in LayoutContext (React Context). Menu type: 'menu' (folder), 'route' (page), 'rule' (perm-only). Server filters by user role — no client-side filtering needed. Labels support i18n via node.local.

Theme tokens (20+ properties) are managed in web/layout/theme.ts, applied via Ant Design <ConfigProvider>, persisted to localStorage under global-storage.

XinForm And XinTable

Two declarative JSON-driven CRUD components. Define columns once with metadata — the same definition drives table display, search form, and create/edit forms.

XinForm

Use for settings/config pages or standalone forms. Supports 3 layout modes: 'Form' (inline), 'ModalForm', 'DrawerForm'.

<XinForm
  columns={[
    { dataIndex: 'username', title: 'Username', valueType: 'text', rules: [{ required: true }] },
    { dataIndex: 'role_id', title: 'Role', valueType: 'select', fieldProps: { options: roleOptions } },
  ]}
  layoutType="ModalForm"
  grid
  trigger={<Button type="primary">New</Button>}
  modalProps={{ title: 'Create User', width: 600 }}
  onFinish={async (values) => { await save(values); return true; }}
/>

Key FormColumn fields: dataIndex (supports nested paths ['a','b']), valueType (26 types: text, password, select, date, switch, etc.), fieldProps, fieldRender (custom render), dependency (field linkage: { dependencies, visible?, disabled?, fieldProps? }), hideIn* visibility flags.

formRef exposes open(), close(), isOpen(), setLoading() plus all Ant Design FormInstance methods.

XinTable

Use for standard CRUD pages (list + create + update + delete). Auto-handles API calls, permissions, search, and toolbar.

<XinTable<ISysUser>
  api="/system/user"
  columns={[
    { title: 'ID', dataIndex: 'id', hideInForm: true, width: 80 },
    { title: 'Username', dataIndex: 'username', valueType: 'text', rules: [{ required: true }] },
    { title: 'Status', dataIndex: 'status', valueType: 'radio', render: (v) => <Tag>{v === 1 ? 'Active' : 'Inactive'}</Tag> },
  ]}
  rowKey="id"
  accessName="system.user"
  formProps={{ grid: true, colProps: { span: 12 }, layout: 'vertical' }}
  modalProps={{ width: 800 }}
/>

Required props: api (REST endpoint), accessName (permission prefix), rowKey (PK field), columns.

Default REST behavior — GET {api} for list, POST {api} for create, PUT {api}/{id} for update, DELETE {api}/{id} for delete. Add/edit/delete buttons auto-wrapped in <AuthButton auth={accessName + '.create'}>.

Customize with: handleRequest (full custom fetch), requestParams (transform before send), handleFinish (custom submit), actionBarRender / toolBarRender / operateRender (slot overrides).

Choosing Between Them

  • XinTable: Full CRUD pages (users, roles, dicts, files)
  • XinForm (inline/ModalForm): Settings pages with a single form (mail, storage, AI config)
  • XinForm (ModalForm + trigger): Add/edit without a table (dept management)
  • Use hideInForm / hideInTable / hideInSearch to control per-context visibility

Development Workflow

When building a new CRUD feature, follow this four-phase workflow. See @skill:xinadmin-development for complete details.

  1. Database Migration — create table structure, indexes, foreign keys
  2. Backend — Controller (AnnoRoute attributes), Model, FormRequest
  3. Frontend — Page (file-system routing), Domain types, API wrappers, i18n
  4. Menu & Permissions — seeder menu entry + rules, menu translation keys