本文为 Uniplore 「浏览器用户画像分析」实验系列全流程指南,覆盖静态布局制作、数据接入、交互联动三大核心模块,包含可直接复用的 SQL、蓝图节点代码与避坑技巧,新手也能零代码复刻企业级数据大屏。

 

一、实验背景与目标

本系列实验基于user_profile_stats用户画像统计表,完成从大屏静态设计到动态交互的全链路开发,最终实现三大核心能力:

  1. 零代码搭建浏览器用户画像分析大屏的完整布局
  2. 通过蓝图编辑器实现筛选器与全图表的联动数据刷新
  3. 配置大屏切换、地图下钻交互,完成企业级数据可视化开发

适用场景:数据分析教学实验、企业用户画像看板、数据可视化学习练手

以下为本次实验所使用平台的基础信息:

  • 平台全称:助睿数智(Uniplore)一站式数据科学实验平台
  • 平台定位:覆盖数据接入、ETL 处理、机器学习建模到可视化分析的全链路 Agentic 零代码数据智能平台

 

二、实验 1:大屏静态布局制作(组件搭建)

(一)核心设计框架

先明确大屏的业务叙事逻辑,再按模块拆分组件,避免盲目拖拽布局:

模块

子模块

推荐组件

核心作用

数据概览

核心指标(用户数 / 平均年龄 / 本科占比 / 中高收入占比)

数字翻牌器

一眼传递用户规模与质量

地域分布

省份热力地图 + TOP5 排行榜

基础平面地图 + 轮播列表

展示用户地理分布与热点区域

人口属性

性别 / 居住地类型

基础饼图 / 轮播饼图

展示用户结构占比

人口属性

年龄 / 职业 / 收入分布

基础柱状图 / 水平柱状图

对比不同类别的用户数量

人口属性

学历分布

水平基础柱图

适配长类别名称的对比展示

交互控件

浏览器筛选器

下拉多选组件

实现多浏览器数据切换

 

 

 

 

 

(二)快速搭建步骤(避坑版)

步骤 1:图层分组与复用

将上一实验的「市场分析大屏」组件整体复制、重命名为市场分析组并隐藏,新建用户画像组用于本次实验,两个大屏可通过图层可见性切换,避免组件重叠干扰。

 

 

 

步骤 2:组件与背景配置(附素材)

按参考图依次添加组件,统一设置背景样式,推荐素材链接如下:

素材

 

页面背景

 

图表区域背景

 

指标标题背景

 

排行榜背景

 

步骤 3:关键组件设置技巧

  • 基础平面地图:添加「区域热力层」子组件,开启省份边界高亮,后续将通过数据动态渲染热力颜色

 

  • 轮播列表(TOP5 省份):设置交替行背景色、行高与字体样式,提升可读性

 

 

  • 饼图组件:性别分布用基础饼图,居住地类型用轮播饼图,增强大屏动态效果

 

 

 

  • 下拉多选筛选器:设置 6 个浏览器选项,默认选中第一个浏览器,开启可清空 / 全选功能

 

 

 

 

三、实验 2:数据接入与筛选器联动(蓝图配置)

(一)核心数据流逻辑

页面加载 / 筛选器选择 → 触发参数接收 → 维度数据 SQL + 核心指标 SQL 并行查询 → 数据分发到各图表组件,实现一次查询、全图表联动刷新。

(二)前置准备:表结构优化

为准确计算平均年龄,先修改user_profile_stats表结构,添加age字段:

DROP TABLE IF EXISTS `user_profile_stats`;
CREATE TABLE `user_profile_stats` (
    `browser_name` VARCHAR(50) NOT NULL COMMENT '浏览器名称',
    `gender` VARCHAR(10) COMMENT '性别',
    `age` INT NOT NULL COMMENT '年龄',
    `age_group` VARCHAR(10) COMMENT '年龄段',
    `edu` VARCHAR(50) COMMENT '学历',
    `job` VARCHAR(50) COMMENT '职业',
    `income` VARCHAR(50) COMMENT '收入',
    `city_type` VARCHAR(10) COMMENT '居住地类型',
    `province` VARCHAR(50) COMMENT '省份',
    `user_count` INT NOT NULL COMMENT '用户数'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户画像统计表';

修改「用户画像表加工」转换流,在分组组件中保留age字段并重新执行。

 

 

 

(三)蓝图节点配置(完整代码)

节点 1:浏览器参数接收(并行数据处理)

接收筛选器选中的浏览器,存入全局变量,供后续 SQL 调用:

 

节点 2:维度数据 SQL 请求(一次查询全维度数据)

UNION ALL合并所有人口属性维度数据,统一输出格式:

const selectedBrowser = window.GLOBAL_SELECTED_BROWSER;
let sql = `
-- 性别分布
select 'gender' as dimension_type, gender as name, sum(user_count) as value
from cs_group_8.user_profile_stats where browser_name = '${selectedBrowser}' group by gender
union all
-- 年龄段分布
select 'age' as dimension_type, age_group as name, sum(user_count) as value
from cs_group_8.user_profile_stats where browser_name = '${selectedBrowser}' group by age_group
union all
-- 学历分布
select 'edu' as dimension_type, edu as name, sum(user_count) as value
from cs_group_8.user_profile_stats where browser_name = '${selectedBrowser}' group by edu
union all
-- 职业分布
select 'job' as dimension_type, job as name, sum(user_count) as value
from cs_group_8.user_profile_stats where browser_name = '${selectedBrowser}' group by job
union all
-- 收入分布
select 'income' as dimension_type, income as name, sum(user_count) as value
from cs_group_8.user_profile_stats where browser_name = '${selectedBrowser}' group by income
union all
-- 居住地类型分布
select 'city_type' as dimension_type, city_type as name, sum(user_count) as value
from cs_group_8.user_profile_stats where browser_name = '${selectedBrowser}' group by city_type
union all
-- 省份分布
select 'province' as dimension_type, province as name, sum(user_count) as value
from cs_group_8.user_profile_stats where browser_name = '${selectedBrowser}' group by province
`;
return sql;

 

 

节点 3:维度数据分发(并行数据处理)

dimension_type过滤数据,分发给对应图表组件,以下为关键分支代码:

// 分支1:性别分布(饼图)
var filtered = data.filter(item => item.dimension_type === 'gender');
return filtered.map(item => ({ name: item.name, value: item.value }));

// 分支2:年龄段分布(柱状图,按顺序排序)
var filtered = data.filter(item => item.dimension_type === 'age');
var order = ['<18', '18-25', '26-35', '36-45', '>45'];
filtered.sort((a, b) => order.indexOf(a.name) - order.indexOf(b.name));
return filtered.map(item => ({ x: item.name, y: item.value, s: '用户数' }));

// 分支3:学历分布(条形图)
var filtered = data.filter(item => item.dimension_type === 'edu');
var order = ['小学及以下', '初中', '高中/中专/技校', '大专', '大学本科', '硕士及以上'];
filtered.sort((a, b) => order.indexOf(a.name) - order.indexOf(b.name));
return filtered.map(item => ({
    x: item.name,
    y: item.value,
    s: '学历'}));

// 分支4:职业分布(柱状图)
var filtered = data.filter(item => item.dimension_type === 'job');
return filtered.map(item => ({
    x: item.name,
    y: item.value,
    s: '职业'}));

// 分支5:收入分布(柱状图)
var filtered = data.filter(item => item.dimension_type === 'income');

// 按收入金额升序排序(提取数字进行比较)
filtered.sort((a, b) => {
    // 提取收入段中的最小金额
    var getMinIncome = (incomeStr) => {
        // 处理 "无收入"、"500元及以下" 等特殊情况
        if (incomeStr === '无收入') return -1;
        if (incomeStr === '500元及以下') return 0;
        // 提取数字,如 "1501~2000元" 提取 1501
        var match = incomeStr.match(/(\d+)/);
        return match ? parseInt(match[1]) : 999999;};
    return getMinIncome(a.name) - getMinIncome(b.name);});
return filtered.map(item => ({
    x: item.name,
    y: item.value,
    s: '收入'}));

// 分支6:居住地类型分布(饼图)
var filtered = data.filter(item => item.dimension_type === 'city_type');
return filtered.map(item => ({
    name: item.name === 'unknown' ? '未知' : item.name,
    value: item.value}));

// 分支7:省份TOP5排行榜(轮播列表)
var filtered = data.filter(item => item.dimension_type === 'province');
filtered.sort((a, b) => b.value - a.value);
var top5 = filtered.slice(0, 5);
return top5.map(item => ({ province: item.name, user_count: item.value }));

 

 

 

节点 4:核心指标 SQL 请求与分发

查询四个核心指标并拆分分发到对应指标卡:

// SQL请求节点代码
const selectedBrowser = window.GLOBAL_SELECTED_BROWSER;
let sql = `
select 'total_users' as name, sum(user_count) as value
from cs_group_8.user_profile_stats where browser_name = '${selectedBrowser}'
union all
select 'avg_age' as name, round(sum(age * user_count) / sum(user_count), 1) as value
from cs_group_8.user_profile_stats where browser_name = '${selectedBrowser}'
union all
select 'high_edu_ratio' as name, round(sum(case when edu in ('本科', '硕士及以上') then user_count else 0 end) * 100.0 / sum(user_count), 1) as value
from cs_group_8.user_profile_stats where browser_name = '${selectedBrowser}'
union all
select 'high_income_ratio' as name, round(sum(case when income in ('5001~8000元', '8001~12000元','12000元以上') then user_count else 0 end) * 100.0 / sum(user_count), 1) as value
from cs_group_8.user_profile_stats where browser_name = '${selectedBrowser}'
`;
return sql;

// 分发节点分支示例(总用户数)
var item = data.find(item => item.name === 'total_users');

 

 

 

 

 

 

 

四、实验 3:大屏交互配置(切换 + 地图下钻)

(一)大屏切换功能实现

通过 Tab 列表组件控制两个大屏的图层可见性,实现无刷新切换:

  1. 添加 Tab 列表组件,设置 1 行 2 列,id分别为 1(市场分析)和 2(用户画像),背景透明度设为 0,与导航按钮重合
  2. 导出 Tab 列表、两个图层组到蓝图编辑器,添加分支判断节点:return data.id == 1;
  3. 满足分支:显示「市场分析组」,隐藏「用户画像组」;不满足分支则相反

 

(二)地图省份点击联动(核心交互)

点击地图省份时,右侧核心指标卡自动刷新为该省份数据,实现地理下钻分析:

步骤 1:省份名称映射(并行数据处理)

处理地图返回的全称与数据表简称的匹配问题:

const specialMap = {
    '北京市': '北京', '天津市': '天津', '上海市': '上海', '重庆市': '重庆',
    '广西壮族自治区': '广西', '内蒙古自治区': '内蒙古', '西藏自治区': '西藏',
    '宁夏回族自治区': '宁夏', '新疆维吾尔自治区': '新疆',
    '香港特别行政区': '香港', '澳门特别行政区': '澳门'
};
let provinceName = data.name;
if (specialMap[provinceName]) {
    provinceName = specialMap[provinceName];
} else {
    provinceName = provinceName.replace(/(省|自治区|市)$/, '');
}
window.globalProvinceName = provinceName;
return provinceName;

 

 

步骤 2:省份核心指标 SQL 查询

根据选中的浏览器和省份,查询该省份的核心指标:

const selectedProvince = window.globalProvinceName;
const selectedBrowser = window.GLOBAL_SELECTED_BROWSER;
const sql = `
select 'total_users' as name, sum(user_count) as value
from cs_group_8.user_profile_stats where browser_name = '${selectedBrowser}' and province = '${selectedProvince}'
union all
select 'avg_age' as name, round(sum(age * user_count) / sum(user_count), 0) as value
from cs_group_8.user_profile_stats where browser_name = '${selectedBrowser}' and province = '${selectedProvince}'
union all
select 'high_edu_ratio' as name, round(sum(case when edu in ('本科', '硕士及以上') then user_count else 0 end) * 100.0 / sum(user_count), 2) as value
from cs_group_8.user_profile_stats where browser_name = '${selectedBrowser}' and province = '${selectedProvince}'
union all
select 'high_income_ratio' as name, round(sum(case when income in ('5001~8000元', '8001~12000元','12000元以上') then user_count else 0 end) * 100.0 / sum(user_count), 2) as value
from cs_group_8.user_profile_stats where browser_name = '${selectedBrowser}' and province = '${selectedProvince}'
`;
return sql;

步骤 3:地图热力层动态渲染

根据用户数自动调整省份颜色深浅,实现热力效果:

  • 添加「提取 adcode 映射表」节点,从地图 GeoJSON 数据中提取省份与 adcode 的映射关系

  • 配置「各省份用户数查询」SQL 节点,统计当前浏览器下各省份用户数

 

 

  • 添加「地图数据映射」节点,将查询结果转换为热力层所需格式:
    function convertToMapData(data) {
      return data.map(item => {
        const provinceName = item.name;
        let area_id = globalProvinceAdcode[provinceName];
        if (!area_id) {
          const simplifiedName = provinceName.replace(/省|市|自治区/g, '');
          for (const fullName in globalProvinceAdcode) {
            if (fullName.includes(simplifiedName)) {
              area_id = globalProvinceAdcode[fullName];
              break;
            }
          }
        }
        return {
          name: provinceName,
          value: parseFloat(item.value) || 0,
          area_id: Number(area_id)
        };
      });
    }
    return convertToMapData(data);

     

  • 将映射结果导入「区域热力层」的「导入热力值数据接口」

 

五、常见问题与避坑指南

  1. 筛选器不联动:检查参数接收节点是否正确存入全局变量,SQL 语句中是否正确引用window.GLOBAL_SELECTED_BROWSER,节点连线是否为「执行成功」→「执行 SQL」
  2. 地图省份不匹配:优先检查省份名称映射代码,确保数据表中的省份简称与地图返回的全称能正确转换
  3. 热力层颜色不更新:确认 adcode 映射表已正确加载,SQL 查询结果包含所有省份,且数据映射节点输出格式为{name, value, area_id}
  4. 指标卡数据为 0:检查 SQL 查询是否按浏览器和省份过滤,核心指标分发节点是否按name字段正确过滤数据

 

六、实验总结

通过本系列实验,我们掌握了助睿 Max 数据大屏的完整开发流程:从静态组件布局、蓝图编辑器数据接入,到多场景交互配置,实现了浏览器用户画像分析大屏的从 0 到 1 搭建。这种低代码可视化开发方式,大幅降低了企业级数据大屏的开发门槛,适合数据分析、产品运营、前端开发等多场景使用。

#助睿数智 #Uniplore #数据大屏

 

 

 

Logo

一站式 AI 云服务平台

更多推荐