import { Alert, Card, Collapse, Divider, Table, Tabs, Typography } from 'antd';

const { Title, Paragraph, Text } = Typography;

// ─── 核心概念 ────────────────────────────────────────────────────────────────

const coreConceptColumns = [
  { title: '概念', dataIndex: 'concept', key: 'concept', width: 160 },
  { title: '数据库表', dataIndex: 'table', key: 'table', width: 140 },
  { title: '说明', dataIndex: 'description', key: 'description' },
];

const coreConceptData = [
  {
    key: 'page',
    concept: 'Page（页面/菜单）',
    table: 't_page',
    description:
      '定义系统中的所有菜单项，支持树形结构（parentId）。每个 Page 有唯一的 code，对应前端路由注册表中的 key。',
  },
  {
    key: 'resource',
    concept: 'Resource（资源）',
    table: 't_resource',
    description:
      '定义后端 API 资源，每个资源对应一组 CRUD 权限（readAny, createAny, updateAny, deleteAny）。',
  },
  {
    key: 'role',
    concept: 'Role（角色）',
    table: 't_role',
    description:
      '角色是权限分配的基本单位。一个用户拥有一个角色，角色决定了可见菜单和 API 权限。',
  },
  {
    key: 'role_pages',
    concept: 'RolePages（角色-页面）',
    table: 't_role_pages',
    description: '角色与页面的关联表，决定角色可以看到哪些菜单项。',
  },
  {
    key: 'role_resource',
    concept: 'RoleResource（角色-资源）',
    table: 't_role_resource',
    description:
      '角色与资源的关联表，定义角色对每个资源的具体权限（读/写/改/删）。',
  },
  {
    key: 'page_resource',
    concept: 'PageResource（页面-资源）',
    table: 't_page_resource',
    description:
      '页面与资源的关联表，记录每个页面需要哪些 API 资源。用于批量为角色分配权限。',
  },
];

// ─── t_page 字段说明 ─────────────────────────────────────────────────────────

const pageFieldColumns = [
  { title: '字段', dataIndex: 'field', key: 'field', width: 180 },
  { title: '说明', dataIndex: 'description', key: 'description' },
  { title: '示例', dataIndex: 'example', key: 'example', width: 260 },
];

const pageFieldData = [
  {
    key: 'code',
    field: 'code',
    description: '页面唯一标识，原生页面必须与 routeRegistry 的 key 一致',
    example: 'software_dashboard',
  },
  {
    key: 'zhName',
    field: 'zhName / enName',
    description: '菜单显示的中英文名称',
    example: '软件看板 / Software Dashboard',
  },
  {
    key: 'path',
    field: 'path',
    description:
      'URL 完整路径。原生页面会被 routeRegistry 覆盖，iframe/外部链接页面以此作为菜单跳转路径',
    example: '/office/software-dashboard',
  },
  {
    key: 'parentId',
    field: 'parentId',
    description: '父菜单 ID，用于构建树形菜单结构',
    example: 'office 页面的 ID',
  },
  {
    key: 'sortOrder',
    field: 'sortOrder',
    description: '同级菜单的排序权重，数字越小越靠前',
    example: '10',
  },
  {
    key: 'iframeUrl',
    field: 'iframeUrl',
    description:
      'iframe 嵌入地址。设置后页面以 iframe 方式渲染，支持 {{locale}} 模板变量',
    example: 'https://analytics.example.com?lang={{locale}}',
  },
  {
    key: 'externalRedirectUrl',
    field: 'externalRedirectUrl',
    description:
      '外部跳转地址。设置后点击菜单在新窗口打开目标 URL，支持 {{locale}} 模板变量',
    example: 'https://wiki.example.com/page',
  },
  {
    key: 'isVirtual',
    field: 'isVirtual',
    description: '虚拟页面标记，设为 true 时不在侧边栏显示菜单项',
    example: 'false',
  },
];

// ─── 常见问题 ────────────────────────────────────────────────────────────────

