2026/3/24 17:50:31
网站建设
项目流程
做网站需要多大的内存,windows优化大师有什么功能,哈西建站优化,做网站要几个人 要多少钱大家好#xff01;我是CSDN的Python新手博主#xff5e; 上一篇我们完成了看板的跨系统联动与可视化任务编排#xff0c;解决了多系统数据互通与自动化办公需求#xff0c;但甲方客户反馈两大核心痛点#xff1a;① 可视化体验单一#xff0c;现有图表多为静态展示#…大家好我是CSDN的Python新手博主 上一篇我们完成了看板的跨系统联动与可视化任务编排解决了多系统数据互通与自动化办公需求但甲方客户反馈两大核心痛点① 可视化体验单一现有图表多为静态展示无法实现数据钻取、联动筛选、自定义查看数据分析效率低② 不支持移动端适配员工外出时无法通过手机查看看板数据、处理待办任务只能依赖电脑灵活性不足③ 多终端数据不同步电脑端修改的看板配置、查看的历史数据手机端无法同步操作体验割裂。今天就带来超落地的新手实战项目——办公看板升级交互式可视化移动端适配多终端同步本次基于之前的“跨系统联动看板”代码新增3大核心功能① 交互式可视化升级ECharts进阶实现图表联动、数据钻取、自定义筛选、主题切换支持拖拽调整图表位置② 移动端全面适配基于Bootstrap响应式布局优化看板组件、适配触摸操作支持手机/平板横屏/竖屏切换③ 多终端数据同步基于Redis缓存Token身份校验实现看板配置、查看记录、待办任务、操作日志多终端实时同步。全程基于现有技术栈FlaskMySQLEChartsBootstrapRedis新增交互式组件、响应式布局、多终端同步引擎代码注释详细新手只需配置适配参数、复制代码就能完成升级让看板兼顾数据分析效率与移动办公灵活性一、本次学习目标掌握ECharts交互式可视化技巧实现图表联动、数据钻取、自定义筛选、主题切换提升数据分析体验新手也能快速上手进阶配置学会Bootstrap响应式布局开发优化看板组件结构适配不同终端电脑、手机、平板解决移动端显示错乱、操作不便的问题理解多终端同步原理基于Redis缓存与Token校验实现看板配置、查看记录、待办任务等数据的实时同步确保多终端操作一致性实现交互式可视化、移动端适配、多终端同步的功能闭环支持员工随时随地查看数据、处理任务提升办公灵活性适配企业移动办公场景支持移动端快捷操作一键刷新、快速筛选、待办处理兼顾电脑端数据分析与移动端便捷性。二、前期准备安装核心依赖库安装核心依赖Redis缓存、响应式组件、ECharts进阶适配pip3 install redis flask-cors flask-bootstrap5 flask-wtf -i https://pypi.tuna.tsinghua.edu.cn/simple确保已有依赖正常Flask、ECharts、跨系统联动等pip3 install --upgrade flask flask-login flask-sqlalchemy requests celery pymysql openpyxl -i https://pypi.tuna.tsinghua.edu.cn/simple说明多终端同步用Redis实现数据缓存存储看板配置、查看记录等移动端适配用Bootstrap5响应式框架无需额外开发移动端页面交互式可视化基于ECharts进阶API复用现有图表基础只需新增配置。第三方服务与配置准备交互式可视化配置定义图表联动规则如点击柱状图某一项折线图同步显示对应数据、数据钻取层级如从部门数据钻取到个人数据、筛选条件时间范围、数据类型、部门筛选、可选主题浅色/深色/自定义配色移动端适配配置设置不同终端的看板布局电脑端多列布局、手机端单列布局、组件适配参数按钮大小、字体大小、图表尺寸、触摸操作规则滑动切换看板、长按筛选多终端同步配置确定同步数据范围看板配置、查看记录、待办任务、操作日志、缓存过期时间默认24小时关键数据永久缓存、Token校验规则同一账号多终端登录Token同步生效环境准备确保Redis服务正常启动复用之前Celery使用的Redis无需新增云服务器开放移动端访问端口配置跨域支持手机端访问后端接口。数据库表优化与创建– 连接MySQL数据库替换为你的数据库信息mysql -u office_user -p -h 47.108.xxx.xxx office_data– 创建可视化配置表visual_configCREATE TABLE visual_config (id INT AUTO_INCREMENT PRIMARY KEY,user_id INT NOT NULL COMMENT ‘用户ID0表示全局配置’,dashboard_id INT NOT NULL COMMENT ‘看板ID’,chart_config TEXT NOT NULL COMMENT ‘图表配置JSON格式含ECharts参数、位置、大小’,filter_config TEXT NOT NULL COMMENT ‘筛选配置JSON格式含默认筛选条件、可选筛选项’,theme VARCHAR(20) DEFAULT ‘light’ COMMENT ‘可视化主题light/dark/custom’,theme_config TEXT NULL COMMENT ‘自定义主题配置JSON格式配色方案’,is_default TINYINT(1) DEFAULT 0 COMMENT ‘是否为默认配置1-是0-否’,create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT ‘创建时间’,update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT ‘更新时间’,KEY idx_user_dashboard (user_id, dashboard_id),FOREIGN KEY (dashboard_id) REFERENCES dashboard_info(id) ON DELETE CASCADE) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT‘交互式可视化配置表’;– 创建终端同步记录表terminal_syncCREATE TABLE terminal_sync (id BIGINT AUTO_INCREMENT PRIMARY KEY,user_id INT NOT NULL COMMENT ‘用户ID’,token VARCHAR(100) NOT NULL COMMENT ‘用户登录Token’,terminal_type ENUM(‘pc’, ‘mobile’, ‘pad’) NOT NULL COMMENT ‘终端类型’,sync_data TEXT NOT NULL COMMENT ‘同步数据JSON格式看板配置、查看记录等’,sync_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT ‘同步时间’,last_operate_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT ‘最后操作时间’,KEY idx_user_token (user_id, token),KEY idx_terminal_type (terminal_type)) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT‘多终端同步记录表’;– 创建用户看板偏好表user_dashboard_preferCREATE TABLE user_dashboard_prefer (id INT AUTO_INCREMENT PRIMARY KEY,user_id INT NOT NULL COMMENT ‘用户ID’,dashboard_id INT NOT NULL COMMENT ‘看板ID’,prefer_config TEXT NOT NULL COMMENT ‘偏好配置JSON格式默认查看页面、快捷操作、排序方式’,recent_view TEXT NULL COMMENT ‘最近查看记录JSON格式图表ID、查看时间’,mobile_layout TINYINT(1) DEFAULT 1 COMMENT ‘移动端布局1-单列2-双列’,create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT ‘创建时间’,update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT ‘更新时间’,UNIQUE KEY uk_user_dashboard (user_id, dashboard_id),FOREIGN KEY (dashboard_id) REFERENCES dashboard_info(id) ON DELETE CASCADE) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT‘用户看板偏好表适配多终端’;– 初始化全局可视化配置示例INSERT INTO visual_config (user_id, dashboard_id, chart_config, filter_config, theme, is_default)VALUES (0,1, – 假设看板ID为1主看板‘{“charts”:[{“id”:1,“type”:“bar”,“position”:{“x”:0,“y”:0,“width”:50,“height”:40},“echarts_config”:{“title”:{“text”:“每日订单量”},“xAxis”:{“type”:“category”},“yAxis”:{“type”:“value”}}},{“id”:2,“type”:“line”,“position”:{“x”:50,“y”:0,“width”:50,“height”:40},“echarts_config”:{“title”:{“text”:“每日销售额”}}}]}’,‘{“default_filter”:{“start_date”:“2026-01-01”,“end_date”:“2026-01-31”,“dept”:“all”},“optional_filters”:[“dept”,“product”,“status”]}’,‘light’,1);– 初始化用户看板偏好示例INSERT INTO user_dashboard_prefer (user_id, dashboard_id, prefer_config, recent_view, mobile_layout)VALUES (1, – 管理员用户ID1,‘{“default_page”:“data_overview”,“quick_operate”:[“refresh”,“export”,“filter”],“sort_type”:“time_desc”}’,‘[{“chart_id”:1,“view_time”:“2026-01-26 10:30:00”},{“chart_id”:2,“view_time”:“2026-01-26 10:35:00”}]’,1);三、实战交互式可视化移动端适配多终端同步升级第一步交互式可视化升级实现图表联动与数据钻取-- coding: utf-8 --visual_upgrade.py 交互式可视化升级模块import jsonfrom flask import Blueprint, request, jsonify, gfrom flask_login import login_required, current_userfrom models import db, VisualConfig, DashboardInfo, UserDashboardPreferfrom audit_engine import audit_logfrom dotenv import load_dotenvimport osimport redis加载环境变量load_dotenv()初始化Redis连接用于缓存可视化配置提升响应速度redis_client redis.Redis(hostos.getenv(“REDIS_HOST”, “localhost”),portint(os.getenv(“REDIS_PORT”, 6379)),dbint(os.getenv(“REDIS_DB”, 0)),decode_responsesTrue)visual_bp Blueprint(“visual”,name) 核心功能获取交互式可视化配置 def get_visual_config(user_id, dashboard_id):“”获取用户的看板可视化配置优先用户自定义无则用全局配置:param user_id: 用户ID:param dashboard_id: 看板ID:return: 可视化配置字典“”# 先从Redis缓存获取提升速度cache_key fvisual_config:{user_id}:{dashboard_id}cache_config redis_client.get(cache_key)if cache_config:return json.loads(cache_config)# 从数据库获取优先用户自定义配置 visual_config VisualConfig.query.filter_by( user_iduser_id, dashboard_iddashboard_id ).order_by(VisualConfig.is_default.desc()).first() # 无用户配置获取全局配置user_id0 if not visual_config: visual_config VisualConfig.query.filter_by( user_id0, dashboard_iddashboard_id, is_default1 ).first() if not visual_config: raise Exception(f未找到看板{dashboard_id}的可视化配置) # 格式化配置数据 config_data { chart_config: json.loads(visual_config.chart_config), filter_config: json.loads(visual_config.filter_config), theme: visual_config.theme, theme_config: json.loads(visual_config.theme_config) if visual_config.theme_config else None } # 存入Redis缓存过期时间24小时 redis_client.setex(cache_key, 86400, json.dumps(config_data)) return config_data 核心功能图表联动与数据钻取逻辑 def get_linked_chart_data(chart_id, drill_down_paramsNone):“”获取联动图表数据、钻取数据:param chart_id: 触发联动的图表ID:param drill_down_params: 数据钻取参数如部门ID、时间范围:return: 联动图表数据字典“”# 模拟数据实际项目中从数据库/跨系统接口获取base_data {1: {“name”: “每日订单量”, “type”: “bar”, “data”: [120, 180, 150, 200, 220, 250]},2: {“name”: “每日销售额”, “type”: “line”, “data”: [12000, 18000, 15000, 20000, 22000, 25000]},3: {“name”: “订单来源分布”, “type”: “pie”, “data”: [{“name”: “线上”, “value”: 600}, {“name”: “线下”, “value”: 300}]}}# 图表联动点击图表1订单量联动图表2销售额显示对应数据 if chart_id 1 and not drill_down_params: return { trigger_chart: base_data[1], linked_charts: [base_data[2]] # 联动图表2 } # 数据钻取点击图表1的某一项如200钻取显示该日各部门订单量 if chart_id 1 and drill_down_params: day drill_down_params.get(day, 3) # 假设点击第3天索引3数据200 drill_data { name: f第{day1}天各部门订单量, type: bar, data: [{name: 销售部, value: 80}, {name: 市场部, value: 60}, {name: 客服部, value: 60}] } return { trigger_chart: base_data[1], drill_down_data: drill_data # 钻取数据 } # 默认返回所有图表数据 return {all_charts: base_data} 接口交互式可视化配置管理 visual_bp.route(“/visual/config/int:dashboard_id”, methods[“GET”])login_requireddef get_visual_config_api(dashboard_id):“”“获取看板交互式可视化配置”“”try:config_data get_visual_config(current_user.id, dashboard_id)return jsonify({“success”: True, “data”: config_data})except Exception as e:return jsonify({“success”: False, “error”: str(e)})visual_bp.route(“/visual/config/save/int:dashboard_id”, methods[“POST”])login_requiredaudit_log(“update”)def save_visual_config(dashboard_id):“”“保存用户自定义可视化配置图表位置、筛选条件、主题”“”data request.get_json()required_fields [“chart_config”, “filter_config”]for field in required_fields:if not data.get(field):return jsonify({“success”: False, “error”: f缺少必填字段{field}})try: # 验证JSON格式 json.loads(data[chart_config]) json.loads(data[filter_config]) if data.get(theme_config): json.loads(data[theme_config]) except json.JSONDecodeError: return jsonify({success: False, error: 配置字段格式错误需JSON}) # 检查是否已有配置有则更新无则新增 visual_config VisualConfig.query.filter_by( user_idcurrent_user.id, dashboard_iddashboard_id ).first() if visual_config: visual_config.chart_config data[chart_config] visual_config.filter_config data[filter_config] visual_config.theme data.get(theme, light) visual_config.theme_config data.get(theme_config) else: visual_config VisualConfig( user_idcurrent_user.id, dashboard_iddashboard_id, chart_configdata[chart_config], filter_configdata[filter_config], themedata.get(theme, light), theme_configdata.get(theme_config), is_default0 ) db.session.add(visual_config) db.session.commit() # 更新Redis缓存 cache_key fvisual_config:{current_user.id}:{dashboard_id} config_data { chart_config: json.loads(data[chart_config]), filter_config: json.loads(data[filter_config]), theme: data.get(theme, light), theme_config: json.loads(data[theme_config]) if data.get(theme_config) else None } redis_client.setex(cache_key, 86400, json.dumps(config_data)) return jsonify({success: True, msg: 可视化配置保存成功}) 接口图表联动与数据钻取 visual_bp.route(“/visual/chart/link”, methods[“POST”])login_requireddef chart_link_api():“”“图表联动与数据钻取接口”“”data request.get_json()chart_id data.get(“chart_id”)drill_down_params data.get(“drill_down_params”)if not chart_id: return jsonify({success: False, error: 缺少图表ID}) try: chart_data get_linked_chart_data(chart_id, drill_down_params) return jsonify({success: True, data: chart_data}) except Exception as e: return jsonify({success: False, error: str(e)}) 接口主题切换 visual_bp.route(“/visual/theme/switch/int:dashboard_id”, methods[“POST”])login_requireddef switch_theme(dashboard_id):“”“切换看板可视化主题浅色/深色/自定义”“”data request.get_json()theme data.get(“theme”)if not theme or theme not in [“light”, “dark”, “custom”]:return jsonify({“success”: False, “error”: “无效的主题类型仅支持light/dark/custom”})# 更新数据库配置 visual_config VisualConfig.query.filter_by( user_idcurrent_user.id, dashboard_iddashboard_id ).first() if not visual_config: # 无用户自定义配置新增配置 visual_config VisualConfig( user_idcurrent_user.id, dashboard_iddashboard_id, chart_configjson.dumps({charts: []}), filter_configjson.dumps({default_filter: {}, optional_filters: []}), themetheme, theme_configdata.get(theme_config), is_default0 ) db.session.add(visual_config) else: visual_config.theme theme if theme custom: if not data.get(theme_config): return jsonify({success: False, error: 自定义主题需传入theme_config配置}) visual_config.theme_config data[theme_config] else: visual_config.theme_config None db.session.commit() # 更新Redis缓存 cache_key fvisual_config:{current_user.id}:{dashboard_id} config_data get_visual_config(current_user.id, dashboard_id) redis_client.setex(cache_key, 86400, json.dumps(config_data)) return jsonify({success: True, msg: f主题切换为{theme}成功}){% extends “base.html” %}{% block content %}交互式数据看板!-- 筛选条件 -- div classd-flex flex-wrap align-items-center gap-2 idfilterBar select classform-select form-select-sm iddeptFilter option valueall selected全部部门/option option valuesales销售部/option option valuemarket市场部/option option valueservice客服部/option /select input typedate classform-control form-control-sm idstartDate value2026-01-01 span至/span input typedate classform-control form-control-sm idendDate value2026-01-31 button classbtn btn-sm btn-primary idfilterBtn筛选/button /div !-- 主题切换与刷新 -- div classd-flex gap-2 select classform-select form-select-sm idthemeSwitch option valuelight selected浅色主题/option option valuedark深色主题/option option valuecustom自定义主题/option /select button classbtn btn-sm btn-secondary idrefreshBtni classbi bi-arrow-clockwise/i 刷新/button button classbtn btn-sm btn-success idsaveConfigBtni classbi bi-save/i 保存配置/button /div /div /div每日订单量点击图表联动销售额点击数据项钻取详情!-- 图表2每日销售额折线图支持联动 -- div classcol-12 col-md-6 chart-item>第二步移动端响应式适配优化移动办公体验-- coding: utf-8 --mobile_adapt.py 移动端适配模块import jsonfrom flask import Blueprint, request, jsonify, render_templatefrom flask_login import login_required, current_userfrom models import UserDashboardPrefer, dbfrom audit_engine import audit_logfrom dotenv import load_dotenvimport os加载环境变量load_dotenv()mobile_bp Blueprint(“mobile”,name) 核心功能判断终端类型 def get_terminal_type():“”判断终端类型pc/mobile/pad:return: 终端类型字符串“”user_agent request.headers.get(“User-Agent”, “”).lower()# 判断移动端手机if any(keyword in user_agent for keyword in [“mobile”, “android”, “iphone”, “ios”]):return “mobile”# 判断平板elif any(keyword in user_agent for keyword in [“ipad”, “tablet”]):return “pad”# 默认PC端else:return “pc” 核心功能移动端数据压缩提升加载速度 def compress_mobile_data(data):“”移动端数据压缩简化图表数据、减少字段提升加载速度:param data: 原始数据:return: 压缩后的数据“”if not isinstance(data, dict):return data# 简化图表数据保留核心字段减少数据点 if chart_config in data and charts in data[chart_config]: for chart in data[chart_config][charts]: if echarts_config in chart and series in chart[echarts_config]: for series in chart[echarts_config][series]: # 数据点数量减半移动端无需过多细节 if isinstance(series[data], list) and len(series[data]) 10: series[data] series[data][::2] # 每隔一个取一个数据点 # 移除不必要的样式配置 if itemStyle in series: series[itemStyle] {color: series[itemStyle].get(color, #165DFF)} if lineStyle in series: series[lineStyle] {width: series[lineStyle].get(width, 2)} # 简化筛选配置移动端只保留常用筛选项 if filter_config in data: filter_config data[filter_config] if optional_filters in filter_config: # 保留前3个常用筛选项 filter_config[optional_filters] filter_config[optional_filters][:3] return data 接口移动端看板页面