别再做静态大屏了!掌握这三招交互魔法,惊艳老板的眼球
一、写在前面:告别“吃灰数据”,让你的大屏“活”起来!
经过前两个实验的爆肝,咱们已经成功拿下了“浏览器市场分析大屏”的静态排版与数据打通,也搞定了“用户画像大屏”的多维绑定及筛选联动。但说句实在话,一块真正具备商业杀伤力的数据大屏,光有“颜值”是远远不够的,核心还得看“交互”——得让用户点一点、切一切,就能像剥洋葱一样挖出数据背后的业务洞察。
本次实操,我们将直接杀入 Max 蓝图编辑器的高阶玩法,手把手带你实现三大神级功能:
👉 Tab 无感切换:巧用图层显隐魔法,在同一个文件里搞定“市场分析”和“用户画像”两大视图的丝滑横跳。
👉 地理下钻联动:点哪查哪!点击地图上的任意省份,右侧的核心指标面板瞬间刷新为该省的专属数据。
👉 动态热力渲染:让地图拥有数据“感知力”,根据受众规模自动分配颜色深浅,受众分布一目了然。
敲黑板! 这波操作完全不需要你手撸复杂的后端 API,也不用写让人头秃的前端监听事件。全程只需在蓝图编辑器里像搭乐高一样拖拽节点、盘盘逻辑,企业级的高级交互大屏就能轻松拿捏。
二、今日核心目标与技能树点亮指南
2.1 我们要掌握哪些硬核本领?
|
能力雷达 |
具体技能点拆解 |
|---|---|
|
图层管理 |
玩转图层可见性控制,实现多屏内容的无缝切换 |
|
导航交互 |
驾驭 Tab 列表组件,精准控制页面模块的显隐状态 |
|
地理下钻 |
挖掘地图组件交互事件,搞定省份点击的数据联动 |
|
数据联动 |
打通神经末梢,让指标卡跟随地图点击动态刷新 |
|
热力渲染 |
吃透 adcode 映射原理,赋予地图热力层动态着色的能力 |
2.2 我们的“工作台”配置
-
实验基地:助睿在线实验平台
-
生产力工具:助睿 Max(一站式可视化开发利器)
-
弹药库(数据源):团队私有数据库(MySQL)
-
前置通关要求:完成实验6-1(静态排版)、实验6-2(数据注入)
2.3 最终火力展示 (效果预览)
跟着本篇教程走完,你的大屏将进化出以下超能力:
-
✅ 顶部 Tab 导航一键切换“市场分析”与“用户画像”双线战场
-
✅ 地图彻底激活,根据各省份的浏览器用户基数自动生成热力涂层
-
✅ 点击任意省份,右侧四大核心指标卡秒级响应,实时展示地方战报
-
✅ 切换浏览器筛选器时,全图热力层同步洗牌更新
三、上帝视角:全局交互架构拆解
3.1 系统交互全景图

3.2 两大核心交互链路