const faqItems = [
  {
    key: '1',
    label: '菜单不显示？',
    children: (
      <ol>
        <li>
          检查 <Text code>routeRegistry.tsx</Text> 中是否注册了路由，且 key 与
          t_page 的 code 一致
        </li>
        <li>
          检查 <Text code>t_page</Text> 表中是否创建了记录（进入 Page Management
          查看）
        </li>
        <li>检查当前用户的角色是否分配了该页面（进入 Role Management 查看）</li>
        <li>
          检查 <Text code>parentId</Text>{' '}
          是否正确——父级页面也需要分配给角色，否则整个子树不可见
        </li>
      </ol>
    ),
  },
  {
    key: '2',
    label: '页面显示空白？',
    children: (
      <ol>
        <li>
          检查 <Text code>routeRegistry.tsx</Text> 中的{' '}
          <Text code>component</Text> 是否正确导入
        </li>
        <li>确认页面组件文件已正确导出（export 名称是否与 import 一致）</li>
        <li>打开浏览器 DevTools Console 查看是否有 JS 加载错误</li>
      </ol>
    ),
  },
  {
    key: '3',
    label: 'API 返回 403？',
    children: (
      <Paragraph>
        后端权限由 <Text code>t_role_resource</Text> 控制。进入 Role
        Management，检查角色是否分配了对应资源的权限（readAny / createAny /
        updateAny / deleteAny）。注意：前端菜单可见不代表有 API
        权限，两者独立配置。
      </Paragraph>
    ),
  },
  {
    key: '4',
    label: 'iframe 页面加载失败？',
    children: (
      <ol>
        <li>
          检查目标网站是否允许被 iframe 嵌入（X-Frame-Options /
          Content-Security-Policy 头）
        </li>
        <li>
          确认 <Text code>iframeUrl</Text> 与{' '}
          <Text code>externalRedirectUrl</Text> 未同时填写（两者互斥）
        </li>
        <li>
          如果目标网站禁止 iframe 嵌入，改用{' '}
          <Text code>externalRedirectUrl</Text> 以新窗口方式打开
        </li>
      </ol>
    ),
  },
  {
    key: '5',
    label: '如何添加子菜单？',
    children: (
      <Paragraph>
        在 <Text code>t_page</Text> 中创建记录时将 <Text code>parentId</Text>{' '}
        设为父菜单的 ID。如果是原生页面，在 <Text code>routeRegistry.tsx</Text>{' '}
        中也需要将路由放入父路由的 <Text code>children</Text> 对象中。
      </Paragraph>
    ),
  },
  {
    key: '6',
    label: '{{locale}} 模板变量怎么用？',
    children: (
      <Paragraph>
        在 <Text code>iframeUrl</Text> 或 <Text code>externalRedirectUrl</Text>{' '}
        中使用 <Text code>{'{{locale}}'}</Text>
        ，系统会在运行时自动替换为当前语言（
        <Text code>en</Text> 或 <Text code>zh_CN</Text>）。例如：
        <Text code>
          https://example.com/docs?lang=zh_CN https://example.com/docs?lang=en
        </Text>
      </Paragraph>
    ),
  },
];

// ─── 原生页面注册步骤 ────────────────────────────────────────────────────────

const nativeStepColumns = [
  { title: '步骤', dataIndex: 'step', key: 'step', width: 80 },
  { title: '操作', dataIndex: 'action', key: 'action', width: 200 },
  { title: '说明', dataIndex: 'detail', key: 'detail' },
];

const nativeStepData = [
  {
    key: '1',
    step: '1',
    action: '创建页面组件',
    detail:
      '在 src/routes/ 下创建页面组件文件，如 src/routes/office/my-feature/index.tsx，导出页面组件。',
  },
  {
    key: '2',
    step: '2',
    action: '在 routeRegistry 注册路由',
    detail:
      '在 src/config/routeRegistry.tsx 中添加路由条目。key 即为 page code，配置 path（相对路径）和 component（lazy import）。如有子路由放入 children。',
  },
  {
    key: '3',
    step: '3',
    action: '在 Page Management 创建记录',
    detail:
      '进入 /admin/permission/page-list，新建页面。code 必须与 routeRegistry 中的 key 完全一致，设置 parentId 为父菜单 ID。',
  },
  {
    key: '4',
    step: '4',
    action: '关联资源（可选）',
    detail:
      '如果页面需要 API 权限控制，在页面记录中关联对应的 Resource，用于后续批量分配权限。',
  },
  {
    key: '5',
    step: '5',
    action: '为角色分配页面',
    detail:
      '进入 /admin/permission/role-list，编辑目标角色，勾选新添加的页面。',
  },
];

// ─── 对比表 ──────────────────────────────────────────────────────────────────

const comparisonColumns = [
  { title: '', dataIndex: 'item', key: 'item', width: 160 },
  { title: '原生页面', dataIndex: 'native', key: 'native' },
  { title: '外部链接', dataIndex: 'external', key: 'external' },
  { title: 'iframe 嵌入', dataIndex: 'iframe', key: 'iframe' },
  { title: '动态菜单', dataIndex: 'dynamic', key: 'dynamic' },
];

