01_system_schema.sql 25.2 KB
-- ============================================================================
--  parking-cloud · P1 系统管理建表脚本
--
--  执行前提:先执行 00_create_database.sql 建好 parking_cloud 库,再 USE parking_cloud;
--  幂等:所有表都是 CREATE TABLE IF NOT EXISTS,可重复执行
--
--  设计约定(与 parking-framework 的 BaseDO 严格一致,改动前先读
--  parking-spring-boot-starter-mybatis/.../core/dataobject/BaseDO.java):
--
--  1. 审计列统一 4 个:create_time / update_time / create_by / update_by
--     (量过的存量库用的是 create_date/modfiy_date/create_emp_id 与 create_time/update_time 两套混用,
--      新表只认这一套;存量实体不继承 BaseDO,继续走各自的 mapper XML,互不影响)
--
--  2. del_flag:**不配置全局逻辑删除**(存量六个库 del_flag 出现 0 次,全局配置会误伤存量 XML)。
--     需要软删除的表在本文件里带 `del_flag` 列,由对应 DO 自行声明
--     `@TableLogic(value = "0", delval = "1")`。不需要软删除的表(关联表、日志表)不带该列。
--
--  3. 因此**带 del_flag 的表一律不建唯一索引**,只建普通索引 —— 否则逻辑删除后的行会与
--     新插入的同名行冲突(yudao 的取舍也是不建唯一索引)。
--
--  4. status 语义:0 = 启用,1 = 停用(与前端 `row.status === 0 ? '启用' : '停用'` 对齐)
--
--  5. 不带 tenant_id:本项目不做多租户
--
--  6. 每张表**显式写死** `COLLATE = utf8mb4_general_ci`,不靠服务端默认值。
--     原因(实测踩中):只写 `DEFAULT CHARSET = utf8mb4` 时,MySQL 取的是「该字符集在
--     **本服务端**的默认排序规则」——8.0 与本地新服务端是 utf8mb4_0900_ai_ci,5.7 才是
--     utf8mb4_general_ci。而 03_legacy_schema.sql 里的 679 张存量表是写死 general_ci 的,
--     于是同一套部署脚本在 8.0 目标机上会把 13 张 system_* 建成 0900、与存量表混在一起
--     (跨表比较/排序行为不一致,还可能 Illegal mix of collations)。写死之后在建库层面
--     就与 00 的 `DEFAULT COLLATE utf8mb4_general_ci` 对齐了。
-- ============================================================================

USE parking_cloud;