链路一:大屏切换交互(图层可见性控制)
Tab列表组件
│
├── 点击"市场分析" (id=1) ──→ 分支判断(id==1)为真
│ ├── 设置图层:市场分析组 → 显示
│ └── 设置图层:用户画像组 → 隐藏
│
└── 点击"用户画像" (id=2) ──→ 分支判断(id==1)为假
├── 设置图层:市场分析组 → 隐藏
└── 设置图层:用户画像组 → 显示
链路二:地图省份点击联动(地理下钻)
基础平面地图(区域热力层)
│
├── 点击区域时事件 ──→ 提取地区名称(并行数据处理)
│ │
│ ├── 省份全称 → 简称映射
│ └── 存入全局变量 window.globalProvinceName
│ │
│ └──→ 省份核心指标查询(SQL请求)
│ │
│ ├── 读取 window.globalProvinceName
│ ├── 读取 window.GLOBAL_SELECTED_BROWSER
│ └── 执行动态SQL
│ │
│ └──→ 省份核心指标分发(并行数据处理)
│ │
│ ├── 分支1:总用户数 → 指标卡1
│ ├── 分支2:平均年龄 → 指标卡2
│ ├── 分支3:本科占比 → 指标卡3
│ └── 分支4:中高收入占比 → 指标卡4
│
└── 热力渲染链路(独立)
│
├── 地理边界geojson加载完成 ──→ 提取adcode映射表
│ │
│ └── 存入 window.globalProvinceAdcode
│ │
└── 浏览器切换/页面加载 ──→ 各省份用户数查询(SQL)
│
└──→ 地图数据与用户数映射
│
└──→ 导入热力值数据接口
四、硬核揭秘:核心技术底层逻辑
4.1 图层显隐魔法:单文件搞定多屏切换
业务痛点:在真实的打工人日常中,一个数据复盘项目绝对不止一个页面(往往要兼顾市场动态、用户画像、运营大盘等)。如果傻乎乎地给每个视角都建一个独立的大屏文件,你将面临:
-
修改噩梦:换个皮肤或者改个数据源,得挨个文件改到自闭。
-
体验拉胯:跨页面跳转那刺眼的白屏,老板看了直摇头。
-
状态割裂:好不容易选好的筛选条件,跳个页面全重置了。
Max 满分答案:图层组打包 + 可见性动态控制,一个文件 Hold 住全场。
技术原理解析:
-
把“市场分析”所有的零件打包成一个 Folder(比如命名为“市场分析组”)。
-
把“用户画像”所有的零件也打包成另一个 Folder(“用户画像组”)。
-
拦截 Tab 列表组件的点击事件,写点简单的判断逻辑,让这两个大组此消彼长地“显示/隐藏”。
方案降维打击对比:
|
方案 |
维护文件数 |
用户切换体验 |
全局状态共享 |
后期维护成本 |
|---|---|---|---|---|
|
传统多页面 |
2个起步 |
极差(闪烁重载) |
不支持 |
极高 |
|
图层切换法(本文) |
1个 |
极致(秒切无感) |
原生支持 |
极低 |
4.2 拿捏地图交互事件体系
Max 中的“基础平面地图”组件可以说是天生自带交互 Buff,核心事件一览:
|
事件触发器 |
触发时机 |
吐出的核心数据 |
|---|---|---|
|
当数据接口地理边界geojson数据加载完成时 |
地图骨架 (GeoJSON) 渲染完毕 |
包含各地理边界的 GeoJSON 对象 |
|
点击区域时 |
鼠标左键点击任意省份地块 |
包含所点击区域的 |
|
鼠标移入区域触发 |
鼠标悬停在某省份上方 |
|
|
鼠标移出区域触发 |
鼠标离开某省份 |
|
我们这次要榨干的两个核心事件:
-
点击区域时:当导火索,触发下钻逻辑,刷新指标卡数据。
-
当地理边界加载完成时:做战前准备,提前把所有省份的 adcode 映射表拿出来,为后面的热力图渲染铺路。
4.3 省份名称大清洗:全称与简称的完美 Match
踩坑预警:地图组件丢给你的名字是带着后缀的完整官方称呼(如“江苏省”、“广西壮族自治区”),但这往往跟我们数据库里存的干净简称(如“江苏”、“广西”)是对不上的。直接拿去查 SQL?妥妥的查无此人。
解决方案:写个中间件清洗数据,建立一套全称到简称的双向映射机制。
// 核心城市的特殊待遇名单(直辖市、特别行政区、各大自治区)
const specialMap = {
'北京市': '北京', '天津市': '天津', '上海市': '上海', '重庆市': '重庆',
'广西壮族自治区': '广西', '内蒙古自治区': '内蒙古',
'西藏自治区': '西藏', '宁夏回族自治区': '宁夏',
'新疆维吾尔自治区': '新疆',
'香港特别行政区': '香港', '澳门特别行政区': '澳门'
};
暴力美学与优雅并存的处理规则:
-
遇到 VIP(特殊映射表):直接 VIP 通道查表替换。
-
遇到普通省份:上正则,强行扒掉词尾的“省”、“自治区”、“市”等外套。
-
最终输出:数据库能无缝识别的极简省份名。
4.4 搞懂行政区划代码(adcode)映射
灵魂发问:adcode 是啥? 简单来说,它就是国家统计局给每个地块发的“身份证号”。Max 的地图组件必须靠这个身份证号,才知道要把颜色涂在哪个区域里。
为什么必须搞映射? 因为热力图层的数据接口非常“挑食”,它只认这种格式:
{
"name": "江苏",
"value": 1500,
"area_id": 320000
}
这里的 area_id 其实就是 adcode!所以我们得把业务里的“省份名”翻译成“adcode”。
去哪找数据? 根本不用自己找,地图内置的 GeoJSON 里就已经藏好这份花名册了,趁它刚加载完,我们直接拦截提取就行。
五、保姆级实操:跟着步骤闭眼入
5.1 Step 1:打通大屏 Tab 导航奇脉
5.1.1 核心脑洞
Tab 列表其实是个高度可定制的 UI 组件。这里的骚操作是“隐身术”——把 Tab 列表的底色、高亮色、悬浮色统统调成 100% 透明,然后把它盖在咱们原本的顶部导航 UI 上。用户以为点的是导航按钮,其实点的是隐形的 Tab,这就是偷天换日!
5.1.2 搞定组件配置
(1)拉入 Tab 组件
-
去组件库把“Tab 列表”拖出来,稳稳丢到顶部导航栏的位置。