const comparisonData = [
  {
    key: 'scene',
    item: '适用场景',
    native: '内部开发的完整功能页面',
    external: '跳转到外部系统（Wiki、文档等）',
    iframe: '在应用内嵌入外部页面（报表等）',
    dynamic: '同一组件多实例（如工作室列表）',
  },
  {
    key: 'registry',
    item: '需要修改前端页面',
    native: '是（config/routeRegistry.tsx）',
    external: '否',
    iframe: '否',
    dynamic: '是（config/dynamicMenus.ts 配置）',
  },
  {
    key: 'component',
    item: '需要写页面组件',
    native: '是',
    external: '否',
    iframe: '否',
    dynamic: '是（共享组件）',
  },
  {
    key: 'tpage',
    item: '需要 t_page 记录',
    native: '是（code = routeRegistry key）',
    external: '是（填 externalRedirectUrl）',
    iframe: '是（填 iframeUrl）',
    dynamic: '是（父级目录）',
  },
  {
    key: 'url',
    item: '关键 t_page 字段',
    native: 'code, path, parentId',
    external: 'externalRedirectUrl',
    iframe: 'iframeUrl',
    dynamic: 'code（如 invested / native）',
  },
  {
    key: 'behavior',
    item: '用户体验',
    native: '应用内完整渲染',
    external: '新窗口打开 + 自动返回',
    iframe: '应用框架内嵌入',
    dynamic: '应用内完整渲染',
  },
  {
    key: 'template',
    item: '支持 {{locale}}',
    native: '—',
    external: '是',
    iframe: '是',
    dynamic: '—',
  },
];

// ─── 组件 ────────────────────────────────────────────────────────────────────

