# redash开源报表中文版 **Repository Path**: ycfarmer/redash_cn ## Basic Information - **Project Name**: redash开源报表中文版 - **Description**: 基于 Redash v26.3.0 的中文定制版(非官方):在保留全部原生能力(50+ 数据源、可视化、定时刷新、告警)基础上,增强菜单导航、组权限、字段脱敏、列宽拖拽,更适合企业内部报表场景,完全开源的报表系统。 - **Primary Language**: Python - **License**: BSD-2-Clause - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 15 - **Forks**: 5 - **Created**: 2021-08-04 - **Last Updated**: 2026-09-04 ## Categories & Tags **Categories**: Uncategorized **Tags**: 报表, redash ## README # Redash 定制发行版 > 基于 [Redash](https://github.com/getredash/redash) **v26.3.0** 的二次开发版本。 > 在保留上游全部能力的前提下,围绕**报表组织与权限**、**数据脱敏**、**表格交互**、**中文场景**做了增强。 [![License](https://img.shields.io/badge/license-BSD--2--Clause-blue.svg)](./LICENSE) [![Based on](https://img.shields.io/badge/based%20on-Redash%20v26.3.0-orange.svg)](https://github.com/getredash/redash) --- ## 这是什么 本项目是 Redash v26.3.0 的一个**定制发行版(fork)**,不是官方 Redash。 它保留了 Redash 原生的能力:50+ 数据源接入、SQL 编辑器、可视化与仪表板、定时刷新、告警、REST API; 在此之上补充了企业内部分享报表时经常缺失的几块能力(菜单化导航、按用户组授权、字段级脱敏、列宽调整等)。 完整的定制点清单见 **[CUSTOMIZATION.md](./CUSTOMIZATION.md)**。 > ⚠️ 如果你是 Redash 官方用户,请前往 。 > 本仓库不接受上游 issue,也不承担上游问题的排查。 --- ## 相对上游的主要增强 | 分类 | 能力 | 说明 | |---|---|---| | 报表导航 | 菜单 + 标签两级导航 | 报表按「菜单 → 标签」分组,左侧树形浏览 | | | 「其它」分组 | 管理员可查看未匹配任何菜单的报表 | | 权限 | 用户组 ↔ 报表授权 | 非管理员只能看到所属用户组被授权的报表 | | | 默认内置角色 | 初始化时自动创建「查询 / 报表 / 下载 / 编辑报表」4 个角色,可直接把用户加入 | | | 菜单管理 | 独立的菜单 CRUD 与角色列表接口 | | 数据安全 | 字段级脱敏 | 基于 SQL 解析(sqlglot)识别字段来源,按规则脱敏 | | 表格交互 | 列宽拖拽 | 报表编辑态下拖动列宽,按报表维度持久化 | | | 数据过期自动刷新 | 存在超过 1 小时未刷新的查询时自动触发刷新 | | | 双处刷新入口 | widget 顶部与底部同时提供刷新按钮与更新时间 | | 中文场景 | 日期与时间本地化 | 日期范围、时间展示等改为中文 | | 导出 | Excel 日期列 | 日期/时间列导出为真正的 Excel 日期格式,而非字符串 | --- ## 截图 ### 报表页 左侧「菜单 → 标签」两级导航;管理员可见「其它」分组(收录未匹配菜单的报表); 报表编辑态可拖动表格列宽;存在超过 1 小时未刷新的查询时自动触发刷新。 报表页:菜单 + 标签分组 + 列宽拖拽 + 数据过期自动刷新 ### 权限管理 | 权限矩阵 | 授权实例 | |---|---| | admin 组的完整权限矩阵 | admin 组已绑定的看板 | - **权限矩阵**:`admin` 组可分配的权限(超级管理员、创建 / 修改 / 查询 / 执行 / 排程 / 告警等) - **授权实例**:`admin` 组已绑定「我要测试」看板(带 `add` 标签),可 Remove 解除授权 ## 环境要求 | 组件 | 版本 | |---|---| | Python | 3.13 | | Node.js | >= 16 < 21 | | Yarn | ^1.22.10 | | PostgreSQL | 推荐 13+(含 `pg_trgm` 扩展) | | Redis | 3+ | --- ## 快速开始 ### 1. 准备数据库与 Redis ```bash # PostgreSQL createdb redash psql -d redash -c "CREATE EXTENSION IF NOT EXISTS pg_trgm;" ``` ### 2. 安装依赖 ```bash # 后端 poetry install # 或使用你自己的虚拟环境 + pip install -r requirements.txt # 前端 yarn install # 会自动构建本地依赖包 viz-lib ``` ### 3. 初始化 新库有两种方式,**二选一**。 #### 方式一:`create_tables`(推荐) ```bash python manage.py database create_tables ``` 根据 SQLAlchemy 模型自动建表,创建 23 张业务表、索引、外键,以及查询全文搜索所需的 `tsq_state` 类型与 `tsq_*` 函数。 > ⚠️ 该命令内部有 `is_db_empty()` 判断,**只对空库生效**,已存在任何表时会直接跳过。 #### 方式二:直接执行 `schema.sql` 不想走 Python 命令时(例如在堡垒机、CI 上只有 psql 客户端),可直接执行完整的建库 SQL: ```bash createdb redash psql -d redash -f schema.sql ``` `schema.sql` 与方式一等价,包含同样的表、索引、外键、全文搜索函数与触发器,并在末尾写入 Alembic 版本号 `db0aca1ebd32`。 > 写入版本号这一步很关键:否则 Alembic 认为库是空的,以后执行 `flask db upgrade` 会从第一个迁移开始重跑并全部失败。 > 升级上游后需同步修改 `schema.sql` 末尾的版本号。 #### 已有库升级 两种方式都只适用于空库。已有数据的库需要手工执行 SQL —— **本仓库不提供自动迁移**: ```bash psql -d redash -f pg17_sqltext_add.sql ``` 该脚本全部使用 `IF NOT EXISTS`,可重复执行。执行前请确认脚本头部的两条数据检查查询返回 0 行,否则唯一索引会创建失败(脚本注释里有对应的去重语句)。 ### 4. 默认内置角色 上面两种方式只建了表结构。创建组织与管理员账号时(见下一节的三种方式),会**一并创建 4 个默认内置角色**: | 角色 | 权限(`permissions`) | 用途 | |---|---|---| | 查询 | `list_dashboards`、`list_alerts`、`list_data_sources`、`view_source`、`view_query`、`execute_query` | 查看并执行查询、查看数据源 | | 报表 | `list_dashboards` | 查看报表列表与报表内容 | | 下载 | `list_dashboards`、`list_alerts`、`list_data_sources`、`view_source`、`view_query`、`execute_query` | 在「查询」权限基础上,额外允许导出查询结果(xlsx / csv) | | 编辑报表 | `list_dashboards`、`create_dashboard`、`edit_dashboard` | 新建与修改报表 | 要点: - 角色就是**用户组**,在「设置 → 用户组」里把用户加入对应组即可授权,一个用户可同时属于多个角色 - 「下载」角色的**名称必须包含“下载”二字**:导出查询结果时后端按用户所属组的名称是否含“下载”判定(见 `redash/handlers/query_results.py`),改名会让该角色失去下载能力 - 角色类型为 `regular`,管理员可自行调整权限、改名或删除 - 具体某张报表 / 某条查询能否访问,还取决于对象级授权(报表的「用户组 ↔ 报表授权」、查询的共享设置),角色只是权限集合,不等于放行所有数据 **已有库补建**(角色被删、或组织是先建的): ```bash # 命令行(推荐,会处理所有组织) python manage.py groups create_default_roles # 所有组织 python manage.py groups create_default_roles --org default # 或 SQL(幂等,只处理 default 组织) psql -d redash -f init_roles.sql ``` > 补建逻辑幂等:已存在同名角色时跳过,不会重复创建,也不会覆盖已有权限。 > 角色定义见 `redash/models/users.py` 的 `Group.DEFAULT_ROLE_GROUPS`。 > > 提示:「设置 → 用户组 → 权限设置」页展示的权限项来自 `roles` 字典表(`api/roles_list`)。 > 该表为空时页面不显示权限项,但角色的默认权限已入库,把用户加入角色即可生效。 ### 5. 创建管理员账号 建表之后库里**没有任何账号**,直接访问是登录不了的。三选一: #### 方式一:命令行(推荐) ```bash python manage.py users create_root admin@example.com "管理员" --password "你的密码" ``` 会一并创建默认组织、内置 `admin` / `default` 用户组,以及上一节的 4 个默认内置角色。 #### 方式二:网页引导 启动服务后访问 ,按页面提示创建组织与管理员(同样会创建 4 个默认内置角色)。 > 该页面仅在库中没有组织时可用,初始化后会自动失效。 > 本版已移除上游 `/setup` 里的订阅上报(原逻辑会把管理员姓名/邮箱/组织名发往 `version.redash.io`),详见 CUSTOMIZATION.md。 #### 方式三:SQL 只有 psql、没有 Python 环境时,用模板生成(组织、管理员、4 个默认内置角色一次性建好): ```bash cp init_admin.sql.example init_admin.sql # 生成密码哈希 python -c "from passlib.apps import custom_app_context as c; print(c.hash('你的密码'))" ``` 把输出的哈希填进 `init_admin.sql` 里的 ``,然后执行: ```bash psql -d redash -f init_admin.sql ``` > ⚠️ **不要把填好密码哈希的 `init_admin.sql` 提交到仓库**(已在 `.gitignore` 中)。 > 只有 `init_admin.sql.example` 模板应该入库。 忘记密码时重置: ```bash python manage.py users password admin@example.com 新密码 ``` ### 6. 构建前端(可选) 仓库已内置编译好的前端产物(`client/dist`),**正常情况下无需构建**,直接跳到下一步。 只有在修改了前端代码(含 `viz-lib/`)之后才需要重新构建: ```bash yarn build # 先编译 viz-lib,再打包 client ``` ### 7. 启动 本项目使用 supervisord 编排进程(gunicorn + RQ worker + RQ scheduler): ```bash ./start.sh ``` 编排定义在 `supervisord.ini`: | 进程 | 命令 | 数量 | |---|---|---| | server | `gunicorn redash.wsgi:app -b 0.0.0.0:5000 --worker-class gevent --workers 4` | 1 | | scheduler | `python3 manage.py rq scheduler` | 1 | | worker | `python3 manage.py rq worker` | 7 | 默认监听 `http://0.0.0.0:5000`。首次使用请先访问 `/setup` 或用 `users create_root` 创建管理员(见「创建管理员账号」一节)。 > 上游提供的 Docker Compose 方案(`compose.yaml`)仍然可用,适合本地开发调试。 --- ## 项目结构 ``` redash/ Flask 后端(API、模型、任务、query runner) models/ 数据模型,含 sqlglot_util.py(SQL 字段解析) handlers/api.py REST 路由注册 tasks/ RQ 异步任务与排程 client/app/ 前端 React 应用(页面、组件、services) client/dist/ 已编译的前端产物(已入库,开箱即用) viz-lib/ 可视化组件库(@redash/viz),本地包,通过 file: 依赖 migrations/ Alembic 数据库迁移(上游) schema.sql 完整建库 SQL,可代替 create_tables 使用 pg17_sqltext_add.sql 已有库升级脚本 supervisord.ini 进程编排 ``` --- ## 开发 ### 启动本地开发服务 Redash 通过环境变量完成配置。本地开发时在 shell 中导出即可: ```bash source /path/to/venv/bin/activate # ---- 必填 ---- export REDASH_HOST="http://localhost:5000" export REDASH_COOKIE_SECRET="<随机字符串,可用 pwgen -1s 32 生成>" export REDASH_DATABASE_URL="postgresql://<用户>:<密码>@localhost:5432/<库名>" export REDASH_REDIS_URL="redis://localhost:6379/0" # ---- 邮件(可选;不配则无法发送告警与邀请邮件)---- export REDASH_MAIL_SERVER="" export REDASH_MAIL_PORT=465 export REDASH_MAIL_USE_SSL="true" export REDASH_MAIL_USERNAME="<发件账号>" export REDASH_MAIL_PASSWORD="<密码或授权码>" export REDASH_MAIL_DEFAULT_SENDER="<发件地址>" # ---- 启动 Web 服务(--debug 开启调试,勿用于生产)---- python manage.py runserver --host 0.0.0.0 --port 5000 --debug ``` 本地开发还需要**另外开两个终端**启动异步任务组件,否则定时刷新、告警、查询执行都不会工作: ```bash python manage.py rq scheduler # 排程:触发定时刷新与告警检查 python manage.py rq worker # 执行查询等后台任务 ``` > 生产环境请用 `./start.sh`(supervisord)代替上述三条命令,见「快速开始」。 ### 环境变量说明 | 变量 | 必填 | 默认值 | 说明 | |---|---|---|---| | `REDASH_HOST` | | `""` | 站点对外访问地址,影响邮件与分享链接 | | `REDASH_AVATAR_PROVIDER` | | `local` | 用户头像来源:`local` 由服务端本地生成(默认,不访问外网);`gravatar` 走 Gravatar | | `REDASH_AVATAR_GRAVATAR_URL_TEMPLATE` | | `https://gravatar.loli.net/avatar/{hash}?s={size}&d=identicon` | 仅 `gravatar` 模式生效,可换成其它镜像 | | `REDASH_AVATAR_SIZE` | | `40` | 头像尺寸(像素) | | `REDASH_COOKIE_SECRET` | ✅ | — | 会话 cookie 签名密钥;未设置会直接启动失败 | | `REDASH_DATABASE_URL` | ✅ | `postgresql:///postgres` | PostgreSQL 连接串(也接受 `DATABASE_URL`) | | `REDASH_REDIS_URL` | | `redis://localhost:6379/0` | Redis 连接串(也接受 `REDIS_URL`) | | `REDASH_MAIL_SERVER` | | `localhost` | SMTP 服务器 | | `REDASH_MAIL_PORT` | | `25` | SMTP 端口 | | `REDASH_MAIL_USE_SSL` | | `false` | 是否启用 SSL(465 端口通常需要开启) | | `REDASH_MAIL_USERNAME` | | — | 发件账号 | | `REDASH_MAIL_PASSWORD` | | — | 密码或授权码 | | `REDASH_MAIL_DEFAULT_SENDER` | | — | 发件地址 | | `REDASH_VERSION_CHECK` | | `false` | 是否每日向 `version.redash.io` 上报版本并检查上游新版本(见下) | > `REDASH_VERSION_CHECK` 默认关闭 —— 上游为 `true`,会每天 POST 到 > `https://version.redash.io/api/report`。本项目是定制 fork,上游版本提示没有意义, > 故默认不外发。需要恢复上游行为时设为 `true`。 完整配置项见 `redash/settings/__init__.py`,支持的环境变量远多于上表。 > ⚠️ 环境变量包含数据库与邮箱密码,**不要提交到仓库**。 > 建议写入 shell 启动脚本或 `.env`(已被 `.gitignore` 忽略),切勿把真实值写进文档或代码注释。 ### 前端开发 ```bash yarn watch # 前端热更新(同时监听 viz-lib) yarn lint # ESLint yarn test # 前端类型检查 + Jest cd viz-lib && yarn test # 可视化组件库测试 ``` > ⚠️ **改了前端代码必须重新构建并提交 `client/dist`**。 > 本仓库把编译产物纳入了版本管理(让使用者免去构建步骤), > 所以只提交源码而不重新 `yarn build` 的话,其他人拉到的仍是旧界面。 > `viz-lib/` 的改动同样需要先 `yarn build:viz`(`yarn build` 已包含这一步)。 后端测试: ```bash make tests ``` 提交规范与分支约定见 [CONTRIBUTING.md](./CONTRIBUTING.md)。 --- ## 新增的 REST API | 方法 | 路径 | 说明 | |---|---|---| | GET/POST | `/api/menus` | 菜单列表 / 新建 | | GET/POST/DELETE | `/api/menus/` | 单个菜单 | | GET | `/api/roles_list` | 角色列表 | | GET | `/api/user/dashboard_groups` | 当前用户可访问的报表 | | GET/POST | `/api/groups//dashboards` | 用户组授权的报表 | | DELETE | `/api/groups//dashboards/` | 取消授权 | --- ## 常见问题 **Q:能不能直接跟随上游升级?** 可以,但需注意本版改动集中在 `redash/models/`、`redash/handlers/`、`client/app/pages/dashboards/` 与 `viz-lib/src/visualizations/table/`,合并时这几处大概率冲突。 **Q:脱敏规则怎么配置?** 脱敏基于 `redash/models/sqlglot_util.py` 解析 SQL 得到「输出字段 → 真实表字段」映射,再按规则处理。规则数据存于数据库,详见 `CUSTOMIZATION.md`。 **Q:列宽是全局的还是按报表的?** 按报表(widget)维度保存,存在 `widgets.options.columnWidths` 中,同一个可视化加到不同报表互不干扰。 --- ## 许可证 **BSD-2-Clause** —— 详见 [LICENSE](./LICENSE)。 本项目是 Redash 的衍生作品,Redash 的版权归其原作者所有(Copyright (c) 2013-2020, Arik Fraimovich)。 本仓库中新增与修改的代码同样以 BSD-2-Clause 发布。 --- ## 致谢 - [Redash](https://github.com/getredash/redash) 及其贡献者,提供了本项目所基于的优秀开源 BI 平台。 - [sqlglot](https://github.com/tobymao/sqlglot),支撑了字段解析与脱敏能力。