-
微调尺寸,让它跟底下的“市场分析”、“用户画像”两个文字按钮严丝合缝地贴脸重合。

(2)开启隐身模式(样式魔改)
-
点开 Tab 列表的基础设置:
-
改行数:
1行 -
改列数:
2列
-
-
找到“标签默认配置”,对下面三兄弟下狠手,透明度全部拉到
0:-
背景颜色 ➔
0% -
选中背景色 ➔
0% -
悬浮背景色 ➔
0%
-
-
现在,Tab 已经变身透明结界,虽然看不见,但随时准备拦截用户的点击。
(3)喂入干净数据 切到数据面板,精简成两条清爽的数据:
[
{ "id": 1, "content": "" },
{ "id": 2, "content": "" }
]
-
id:作为接下来路由分发的暗号。 -
content:留空即可(毕竟字长在底图上)。
弄完记得随手点一下刷新数据接口。
5.1.3 蓝图逻辑编排
(1)把演员请上蓝图画布 将以下组件从图层树里拖拽到蓝图编辑器:
-
“市场分析”图层组
-
“用户画像”图层组
-
刚才做的“隐形 Tab 列表”

(2)加入大脑(分支判断) 拖入一个“分支判断”节点,在代码区写下这句灵魂判词:
return data.id == 1;
逻辑极简:
-
点左边按钮(市场分析) ➔ 输出 1 ➔
true➔ 走满足分支。 -
点右边按钮(用户画像) ➔ 输出 2 ➔
false➔ 走不满足分支。
(3)接线:满足分支(亮出市场大屏) 在为 true 的出口,连上两个“设置图层可见性”节点:
-
市场分析组 ➔ 动作切到:
显示 -
用户画像组 ➔ 动作切到:
隐藏
(4)接线:不满足分支(亮出用户大屏) 在为 false 的出口,同样配两个动作:
-
市场分析组 ➔ 动作切到:
隐藏 -
用户画像组 ➔ 动作切到:
显示
(5)节点大串联

5.1.4 自查 checklist
-
狂点“市场分析”,检查是不是这半边活了,另一半藏起来了
-
狂点“用户画像”,检查是不是反过来了
-
左右横跳,感受一下没有任何刷新白屏的丝滑感
5.2 Step 2:触发地图点击,召唤数据下钻
5.2.1 整体套路
用户猛击地图 ➔ 截获省份名 ➔ 去数据库捞这片地的数据 ➔ 拆分给四个指标卡。这就是经典的地理下钻分析 (Geo-drilldown) 套路。
5.2.2 核心节点配置与代码
(1)洗数据:提取地区名称(并行处理节点)
-
目的:接住点击事件吐出的名字,过一遍清洗机,变成标准简称并存入全局变量。
-
怎么做:拖一个“并行数据处理”节点,改名“提取地区名称”,贴入代码:

// 特权省市VIP通道
const specialMap = {
'北京市': '北京',
'天津市': '天津',
'上海市': '上海',
'重庆市': '重庆',
'广西壮族自治区': '广西',
'内蒙古自治区': '内蒙古',
'西藏自治区': '西藏',
'宁夏回族自治区': '宁夏',
'新疆维吾尔自治区': '新疆',
'香港特别行政区': '香港',
'澳门特别行政区': '澳门'
};
let provinceName = data.name;
// 优先VIP通道走一波
if (specialMap[provinceName]) {
provinceName = specialMap[provinceName];
} else {
// 没走通的,直接暴力脱掉后缀外套
provinceName = provinceName.replace(/(省|自治区|市)$/, '');
}
// 注入全局,方便全场调用
window.globalProvinceName = provinceName;
return provinceName;
(2)向数据库开炮:查询核心指标(SQL 请求节点)
-
目的:带上选中的省份和当前的浏览器参数,去库里拿四大指标。
-
怎么做:加个“SQL请求”节点,改名“省份核心指标查询”,贴入代码:

const selectedProvince = window.globalProvinceName;
console.log("拦截到的点击省份:", selectedProvince);
const selectedBrowser = window.GLOBAL_SELECTED_BROWSER;
const sql = `
-- 战报1:地盘总人数
select 'total_users' as name, sum(user_count) as value
from labs.user_profile_stats
where browser_name = '${selectedBrowser}'
and province = '${selectedProvince}'
union all
-- 战报2:用户年龄盘点(加权平均)
select 'avg_age' as name,
round(sum(age * user_count) / sum(user_count), 0) as value
from labs.user_profile_stats
where browser_name = '${selectedBrowser}'
and province = '${selectedProvince}'
union all
-- 战报3:高学历人群浓度
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 labs.user_profile_stats
where browser_name = '${selectedBrowser}'
and province = '${selectedProvince}'
union all
-- 战报4:高氪金玩家占比(中高收入)
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 labs.user_profile_stats
where browser_name = '${selectedBrowser}'
and province = '${selectedProvince}'
`;
console.log("拼好的查库SQL:", sql);
return sql;
高能解析:为什么用
UNION ALL一把梭?因为四项指标长得一样(都是 name 和 value),一次性打捆发给数据库,大大降低请求延迟,贼快。
(3)精准发牌:数据分发(并行处理节点)
-
目的:SQL 吐出来的是个四行数组,我们需要拆开塞给四个不同的指标卡。
-
怎么做:搞四个“并行数据处理”节点,作为分发器。

发给“总用户数”:
var item = data.find(item => item.name === 'total_users');
return [{ value: item ? item.value : 0 }];
发给“平均年龄”:
var item = data.find(item => item.name === 'avg_age');
return [{ value: item ? item.value : 0 }];
发给“高学历占比”:
var item = data.find(item => item.name === 'high_edu_ratio');
return [{ value: item ? item.value : 0 }];
发给“中高收入占比”:
var item = data.find(item => item.name === 'high_income_ratio');
return [{ value: item ? item.value : 0 }];
5.2.3 蓝图连线

5.2.4 自查 checklist
-
猛击江苏板块,看指标卡是不是切成了散装江苏的数据
-
再点广东大本营,数据必须立刻刷新
-
核对一下数据,确保和顶部的浏览器筛选器是联动的
-
换个浏览器,重新点省份,数据有变化即算通关
5.3 Step 3:点亮全国地图热力层
5.3.1 怎么玩转热力图?
想让地图“按人头涂颜色”,分三步走:
-
偷出名册表:等地图骨架刚加载完,赶紧把所有省份的 adcode 字典存下来。
-
盘点各地兵力:根据筛选器,用 SQL 查出全国每个省到底有多少人。
-
两表一碰:把查出来的省份去匹配 adcode 字典,输出热力图引擎能吃的标准 JSON。
5.3.2 核心节点实操
(1)偷名册:提取 adcode(并行处理节点)
-
触发机制:一定要连在区域热力层的“当数据接口地理边界geojson数据加载完成时”后面。
-
怎么做:加个节点叫“提取adcode映射表”,代码如下:

/**
* 从骨架里扒出 adcode 映射表
*/
function extractAdcodeAndName(data) {
if (!data || !Array.isArray(data.features)) {
console.error('地图数据格式不熟!');
return {};
}
const nameToAdcode = {};
// 遍历每一个地块,建立档案
data.features.forEach(feature => {
const props = feature.properties;
if (props && props.adcode && props.name) {
nameToAdcode[props.name] = props.adcode;
}
});
return nameToAdcode;
}
const mapping = extractAdcodeAndName(data);
// 放进全局保险箱,等会儿渲染要用
window.globalProvinceAdcode = mapping;
console.log("全国adcode字典加载完毕,总计:", Object.keys(mapping).length);
return mapping;
(2)盘兵力:查询全盘数据(SQL请求节点)
-
目的:一把抓出当前浏览器在全国各省的势力分布。
-
怎么做:加节点“各省份用户数查询”:

const selectedBrowser = window.GLOBAL_SELECTED_BROWSER;
const sql = `
SELECT
province AS name,
SUM(user_count) AS value
FROM labs.user_profile_stats
WHERE browser_name = '${selectedBrowser}'
AND province IS NOT NULL
AND province != ''
GROUP BY province
ORDER BY value DESC
`;
console.log("热力图群嘲SQL生成:", sql);
return sql;
(3)数据缝合:映射与格式化(并行处理节点)
-
目的:把刚才查出的数据,跟第一步存的 adcode 字典缝合。
-
怎么做:加节点“地图数据与用户数映射”:

function convertToMapData(data) {
if (!Array.isArray(data) || data.length === 0) {
return [];
}
return data.map(item => {
const provinceName = item.name;
// Plan A:精准打击(直接匹配)
let area_id = window.globalProvinceAdcode[provinceName];
// Plan B:模糊搜索(剔除少数民族自治等长串后缀)
if (!area_id) {
const simplifiedName = provinceName.replace(
/省|市|自治区|特别行政区|回族|壮族|维吾尔|藏族|苗族/g,
''
);
for (const fullName in window.globalProvinceAdcode) {
if (fullName.includes(simplifiedName)) {
area_id = window.globalProvinceAdcode[fullName];
break;
}
}
}
// Plan C:兜底策略(找不到就发配到公海)
if (!area_id) {
area_id = "000000";
}
return {
name: provinceName,
value: parseFloat(item.value) || 0,
area_id: Number(area_id) // 这个就是大屏引擎认的身份证
};
});
}
const result = convertToMapData(data);
return result;
5.3.3 蓝图连线(热力渲染链路)


5.3.4 自查 checklist
-
一刷新,祖国山河是不是已经五颜六色了?
-
用户大省(北上广深浙)颜色是不是最深的?
-
动一下浏览器筛选项,颜色分布是不是跟着跳舞了?
-
就算有个别省没数据,也没有报红死机,而是优雅地灰掉。
5.4 Step 4:最终蓝图大一统
这几招练完,你的蓝图画布上应该躺着这三条优美的神经链路:
5.4.1 大屏切换链路

5.4.2 省份点击下钻链路

5.4.3 热力渲染链路