-- ---------------------------------------------------------------------------
-- 1. 组织
--    前端「组织管理」页列:name / sort / leader / mobile / status / createTime
--
--    ⚠️ 刻意偏离 yudao 的 `system_dept`,改叫 `system_org`,理由有三:
--      a) 前端契约已经定死为 `OrgApi` + `/system/org` + `OrgVO.orgId` + `UserVO.orgName`
--         (见 parking-cloud-ui/src/api/system/{org,user}/index.ts),用 dept 就得在
--         VO 层做一次永久的 orgId ↔ deptId 翻译,是全链路最容易出错的地方
--      b) 存量库与存量代码用的就是 org(`sys_org` 表、`SysOrgService`、`SysOrgDao`),
--         P1 第 6 步搬 zteits-sys 的 27 个 impl 时无需换词
--      c) `leader` 存姓名、`mobile` 存电话(而不是 yudao 的 leader_user_id + phone),
--         直接对齐前端已写好的列,省掉列表页一次「用户 id → 姓名」的额外查询
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS system_org (
    id          BIGINT       NOT NULL AUTO_INCREMENT COMMENT '主键',
    name        VARCHAR(30)  NOT NULL                COMMENT '组织名称',
    parent_id   BIGINT       NOT NULL DEFAULT 0      COMMENT '父级 id,0 为顶级',
    sort        INT          NOT NULL DEFAULT 0      COMMENT '显示顺序',
    leader      VARCHAR(30)           DEFAULT ''     COMMENT '负责人姓名',
    mobile      VARCHAR(20)           DEFAULT ''     COMMENT '联系电话',
    email       VARCHAR(50)           DEFAULT ''     COMMENT '邮箱',
    status      TINYINT      NOT NULL DEFAULT 0      COMMENT '状态:0 启用,1 停用',
    remark      VARCHAR(500)          DEFAULT ''     COMMENT '备注',
    create_time DATETIME     NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    update_time DATETIME     NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
    create_by   VARCHAR(64)           DEFAULT ''     COMMENT '创建者',
    update_by   VARCHAR(64)           DEFAULT ''     COMMENT '更新者',
    del_flag    TINYINT      NOT NULL DEFAULT 0      COMMENT '删除标记:0 未删,1 已删(DO 上用 @TableLogic)',
    PRIMARY KEY (id),
    KEY idx_parent_id (parent_id)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统管理 - 组织';

-- ---------------------------------------------------------------------------
-- 2. 用户
--    前端「用户管理」页列:username / nickname / orgName(由 org_id 关联出) / mobile / email / status
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS system_users (
    id          BIGINT       NOT NULL AUTO_INCREMENT COMMENT '主键',
    username    VARCHAR(30)  NOT NULL                COMMENT '登录账号',
    password    VARCHAR(100) NOT NULL                COMMENT '加密后的密码(BCrypt)',
    nickname    VARCHAR(30)  NOT NULL                COMMENT '用户昵称',
    remark      VARCHAR(500)          DEFAULT ''     COMMENT '备注',
    org_id      BIGINT                DEFAULT NULL   COMMENT '所属组织 id(前端字段名 orgId)',
    email       VARCHAR(50)           DEFAULT ''     COMMENT '邮箱',
    mobile      VARCHAR(20)           DEFAULT ''     COMMENT '手机号',
    sex         TINYINT               DEFAULT 0      COMMENT '性别:0 未知,1 男,2 女',
    avatar      VARCHAR(512)          DEFAULT ''     COMMENT '头像地址',
    status      TINYINT      NOT NULL DEFAULT 0      COMMENT '状态:0 启用,1 停用',
    login_ip    VARCHAR(50)           DEFAULT ''     COMMENT '最后登录 IP',
    login_date  DATETIME              DEFAULT NULL   COMMENT '最后登录时间',
    create_time DATETIME     NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    update_time DATETIME     NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
    create_by   VARCHAR(64)           DEFAULT ''     COMMENT '创建者',
    update_by   VARCHAR(64)           DEFAULT ''     COMMENT '更新者',
    del_flag    TINYINT      NOT NULL DEFAULT 0      COMMENT '删除标记:0 未删,1 已删(DO 上用 @TableLogic)',
    PRIMARY KEY (id),
    KEY idx_username (username),
    KEY idx_mobile (mobile),
    KEY idx_org_id (org_id),
    KEY idx_status (status)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统管理 - 用户';

-- ---------------------------------------------------------------------------
-- 3. 角色
--    前端「角色管理」页列:name / code / sort / status / createTime
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS system_role (
    id          BIGINT       NOT NULL AUTO_INCREMENT COMMENT '主键',
    name        VARCHAR(30)  NOT NULL                COMMENT '角色名称',
    code        VARCHAR(100) NOT NULL                COMMENT '角色标识,如 super_admin',
    sort        INT          NOT NULL DEFAULT 0      COMMENT '显示顺序',
    data_scope  TINYINT      NOT NULL DEFAULT 5      COMMENT '数据范围:1 全部,2 自定义,3 本组织,4 本组织及以下,5 仅本人(默认取 5 = 最小权限,避免新建角色静默全见)',
    status      TINYINT      NOT NULL DEFAULT 0      COMMENT '状态:0 启用,1 停用',
    type        TINYINT      NOT NULL DEFAULT 2      COMMENT '类型:1 内置(不可删),2 自定义',
    remark      VARCHAR(500)          DEFAULT ''     COMMENT '备注',
    create_time DATETIME     NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    update_time DATETIME     NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
    create_by   VARCHAR(64)           DEFAULT ''     COMMENT '创建者',
    update_by   VARCHAR(64)           DEFAULT ''     COMMENT '更新者',
    del_flag    TINYINT      NOT NULL DEFAULT 0      COMMENT '删除标记:0 未删,1 已删(DO 上用 @TableLogic)',
    PRIMARY KEY (id),
    KEY idx_code (code)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统管理 - 角色';

-- ---------------------------------------------------------------------------
-- 4. 菜单(同时承载权限标识)
--    type=3 的按钮菜单只用于权限点,前端菜单树里会被过滤掉
--    component 为目录时留空(前端 store/modules/permission.ts 只给有 component 的节点建路由)
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS system_menu (
    id             BIGINT       NOT NULL AUTO_INCREMENT COMMENT '主键',
    name           VARCHAR(50)  NOT NULL                COMMENT '菜单名称',
    permission     VARCHAR(100)          DEFAULT ''     COMMENT '权限标识,如 system:user:query',
    type           TINYINT      NOT NULL                COMMENT '类型:1 目录,2 菜单,3 按钮',
    sort           INT          NOT NULL DEFAULT 0      COMMENT '显示顺序',
    parent_id      BIGINT       NOT NULL DEFAULT 0      COMMENT '父级 id,0 为顶级',
    path           VARCHAR(200)          DEFAULT ''     COMMENT '路由地址',
    icon           VARCHAR(100)          DEFAULT ''     COMMENT '图标,如 ep:user',
    component      VARCHAR(255)          DEFAULT ''     COMMENT '组件路径(相对 src/views),目录留空',
    component_name VARCHAR(255)          DEFAULT ''     COMMENT '组件名,用于 keep-alive',
    status         TINYINT      NOT NULL DEFAULT 0      COMMENT '状态:0 启用,1 停用',
    visible        TINYINT      NOT NULL DEFAULT 1      COMMENT '是否显示:1 显示,0 隐藏',
    create_time    DATETIME     NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    update_time    DATETIME     NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
    create_by      VARCHAR(64)           DEFAULT ''     COMMENT '创建者',
    update_by      VARCHAR(64)           DEFAULT ''     COMMENT '更新者',
    del_flag       TINYINT      NOT NULL DEFAULT 0      COMMENT '删除标记:0 未删,1 已删(DO 上用 @TableLogic)',
    PRIMARY KEY (id),
    KEY idx_parent_id (parent_id),
    KEY idx_permission (permission)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统管理 - 菜单与权限';

-- ---------------------------------------------------------------------------
-- 5/6. 用户-角色、角色-菜单 关联表
--      关联表不做软删除(解绑即物理删除),因此不带 del_flag
--      —— 正因为没有软删除,这里可以(也应该)建唯一键:它同时起到
--      「同一角色不会重复授同一个菜单」的约束与「种子脚本可重复执行」的幂等保证
--      (02_system_seed.sql 里用 INSERT IGNORE ... SELECT 批量授权,靠它去重)
--
--      关联表也带齐 4 个审计列(update_* 实际不用)——统一「所有 system_* 表列结构一致」
--      这条规则,可以让每个 DO 都无脑 extends BaseDO,
--      否则 DefaultDBFieldHandler 只对 BaseDO 生效、需要逐个 DO 特殊处理。
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS system_user_role (
    id          BIGINT      NOT NULL AUTO_INCREMENT COMMENT '主键',
    user_id     BIGINT      NOT NULL                COMMENT '用户 id',
    role_id     BIGINT      NOT NULL                COMMENT '角色 id',
    create_time DATETIME    NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    update_time DATETIME    NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
    create_by   VARCHAR(64)          DEFAULT ''     COMMENT '创建者',
    update_by   VARCHAR(64)          DEFAULT ''     COMMENT '更新者',
    PRIMARY KEY (id),
    UNIQUE KEY uk_user_role (user_id, role_id),
    KEY idx_role_id (role_id)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统管理 - 用户与角色关联';

CREATE TABLE IF NOT EXISTS system_role_menu (
    id          BIGINT      NOT NULL AUTO_INCREMENT COMMENT '主键',
    role_id     BIGINT      NOT NULL                COMMENT '角色 id',
    menu_id     BIGINT      NOT NULL                COMMENT '菜单 id',
    create_time DATETIME    NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    update_time DATETIME    NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
    create_by   VARCHAR(64)          DEFAULT ''     COMMENT '创建者',
    update_by   VARCHAR(64)          DEFAULT ''     COMMENT '更新者',
    PRIMARY KEY (id),
    UNIQUE KEY uk_role_menu (role_id, menu_id),
    KEY idx_menu_id (menu_id)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统管理 - 角色与菜单关联';

-- ---------------------------------------------------------------------------
-- 7/8. 字典类型、字典数据
--      前端「字典管理」页列:name / type / status / remark / createTime
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS system_dict_type (
    id          BIGINT       NOT NULL AUTO_INCREMENT COMMENT '主键',
    name        VARCHAR(100) NOT NULL                COMMENT '字典名称',
    type        VARCHAR(100) NOT NULL                COMMENT '字典类型,如 system_user_sex',
    status      TINYINT      NOT NULL DEFAULT 0      COMMENT '状态:0 启用,1 停用',
    remark      VARCHAR(500)          DEFAULT ''     COMMENT '备注',
    create_time DATETIME     NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    update_time DATETIME     NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
    create_by   VARCHAR(64)           DEFAULT ''     COMMENT '创建者',
    update_by   VARCHAR(64)           DEFAULT ''     COMMENT '更新者',
    del_flag    TINYINT      NOT NULL DEFAULT 0      COMMENT '删除标记:0 未删,1 已删(DO 上用 @TableLogic)',
    PRIMARY KEY (id),
    KEY idx_type (type)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统管理 - 字典类型';

CREATE TABLE IF NOT EXISTS system_dict_data (
    id          BIGINT       NOT NULL AUTO_INCREMENT COMMENT '主键',
    sort        INT          NOT NULL DEFAULT 0      COMMENT '显示顺序',
    label       VARCHAR(100) NOT NULL                COMMENT '字典标签',
    value       VARCHAR(100) NOT NULL                COMMENT '字典键值',
    dict_type   VARCHAR(100) NOT NULL                COMMENT '字典类型(关联 system_dict_type.type)',
    status      TINYINT      NOT NULL DEFAULT 0      COMMENT '状态:0 启用,1 停用',
    color_type  VARCHAR(100)          DEFAULT ''     COMMENT '标签颜色(el-tag 的 type 值)',
    css_class   VARCHAR(100)          DEFAULT ''     COMMENT '标签样式',
    remark      VARCHAR(500)          DEFAULT ''     COMMENT '备注',
    create_time DATETIME     NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    update_time DATETIME     NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
    create_by   VARCHAR(64)           DEFAULT ''     COMMENT '创建者',
    update_by   VARCHAR(64)           DEFAULT ''     COMMENT '更新者',
    del_flag    TINYINT      NOT NULL DEFAULT 0      COMMENT '删除标记:0 未删,1 已删(DO 上用 @TableLogic)',
    PRIMARY KEY (id),
    KEY idx_dict_type (dict_type)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统管理 - 字典数据';

-- ---------------------------------------------------------------------------
-- 9/10. OAuth2 访问令牌 / 刷新令牌
--       访问令牌同时缓存进 Redis(key: oauth2_access_token:{token}),DB 是权威存储
--       user_type:2 = 管理后台用户(UserTypeEnum.ADMIN)
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS system_oauth2_access_token (
    id           BIGINT       NOT NULL AUTO_INCREMENT COMMENT '主键',
    user_id      BIGINT       NOT NULL                COMMENT '用户 id',
    user_type    TINYINT      NOT NULL                COMMENT '用户类型:1 会员,2 管理后台用户',
    access_token VARCHAR(255) NOT NULL                COMMENT '访问令牌',
    refresh_token VARCHAR(32) NOT NULL                COMMENT '刷新令牌',
    expires_time DATETIME     NOT NULL                COMMENT '过期时间',
    scope        VARCHAR(255)          DEFAULT ''     COMMENT '授权范围',
    create_time  DATETIME     NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    update_time  DATETIME     NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
    create_by    VARCHAR(64)           DEFAULT ''     COMMENT '创建者',
    update_by    VARCHAR(64)           DEFAULT ''     COMMENT '更新者',
    PRIMARY KEY (id),
    KEY idx_access_token (access_token),
    KEY idx_refresh_token (refresh_token),
    KEY idx_user_id (user_id)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统管理 - OAuth2 访问令牌';

CREATE TABLE IF NOT EXISTS system_oauth2_refresh_token (
    id           BIGINT      NOT NULL AUTO_INCREMENT COMMENT '主键',
    user_id      BIGINT      NOT NULL                COMMENT '用户 id',
    user_type    TINYINT     NOT NULL                COMMENT '用户类型:1 会员,2 管理后台用户',
    refresh_token VARCHAR(32) NOT NULL               COMMENT '刷新令牌',
    expires_time DATETIME    NOT NULL                COMMENT '过期时间',
    create_time  DATETIME    NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    update_time  DATETIME    NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
    create_by    VARCHAR(64)          DEFAULT ''     COMMENT '创建者',
    update_by    VARCHAR(64)          DEFAULT ''     COMMENT '更新者',
    PRIMARY KEY (id),
    KEY idx_refresh_token (refresh_token),
    KEY idx_user_id (user_id)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统管理 - OAuth2 刷新令牌';

-- ---------------------------------------------------------------------------
-- 11. OAuth2 客户端
--     本项目只有「管理后台前端」一个客户端;secret 只用于内部换取令牌,
--     真实密钥应由部署环境注入(禁止把生产密钥提交进仓库)
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS system_oauth2_client (
    id                              BIGINT       NOT NULL AUTO_INCREMENT COMMENT '主键',
    client_id                       VARCHAR(255) NOT NULL                COMMENT '客户端编号',
    secret                          VARCHAR(255) NOT NULL                COMMENT '客户端密钥',
    name                            VARCHAR(255) NOT NULL                COMMENT '客户端名称',
    logo                            VARCHAR(255)          DEFAULT ''     COMMENT '客户端 logo',
    description                     VARCHAR(255)          DEFAULT ''     COMMENT '描述',
    status                          TINYINT      NOT NULL DEFAULT 0      COMMENT '状态:0 启用,1 停用',
    access_token_validity_seconds   INT          NOT NULL DEFAULT 1800   COMMENT '访问令牌有效期(秒)',
    refresh_token_validity_seconds  INT          NOT NULL DEFAULT 2592000 COMMENT '刷新令牌有效期(秒),默认 30 天',
    redirect_uris                   VARCHAR(1024)         DEFAULT ''     COMMENT '可重定向的 URI',
    authorized_grant_types          VARCHAR(255)          DEFAULT ''     COMMENT '授权类型,逗号分隔',
    scopes                          VARCHAR(255)          DEFAULT ''     COMMENT '授权范围,逗号分隔',
    auto_approve_scopes             VARCHAR(255)          DEFAULT ''     COMMENT '自动授权的范围',
    additional_information          VARCHAR(4096)         DEFAULT ''     COMMENT '附加信息',
    create_time                     DATETIME     NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    update_time                     DATETIME     NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
    create_by                       VARCHAR(64)           DEFAULT ''     COMMENT '创建者',
    update_by                       VARCHAR(64)           DEFAULT ''     COMMENT '更新者',
    PRIMARY KEY (id),
    KEY idx_client_id (client_id)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统管理 - OAuth2 客户端';

-- ---------------------------------------------------------------------------
-- 12. 登录日志
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS system_login_log (
    id          BIGINT      NOT NULL AUTO_INCREMENT COMMENT '主键',
    user_id     BIGINT               DEFAULT NULL   COMMENT '用户 id(登录失败时为空)',
    user_type   TINYINT     NOT NULL DEFAULT 2      COMMENT '用户类型:1 会员,2 管理后台用户',
    username    VARCHAR(50) NOT NULL DEFAULT ''     COMMENT '登录账号',
    log_type    TINYINT     NOT NULL                COMMENT '日志类型:1 账号登录,2 社交登录,3 自己登出,4 被删除登出(见 LoginLogTypeEnum)',
    result      TINYINT     NOT NULL DEFAULT 0      COMMENT '结果:0 成功,非 0 失败(10 密码错,11 验证码错,12 账号禁用;见 LoginResultEnum)',
    ip          VARCHAR(50)          DEFAULT ''     COMMENT '登录 IP',
    user_agent  VARCHAR(512)         DEFAULT ''     COMMENT '浏览器 UA',
    create_time DATETIME    NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    update_time DATETIME    NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间(日志只插不改,此列仅为对齐 BaseDO)',
    create_by   VARCHAR(64)          DEFAULT ''     COMMENT '创建者',
    update_by   VARCHAR(64)          DEFAULT ''     COMMENT '更新者',
    PRIMARY KEY (id),
    KEY idx_user_id (user_id),
    KEY idx_username (username),
    KEY idx_create_time (create_time)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统管理 - 登录日志';

-- ---------------------------------------------------------------------------
-- 13. 操作日志
--     字段直接对齐前端「日志管理」页的列:
--     userNickname / module / name / type / requestMethod / requestUrl / ip / duration / resultCode
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS system_operate_log (
    id             BIGINT       NOT NULL AUTO_INCREMENT COMMENT '主键',
    user_id        BIGINT                DEFAULT NULL   COMMENT '操作人 id',
    user_nickname  VARCHAR(30)           DEFAULT ''     COMMENT '操作人昵称(冗余,避免列表页 join)',
    `module`       VARCHAR(100)          DEFAULT ''     COMMENT '模块名,如 用户管理',
    `name`         VARCHAR(100)          DEFAULT ''     COMMENT '操作名,如 新增用户',
    `type`         VARCHAR(20)           DEFAULT ''     COMMENT '操作类型:查询/新增/修改/删除',
    request_method VARCHAR(10)           DEFAULT ''     COMMENT '请求方法:GET/POST/PUT/DELETE',
    request_url    VARCHAR(255)          DEFAULT ''     COMMENT '请求地址',
    ip             VARCHAR(50)           DEFAULT ''     COMMENT '操作 IP',
    duration       INT          NOT NULL DEFAULT 0      COMMENT '耗时(毫秒)',
    result_code    INT          NOT NULL DEFAULT 0      COMMENT '结果码(CommonResult.code,0 为成功)',
    create_time    DATETIME     NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    update_time    DATETIME     NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间(日志只插不改,此列仅为对齐 BaseDO)',
    create_by      VARCHAR(64)           DEFAULT ''     COMMENT '创建者',
    update_by      VARCHAR(64)           DEFAULT ''     COMMENT '更新者',
    PRIMARY KEY (id),
    KEY idx_user_id (user_id),
    KEY idx_create_time (create_time)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统管理 - 操作日志';

-- ---------------------------------------------------------------------------
-- 校验:应输出 13 张 system_* 表
--   system_dict_data / system_dict_type / system_login_log / system_menu
--   system_oauth2_access_token / system_oauth2_client / system_oauth2_refresh_token
--   system_operate_log / system_org / system_role / system_role_menu
--   system_user_role / system_users
-- ---------------------------------------------------------------------------
SELECT table_name, table_comment
FROM information_schema.tables
WHERE table_schema = 'parking_cloud' AND table_name LIKE 'system\_%'
ORDER BY table_name;