export const PermissionReadmePage = () => {
  return (
    <div>
      <Typography>
        <Title level={2}>菜单管理说明</Title>
        <Paragraph>
          本页面介绍系统的菜单、路由与权限管理机制，帮助管理员理解如何添加和配置不同类型的菜单项。
        </Paragraph>
      </Typography>

      {/* ── 架构概览 ──────────────────────────────────────────────── */}
      <Card title="菜单系统架构" style={{ marginBottom: 24 }}>
        <Paragraph>
          系统的菜单管理涉及<Text strong>前端路由注册</Text>和
          <Text strong>数据库页面配置</Text>两个部分的协作。 未匹配到
          routeRegistry 的路由会进入 <Text code>WildcardPage</Text> 通配组件，
          由它根据 t_page 的配置决定渲染 iframe、打开外部链接或显示 404。
        </Paragraph>
        <Alert
          type="info"
          showIcon
          message="数据流"
          description={
            <div>
              <Text code>routeRegistry.tsx</Text>（前端路由定义：Route
              Path、React组件） + <Text code>t_page</Text>（数据库菜单配置） →{' '}
              <Text code>侧边栏菜单渲染</Text> + <Text code>路由匹配</Text>
              <br />
              <br />
              路由匹配优先级：<Text code>routeRegistry</Text> 原生路由 &gt;{' '}
              <Text code>WildcardPage (/*)</Text> 通配路由
              <br />
              <br />
              WildcardPage 处理：查询 t_page → 有 <Text code>iframeUrl</Text> →
              渲染 iframe ｜ 有 <Text code>externalRedirectUrl</Text> →
              新窗口打开 ｜ 否则 → 404
            </div>
          }
          style={{ marginBottom: 16 }}
        />
      </Card>

      {/* ── 核心概念 ──────────────────────────────────────────────── */}
      <Card title="核心概念" style={{ marginBottom: 24 }}>
        <Table
          columns={coreConceptColumns}
          dataSource={coreConceptData}
          pagination={false}
          size="small"
          bordered
        />
        <Divider />
        <Title level={5}>t_page 关键字段</Title>
        <Table
          columns={pageFieldColumns}
          dataSource={pageFieldData}
          pagination={false}
          size="small"
          bordered
        />
      </Card>

      {/* ── 四种注册方式 ──────────────────────────────────────────── */}
      <Card title="菜单注册方式" style={{ marginBottom: 24 }}>
        <Alert
          type="info"
          showIcon
          message="四种方式对比"
          style={{ marginBottom: 16 }}
          description={
            <Table
              columns={comparisonColumns}
              dataSource={comparisonData}
              pagination={false}
              size="small"
              bordered
              scroll={{ x: 800 }}
            />
          }
        />

        <Tabs
          items={[
            {
              key: 'native',
              label: '原生页面',
              children: (
                <>
                  <Paragraph>
                    原生页面是最常见的方式——编写 React 组件，在{' '}
                    <Text code>routeRegistry.tsx</Text> 中注册路由，再在 t_page
                    中创建对应记录。
                  </Paragraph>
                  <Alert
                    type="warning"
                    showIcon
                    message="关键约束"
                    description={
                      <>
                        routeRegistry 中的 key（如{' '}
                        <Text code>software_dashboard</Text>）必须与 t_page 的{' '}
                        <Text code>code</Text>{' '}
                        字段完全一致，否则菜单无法正常显示。
                      </>
                    }
                    style={{ marginBottom: 16 }}
                  />
                  <Title level={5}>注册步骤</Title>
                  <Table
                    columns={nativeStepColumns}
                    dataSource={nativeStepData}
                    pagination={false}
                    size="small"
                    bordered
                  />
                  <Divider />
                  <Title level={5}>routeRegistry 示例</Title>
                  <pre
                    style={{
                      background: '#f5f5f5',
                      padding: 16,
                      borderRadius: 6,
                      overflow: 'auto',
                      fontSize: 13,
                      lineHeight: 1.6,
                    }}
                  >{`// src/config/routeRegistry.tsx
office: {
  path: "/office",
  children: {
    // key "my_feature" 即为 t_page 中的 code
    my_feature: {
      path: "my-feature-dashboard",
      component: lazy(() => import("@/routes/office/my-feature")),
    },
  },
},`}</pre>

                  <Divider />
                  <Title level={5}>下划线前缀（_ 开头）的子路由</Title>
                  <Paragraph>
                    routeRegistry 中以 <Text code>_</Text> 开头的 key 是
                    <Text strong>内部子路由</Text>，
                    <Text strong>无需在 t_page 中注册</Text>。 它们由父级页面的
                    code 统一管理权限，属于同一个页面模块的不同视图。
                  </Paragraph>

                  <Title level={5}>CRUD 子路由</Title>
                  <Paragraph>
                    最常见的 <Text code>_</Text> 前缀子路由，
                    用于同一模块的列表/新建/编辑/详情视图，不出现在侧边栏中：
                  </Paragraph>
                  <Table
                    columns={[
                      {
                        title: 'Key',
                        dataIndex: 'key',
                        key: 'key',
                        width: 100,
                      },
                      {
                        title: '典型 path',
                        dataIndex: 'path',
                        key: 'path',
                        width: 140,
                      },
                      { title: '用途', dataIndex: 'usage', key: 'usage' },
                    ]}
                    dataSource={[
                      {
                        key: '_list',
                        path: '""（index: true）',
                        usage:
                          '列表页，作为父路由的默认子路由（index route），访问父路径时自动渲染',
                      },
                      {
                        key: '_create',
                        path: '"create"',
                        usage: '新建页，如 /admin/staff/create',
                      },
                      {
                        key: '_edit',
                        path: '"edit/:id"',
                        usage: '编辑页，如 /admin/staff/edit/123',
                      },
                      {
                        key: '_show',
                        path: '"show/:id"',
                        usage: '详情页，如 /admin/staff/show/123',
                      },
                      {
                        key: '_index',
                        path: '""（index: true）',
                        usage: '与 _list 类似，用于非 CRUD 场景的默认子路由',
                      },
                    ]}
                    pagination={false}
                    size="small"
                    bordered
                  />

                  <Divider />
                  <Title level={5}>动态参数路由 + Sidebar-only 菜单条目</Title>
                  <Paragraph>
                    当多个菜单项共享同一个页面组件、只通过 URL
                    参数区分内容时，使用{' '}
                    <Text strong>动态参数路由 + Sidebar-only 条目</Text>
                    的组合模式：
                  </Paragraph>
                  <ul>
                    <li>
                      动态参数路由（如 <Text code>_tab</Text> /{' '}
                      <Text code>_region</Text>） - 负责实际渲染，
                      <Text strong>不注册 t_page</Text>
                    </li>
                    <li>
                      Sidebar-only 条目（如 <Text code>apac</Text>、
                      <Text code>security_event</Text>
                      ）— 只有 path、没有 component，
                      <Text strong>需要注册 t_page</Text>，
                      出现在侧边栏菜单中。用户点击后 URL
                      匹配到动态参数路由，由共享组件渲染。
                    </li>
                  </ul>
                  <pre
                    style={{
                      background: '#f5f5f5',
                      padding: 16,
                      borderRadius: 6,
                      overflow: 'auto',
                      fontSize: 13,
                      lineHeight: 1.6,
                    }}
                  >{`// 示例：RTO 看板按区域分子菜单
// t_page 需注册：overview, apac, amer, emea
// _index 和 _region 无需注册

overview: {
  path: "rto-dashboard",
  children: {
    _index: {                           // 默认视图，无需注册 t_page
      path: "",
      index: true,
      component: lazy(() => import("@/routes/office/rto")),
    },
    _region: {                          // 动态参数路由，无需注册 t_page
      path: ":region",                  // 匹配 /office/rto-dashboard/apac 等
      component: lazy(() => import("@/routes/office/rto")),
    },
    // Sidebar-only 条目：需注册 t_page，出现在侧边栏菜单
    apac: { path: "apac" },             // 无 component，点击后由 _region 渲染
    amer: { path: "amer" },
    emea: { path: "emea" },
  },
},`}</pre>

                  <Alert
                    type="info"
                    showIcon
                    message="命名约定总结"
                    description={
                      <ul style={{ margin: 0, paddingLeft: 20 }}>
                        <li>
                          <Text strong>不以 _ 开头</Text>的 key → 页面
                          code，需在 t_page 中注册。有 component
                          的是原生页面，无 component 的是 sidebar-only 菜单条目
                        </li>
                        <li>
                          <Text strong>以 _ 开头</Text>的 key →
                          内部子路由，不注册
                          t_page，不出现在侧边栏，权限跟随父级页面
                        </li>
                      </ul>
                    }
                    style={{ marginTop: 16, marginBottom: 16 }}
                  />

                  <Title level={5}>CRUD 模块完整示例</Title>
                  <pre
                    style={{
                      background: '#f5f5f5',
                      padding: 16,
                      borderRadius: 6,
                      overflow: 'auto',
                      fontSize: 13,
                      lineHeight: 1.6,
                    }}
                  >{`// 只需在 t_page 中注册 "staff"（code="staff"），
// 下面 4 个 _ 开头的子路由无需注册，自动跟随 staff 的权限。
staff: {
  path: "staff",
  children: {
    _list: {
      path: "",
      index: true,    // 访问 /admin/staff 时渲染列表页
      component: lazy(() => import("@/routes/administration/staff")
        .then((m) => ({ default: m.StaffListPage }))),
    },
    _create: {
      path: "create", // /admin/staff/create
      component: lazy(() => import("@/routes/administration/staff")
        .then((m) => ({ default: m.StaffCreatePage }))),
    },
    _edit: {
      path: "edit/:id", // /admin/staff/edit/123
      component: lazy(() => import("@/routes/administration/staff")
        .then((m) => ({ default: m.StaffEditPage }))),
    },
    _show: {
      path: "show/:id", // /admin/staff/show/123
      component: lazy(() => import("@/routes/administration/staff")
        .then((m) => ({ default: m.StaffShowPage }))),
    },
  },
},`}</pre>
                </>
              ),
            },
            {
              key: 'external',
              label: '外部链接',
              children: (
                <>
                  <Paragraph>
                    外部链接方式<Text strong>无需编写任何前端代码</Text>
                    ，只需在 Page Management 中创建一条 t_page 记录，并填写{' '}
                    <Text code>externalRedirectUrl</Text> 字段即可。
                    点击菜单时系统会在新窗口打开目标 URL，并自动返回前一个页面。
                  </Paragraph>
                  <Title level={5}>注册步骤</Title>
                  <ol>
                    <li>
                      进入 <Text code>/admin/permission/page-list</Text>
                      ，新建页面记录
                    </li>
                    <li>
                      填写 <Text code>code</Text>、<Text code>zhName</Text>、
                      <Text code>path</Text>（任意唯一路径即可）、
                      <Text code>parentId</Text>
                    </li>
                    <li>
                      在 <Text code>External Redirect URL</Text>{' '}
                      字段填入目标地址
                    </li>
                    <li>为角色分配该页面</li>
                  </ol>
                  <Alert
                    type="info"
                    showIcon
                    message="模板变量"
                    description={
                      <>
                        URL 中可使用 <Text code>{'{{locale}}'}</Text>{' '}
                        模板变量，运行时会替换为当前语言（en / zh）。例如：
                        <br />
                        <Text code>
                          https://wiki.example.com/page?lang={'{{locale}}'}
                        </Text>
                      </>
                    }
                    style={{ marginTop: 16 }}
                  />
                  <Divider />
                  <Title level={5}>工作流程</Title>
                  <pre
                    style={{
                      background: '#f5f5f5',
                      padding: 16,
                      borderRadius: 6,
                      overflow: 'auto',
                      fontSize: 13,
                      lineHeight: 1.6,
                    }}
                  >{`用户点击菜单
  → 前端路由跳转到 page.path
  → 未匹配到 routeRegistry，进入 WildcardPage
  → WildcardPage 查询 t_page，发现 externalRedirectUrl
  → window.open(url, "_blank") 新窗口打开
  → window.history.back() 自动返回`}</pre>
                </>
              ),
            },
            {
              key: 'iframe',
              label: 'iframe 嵌入',
              children: (
                <>
                  <Paragraph>
                    iframe 方式同样<Text strong>无需编写前端代码</Text>
                    ，在 Page Management 中填写 <Text code>iframeUrl</Text>{' '}
                    字段即可。页面会在应用框架（侧边栏、顶栏）内以 iframe
                    全屏嵌入目标网页。
                  </Paragraph>
                  <Title level={5}>注册步骤</Title>
                  <ol>
                    <li>
                      进入 <Text code>/admin/permission/page-list</Text>
                      ，新建页面记录
                    </li>
                    <li>
                      填写 <Text code>code</Text>、<Text code>zhName</Text>、
                      <Text code>path</Text>（任意唯一路径即可）、
                      <Text code>parentId</Text>
                    </li>
                    <li>
                      在 <Text code>Iframe URL</Text> 字段填入目标地址
                    </li>
                    <li>为角色分配该页面</li>
                  </ol>
                  <Alert
                    type="warning"
                    showIcon
                    message="注意事项"
                    description={
                      <ul style={{ margin: 0, paddingLeft: 20 }}>
                        <li>
                          <Text code>iframeUrl</Text> 和{' '}
                          <Text code>externalRedirectUrl</Text>{' '}
                          不能同时填写，两者互斥
                        </li>
                        <li>
                          目标网站必须允许被 iframe 嵌入（未设置{' '}
                          <Text code>X-Frame-Options: DENY</Text> 或{' '}
                          <Text code>
                            Content-Security-Policy: frame-ancestors 'none'
                          </Text>
                          ）
                        </li>
                        <li>如果目标网站禁止 iframe，请改用外部链接方式</li>
                        <li>
                          同样支持 <Text code>{'{{locale}}'}</Text> 模板变量
                        </li>
                      </ul>
                    }
                    style={{ marginTop: 16 }}
                  />
                </>
              ),
            },
            {
              key: 'dynamic',
              label: '动态菜单',
              children: (
                <>
                  <Paragraph>
                    动态菜单适用于
                    <Text strong>同一个页面组件需要生成多个菜单项</Text>
                    的场景。通过 <Text code>
                      src/config/dynamicMenus.ts
                    </Text>{' '}
                    的配置驱动方案，开发者只需添加一条配置即可新增动态菜单组。
                  </Paragraph>

                  <Title level={5}>配置方式</Title>
                  <Paragraph>
                    在 <Text code>src/config/dynamicMenus.ts</Text> 中的{' '}
                    <Text code>dynamicMenuGroups</Text> 数组中添加一条配置：
                  </Paragraph>
                  <pre
                    style={{
                      background: '#f5f5f5',
                      padding: 16,
                      borderRadius: 6,
                      overflow: 'auto',
                      fontSize: 13,
                      lineHeight: 1.6,
                    }}
                  >{`// src/config/dynamicMenus.ts
interface DynamicMenuGroup {
  parentCode: string;    // 父级 page code（需在 t_page 注册）
  routePrefix: string;   // 路由前缀，如 "/rd/invested"
  items: string[];       // 子项列表，每项生成一个菜单项和路由
  component: LazyExoticComponent<ComponentType<any>>;  // 共享组件
}

// 示例：RD 工作室
{
  parentCode: "invested",
  routePrefix: "/rd/invested",
  items: studioMap.investedStudios,
  component: lazy(() => import("@/routes/rd/rdec")),
}`}</pre>

                  <Alert
                    type="info"
                    showIcon
                    message="权限控制"
                    description={
                      <>
                        动态菜单的权限以 <Text code>parentCode</Text>{' '}
                        为单位控制。例如为角色分配 <Text code>invested</Text>{' '}
                        页面后，该角色可以看到该组下所有子菜单项。无需为每个子项单独配置权限。
                      </>
                    }
                    style={{ marginTop: 16 }}
                  />

                  <Divider />
                  <Title level={5}>添加新动态菜单组的步骤</Title>
                  <ol>
                    <li>
                      在 <Text code>t_page</Text> 中注册父级页面（设置{' '}
                      <Text code>code</Text>、<Text code>parentId</Text>）
                    </li>
                    <li>
                      在 <Text code>src/config/dynamicMenus.ts</Text> 的{' '}
                      <Text code>dynamicMenuGroups</Text> 数组中添加一条配置
                    </li>
                    <li>
                      路由和菜单项会自动生成，无需修改{' '}
                      <Text code>routeRegistry.tsx</Text>、
                      <Text code>App.tsx</Text> 或{' '}
                      <Text code>useDynamicResources.tsx</Text>
                    </li>
                  </ol>

                  <Divider />
                  <Title level={5}>现有示例：RD 工作室</Title>
                  <Paragraph>
                    当前系统中 RD 模块的 invested（投资工作室）和
                    native（自研工作室）使用动态菜单：
                  </Paragraph>
                  <ul>
                    <li>
                      工作室列表定义在 <Text code>src/config/studio.ts</Text> 的{' '}
                      <Text code>studioMap</Text> 中
                    </li>
                    <li>
                      所有工作室路由共享同一个 <Text code>RDEC</Text>{' '}
                      组件，组件内从 URL 提取工作室名称
                    </li>
                    <li>
                      添加新工作室只需在 <Text code>studio.ts</Text> 的{' '}
                      <Text code>StudioEnum</Text> 和{' '}
                      <Text code>studioMap</Text> 中添加条目即可
                    </li>
                  </ul>
                </>
              ),
            },
          ]}
        />
      </Card>

      {/* ── 权限层级关系 ────────────────────────────────────────────── */}
      <Card title="权限层级关系" style={{ marginBottom: 24 }}>
        <Title level={5}>实体关系总览</Title>
        <pre
          style={{
            background: '#f5f5f5',
            padding: 16,
            borderRadius: 6,
            overflow: 'auto',
            fontSize: 13,
            lineHeight: 1.8,
          }}
        >{`User (t_admin_user_role)
 └─ roles: ["PRODUCT", "SYSTEM_ADMIN"]     ← 用户可拥有多个角色（JSON 数组）
      │
      ▼
Role (t_role)
 ├─ RolePages (t_role_pages)               ← 控制菜单可见性（前端）
 │    └─ Page (t_page)
 │         └─ PageResource (t_page_resource)  ← 页面声明需要的资源权限
 │
 └─ RoleResource (t_role_resource)         ← 控制 API 访问权限（后端）
      └─ Resource (t_resource)
           └─ actions: ["readAny", "createAny", "updateAny", "deleteAny"]`}</pre>

        <Divider />
        <Title level={5}>双层权限防御</Title>
        <Paragraph>系统在前端和后端分别进行权限检查，两层独立运作：</Paragraph>

        <Table
          columns={[
            { title: '', dataIndex: 'item', key: 'item', width: 140 },
            {
              title: '前端：菜单可见性',
              dataIndex: 'frontend',
              key: 'frontend',
            },
            {
              title: '后端：API 访问权限',
              dataIndex: 'backend',
              key: 'backend',
            },
          ]}
          dataSource={[
            {
              key: 'table',
              item: '关联表',
              frontend: 't_role_pages（角色 → 页面）',
              backend: 't_role_resource（角色 → 资源）',
            },
            {
              key: 'what',
              item: '控制什么',
              frontend: '侧边栏菜单项是否显示',
              backend: 'API 请求是否允许执行',
            },
            {
              key: 'fail',
              item: '无权限表现',
              frontend: '菜单不可见',
              backend: '返回 HTTP 403',
            },
            {
              key: 'check',
              item: '检查机制',
              frontend: 'useUserPageAccess() Hook 过滤菜单树',
              backend: 'AuthGuard → RolesGuard → @UseRoles() 装饰器',
            },
          ]}
          pagination={false}
          size="small"
          bordered
        />

        <Divider />
        <Title level={5}>权限检查完整流程</Title>
        <pre
          style={{
            background: '#f5f5f5',
            padding: 16,
            borderRadius: 6,
            overflow: 'auto',
            fontSize: 13,
            lineHeight: 1.8,
          }}
        >{`┌─ 前端菜单加载 ─────────────────────────────────────────────────────┐
│                                                                     │
│  1. GET /userinfo → 获取用户角色列表 (如 ["PRODUCT"])                │
│  2. POST /role/findMany → 查询角色 ID                               │
│  3. POST /rolePages/findMany → 查询角色关联的页面 ID                │
│  4. POST /page/findMany → 获取所有页面定义                          │
│  5. 构建可访问页面集合（包含分配页面 + 递归添加祖先页面）           │
│  6. 生成侧边栏菜单树                                                │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

┌─ 后端 API 权限检查 ────────────────────────────────────────────────┐
│                                                                     │
│  请求到达 → AuthGuard（验证身份，提取 userid）                      │
│          → RolesGuard（查询 t_admin_user_role，获取角色列表）        │
│          → @UseRoles({ resource: "xxx", action: "read" })           │
│          → RolesBuilder 检查该角色对该资源是否有对应权限             │
│          → 通过 ✓ 执行 / 拒绝 ✗ 返回 403                           │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘`}</pre>

        <Divider />
        <Title level={5}>PageResource 的作用</Title>
        <Paragraph>
          <Text code>t_page_resource</Text> 定义了每个页面需要哪些 API
          资源及权限。当管理员在 Role Management 中为角色勾选页面时，系统会
          <Text strong>自动从 PageResource 中提取资源权限</Text>，同步写入{' '}
          <Text code>t_role_resource</Text>。
        </Paragraph>
        <pre
          style={{
            background: '#f5f5f5',
            padding: 16,
            borderRadius: 6,
            overflow: 'auto',
            fontSize: 13,
            lineHeight: 1.8,
          }}
        >{`管理员勾选页面 A（关联了 Resource X [readAny] 和 Resource Y [readAny, createAny]）
  ↓
系统自动执行：
  1. 写入 t_role_pages：角色 → 页面 A
  2. 查询 t_page_resource：页面 A 需要 X(readAny)、Y(readAny, createAny)
  3. 合并写入 t_role_resource：角色 → X(readAny)、Y(readAny, createAny)

管理员取消勾选页面 A：
  1. 删除 t_role_pages 中的关联
  2. 如果 Resource X/Y 不被其他页面引用，同步删除 t_role_resource 中的关联`}</pre>

        <Divider />
        <Title level={5}>API 权限类型</Title>
        <Table
          columns={[
            { title: '权限', dataIndex: 'action', key: 'action', width: 140 },
            { title: '含义', dataIndex: 'meaning', key: 'meaning' },
            {
              title: '对应 HTTP 操作',
              dataIndex: 'http',
              key: 'http',
              width: 200,
            },
          ]}
          dataSource={[
            {
              key: 'read',
              action: 'readAny',
              meaning: '读取任意记录',
              http: 'GET / POST findMany',
            },
            {
              key: 'create',
              action: 'createAny',
              meaning: '创建新记录',
              http: 'POST createOne',
            },
            {
              key: 'update',
              action: 'updateAny',
              meaning: '修改任意记录',
              http: 'PATCH / PUT updateOne',
            },
            {
              key: 'delete',
              action: 'deleteAny',
              meaning: '删除任意记录',
              http: 'DELETE deleteOne',
            },
          ]}
          pagination={false}
          size="small"
          bordered
        />

        <Divider />
        <Title level={5}>通用资源（Common Resource）</Title>
        <Paragraph>
          <Text code>t_resource</Text> 中标记为{' '}
          <Text code>isCommonResource = true</Text> 的资源会自动为所有角色授予{' '}
          <Text code>readAny</Text>{' '}
          权限，无需在页面或角色中单独配置。适用于全局公共数据（如枚举列表、配置项等）。
        </Paragraph>

        <Divider />
        <Title level={5}>系统管理员</Title>
        <Alert
          type="info"
          showIcon
          message="硬编码管理员"
          description={
            <>
              以下用户在后端硬编码为 SYSTEM_ADMIN 角色，即使不在{' '}
              <Text code>t_admin_user_role</Text> 表中也会自动获得管理员权限：
              <Text code>kavenma</Text>、<Text code>jasonlan</Text>、
              <Text code>gc_lvhenan</Text>。
            </>
          }
        />
      </Card>

      {/* ── 常见问题 ──────────────────────────────────────────────── */}
      <Card title="常见问题">
        <Collapse items={faqItems} />
      </Card>
    </div>
  );
};

export default PermissionReadmePage;