六、进阶课堂:关键技术的千层套路
6.1 玩转全局变量
咱们这次疯狂使用了 window 全局变量来做数据跨节点的搬运工:
|
变量大名 |
存了啥宝贝 |
谁写的 |
谁在用 |
|---|---|---|---|
|
|
当前激活的浏览器 |
下拉框触发器 |
各大数据库查表节点 |
|
|
刚才点击的省份 |
地图点击洗数据节点 |
省份专属 SQL 查询节点 |
|
|
adcode 通讯录 |
地理边界加载节点 |
热力图数据组装节点 |
老司机忠告:
-
✅ 一定要加上
GLOBAL_这类的前缀,避免和原生变量打架。 -
✅ 生命周期要门清:谁负责初始化,谁负责覆写,理得越清 bug 越少。
6.2 分支节点的高端玩法
我们在切换大屏时用的是最朴素的 return data.id == 1;,其实它还能这么玩:
-
数值卡点:
return data.value > 10000;(大户自动触发特殊动效) -
复合连招:
return data.id == 1 && data.role == 'admin';(多条件组合) -
正则过滤:
return data.name.includes('大区');(模糊匹配分流)
6.3 揭秘热力图底层引擎
-
你以为的热力图:很复杂。
-
Max 的底层热力图:一套管道全自动处理。 数据喂进去 ➔ 匹配地块 ➔ 平台内置引擎自动算出数据最大最小值,分发深浅色阶 ➔ Canvas/SVG 原生渲染。完全不用你自己算 RGB,美滋滋。
七、避坑指南:高频报错与自救攻略
Q1:切大屏时,为啥画面重影了?
救火办法:你肯定没把那两个大组独立打包好,或者在“分支判断”后面,两根线的“显示/隐藏”动作写顺手写成一样的了。仔细核对动作配置!
Q2:疯狂点省份,指标卡就是装死?
救火办法:
第一步,在“提取名称”节点加上
console.log(data),看看点击事件到底有没有触发。第二步,查
window.globalProvinceName是不是undefined。第三步,把拼好的 SQL 复制到数据库直接跑一下,八成是字符串单引号拼漏了!
Q3:全国地图一片灰,完全不上色?
救火办法:
八成是 adcode 字典没装好。按 F12 看看“提取adcode”节点报没报错。
检查最后拼出来的数据结构,一定要确认
area_id字段塞的是数字 (Number)!如果你传了个字符串过去,地图引擎会直接摆烂的。
Q4:内蒙古、新疆这种名字死活匹配不上?
救火办法:正则大法也不是万能的。老老实实在代码开头的
specialMap字典里给他们加个硬性 VIP 通道。
Q5:动了顶部筛选器,热力图不动?
救火办法:查你的蓝图触发源!确保“浏览器筛选器”的节点有一根线连到了“各省份用户数查询”节点上,没线连它怎么知道该刷新了?
八、干货总结与高阶玩法脑暴
8.1 今天咱们赚到了什么?
一套打通任督二脉的完整企业级交互闭环:
-
图层可见性流派 ➔ 零代码实现单体巨石应用的无感切换。
-
事件驱动流派 ➔ 点击捕获 + SQL 变量注入,实现了真正的“探索式”洞察。
-
数据驱动流派 ➔ 吃透 adcode,搞懂前端渲染与数据的绑定美学。
8.2 给你点新灵感 (课后拓展)
掌握了这些,你完全可以自己去魔改:
-
🚀 时空穿梭:加个时间轴组件,连上 SQL 的日期变量,做一个数据按月份随时间变幻的动态热力推演。
-
🚀 套娃式下钻:配上城市级的 GeoJSON,点击省份后直接下钻到地级市。
-
🚀 立体打击:点击地图,不但右边指标卡变,把底下的饼图、折线图全部联动刷新,全屏共鸣。
8.3 想让系统飞起来?(性能优化)
如果你数据量极大,建议给 browser_name 和 province 这俩字段加个数据库联合索引,速度能飙升 60%。或者把首屏用不到的图层做个懒加载,体验直接拉满。
8.4 大功告成,赶紧发朋友圈
点击右上角“发布”,打开分享开关,把生成的链接甩到群里,尽情享受大佬的注视吧!


九、CV工程师福利:完整代码速查表
9.1 省份名称清洗插件
const specialMap = {
'北京市': '北京', '天津市': '天津', '上海市': '上海', '重庆市': '重庆',
'广西壮族自治区': '广西', '内蒙古自治区': '内蒙古', '西藏自治区': '西藏',
'宁夏回族自治区': '宁夏', '新疆维吾尔自治区': '新疆',
'香港特别行政区': '香港', '澳门特别行政区': '澳门'
};
let provinceName = data.name;
if (specialMap[provinceName]) {
provinceName = specialMap[provinceName];
} else {
provinceName = provinceName.replace(/(省|自治区|市)$/, '');
}
window.globalProvinceName = provinceName;
return provinceName;
9.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 labs.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 labs.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 labs.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 labs.user_profile_stats
where browser_name = '${selectedBrowser}' and province = '${selectedProvince}'
`;
return sql;
9.3 潜行偷取 adcode
function extractAdcodeAndName(data) {
if (!data || !Array.isArray(data.features)) {
console.error('无效的地图数据格式');
return {};
}
const nameToAdcode = {};
data.features.forEach(feature => {
const props = feature.properties;
if (props && props.adcode && props.name) {
nameToAdcode[props.name] = props.adcode;
}
});
return nameToAdcode;
}
const mapping = extractAdcodeAndName(data);
window.globalProvinceAdcode = mapping;
return mapping;
9.4 热力图数据终极缝合
function convertToMapData(data) {
if (!Array.isArray(data) || data.length === 0) return [];
return data.map(item => {
const provinceName = item.name;
let area_id = window.globalProvinceAdcode[provinceName];
if (!area_id) {
const simplifiedName = provinceName.replace(/省|市|自治区|特别行政区|回族|壮族|维吾尔|藏族|苗族/g, '');
for (const fullName in window.globalProvinceAdcode) {
if (fullName.includes(simplifiedName)) {
area_id = window.globalProvinceAdcode[fullName];
break;
}
}
}
if (!area_id) area_id = "000000";
return {
name: provinceName,
value: parseFloat(item.value) || 0,
area_id: Number(area_id)
};
});
}
return convertToMapData(data);
更多推荐

所有评论(0)