This commit is contained in:
yumoqing 2025-11-18 22:18:55 +08:00
parent 99f61ae8fe
commit 9e8ea7ba15
6 changed files with 340 additions and 1 deletions

View File

@ -11,7 +11,7 @@ SOURCES=" page_data_loader.js factory.js uitypesdef.js utils.js uitype.js \
llm.js websocket.js datarow.js tabular.js continueaudio.js \
line.js pie.js bar.js gobang.js period.js iconbarpage.js \
keypress.js asr.js webspeech.js countdown.js progressbar.js \
qaframe.js svg.js videoplayer.js "
qaframe.js svg.js videoplayer.js sctter.js radar.js kline.js heatmap.js map.js"
echo ${SOURCES}
cat ${SOURCES} > ../dist/bricks.js
# uglifyjs --compress --mangle -- ../dist/bricks.js > ../dist/bricks.min.js

73
bricks/heatmap.js Normal file
View File

@ -0,0 +1,73 @@
var bricks = window.bricks || {};
bricks.ChartHeatmap = class extends bricks.EchartsExt {
/*
数据格式:
[
{ x: '周一', y: '上午', value: 120 },
{ x: '周二', y: '下午', value: 90 }, ...
]
参数:
{
data_url,
xField: 'x', // X 轴字段
yField: 'y', // Y 轴字段
valueField: 'value'
}
*/
setup_options(data) {
const xField = this.xField || 'x';
const yField = this.yField || 'y';
const valueField = this.valueField || 'value';
const xs = [...new Set(data.map(d => d[xField]))];
const ys = [...new Set(data.map(d => d[yField]))];
const map = {};
ys.forEach(y => map[y] = {});
data.forEach(d => {
map[d[yField]][d[xField]] = d[valueField];
});
const heatmapData = [];
for (let j = 0; j < ys.length; j++) {
const y = ys[j];
for (let i = 0; i < xs.length; i++) {
const x = xs[i];
heatmapData.push([i, j, map[y][x] || 0]);
}
}
return {
tooltip: { position: 'top' },
grid: { height: '80%', top: '10%' },
xAxis: {
type: 'category',
data: xs,
splitArea: { show: true }
},
yAxis: {
type: 'category',
data: ys,
splitArea: { show: true }
},
visualMap: {
min: 0,
max: Math.max(...data.map(d => d[valueField])),
calculable: true,
orient: 'horizontal',
left: 'center',
bottom: '5%'
},
series: [{
type: 'heatmap',
data: heatmapData,
label: { show: false },
emphasis: { itemStyle: { shadowBlur: 10, shadowColor: 'rgba(0,0,0,0.5)' } }
}]
};
}
};
bricks.Factory.register('ChartHeatmap', bricks.ChartHeatmap);

49
bricks/kline.js Normal file
View File

@ -0,0 +1,49 @@
var bricks = window.bricks || {};
bricks.ChartKLine = class extends bricks.EchartsExt {
/*
数据格式:
[
{ name: '2025-04-01', open: 2100, close: 2150, low: 2080, high: 2160 },
...
]
参数:
{
data_url,
nameField: 'name', // 时间轴字段
valueFields: ['open','close','low','high']
}
*/
setup_options(data) {
const { nameField } = this;
const categories = data.map(d => d[nameField]);
const kData = data.map(d => [d.open, d.close, d.low, d.high]);
return {
tooltip: {
trigger: 'axis',
axisPointer: { type: 'cross' }
},
xAxis: {
type: 'category',
data: categories,
scale: true
},
yAxis: {
type: 'value',
scale: true
},
series: [{
type: 'candlestick',
data: kData
}],
dataZoom: [
{ type: 'inside' },
{ type: 'slider' }
]
};
}
};
bricks.Factory.register('ChartKLine', bricks.ChartKLine);

65
bricks/map.js Normal file
View File

@ -0,0 +1,65 @@
var bricks = window.bricks || {};
bricks.ChartMap = class extends bricks.EchartsExt {
/*
数据格式:
[
{ name: '北京', value: 120 },
{ name: '上海', value: 90 }, ...
]
参数:
{
data_url,
nameField: 'name',
valueField: 'value',
map_name: 'china', // 对应 echarts.registerMap 注册的地图名
map_options: {} // 可选自定义样式
}
*/
async setup_options(data) {
const { nameField, valueField = 'value', map_name = 'china', map_options } = this;
const mapData = data.map(d => ({
name: d[nameField],
value: d[valueField]
}));
return {
tooltip: {
trigger: 'item',
formatter: '{b}: {c}'
},
visualMap: {
min: 0,
max: Math.max(...mapData.map(d => d.value)),
left: 'left',
top: 'bottom',
text: ['高', '低'],
calculable: true
},
series: [{
name: '数据',
type: 'map',
map: map_name,
roam: false,
label: { show: true, color: '#fff' },
itemStyle: {
areaColor: '#eee',
borderColor: '#444'
},
emphasis: {
label: { color: '#fff' },
itemStyle: { areaColor: '#e09191' }
},
data: mapData
}],
...(map_options || {})
};
}
};
bricks.Factory.register('ChartMap', bricks.ChartMap);
/*
💡 使用前需通过 `echarts.registerMap('china', geoJson)` 注册地图数据
*/

54
bricks/radar.js Normal file
View File

@ -0,0 +1,54 @@
var bricks = window.bricks || {};
bricks.ChartRadar = class extends bricks.EchartsExt {
/*
数据格式示例:
[
{ name: '张三', indicator1: 80, indicator2: 60, ... },
{ name: '李四', indicator1: 70, indicator2: 90, ... }
]
参数:
{
data_url,
data_params,
nameField: 'name',
valueFields: ['indicator1', 'indicator2', ...],
radar_options: { // 自定义雷达配置
indicator: [
{ name: '销售', max: 100 },
{ name: '管理', max: 100 }, ...
]
}
}
*/
setup_options(data) {
const { nameField, valueFields } = this;
const series = [];
const indicator = this.radar_options?.indicator || valueFields.map(f => ({ name: f, max: 100 }));
data.forEach(item => {
series.push({
name: item[nameField],
type: 'radar',
data: [
{
value: valueFields.map(f => item[f]),
name: item[nameField]
}
]
});
});
return {
tooltip: { trigger: 'item' },
legend: { data: data.map(d => d[nameField]) },
radar: { indicator },
series
};
}
};
bricks.Factory.register('ChartRadar', bricks.ChartRadar);
/*
*/

98
bricks/scatter.js Normal file
View File

@ -0,0 +1,98 @@
var bricks = window.bricks || {};
bricks.ChartScatter = class extends bricks.EchartsExt {
/*
* opts:
* {
* data_url,
* data_params,
* method,
* user_data,
* nameField: 可选用于标签
* xField: X坐标字段
* yField: Y坐标字段
* sizeField?: 气泡大小字段可选
* categoryField?: 分组字段用于不同颜色
* }
*/
setup_options(data) {
let seriesMap = {};
if (this.categoryField) {
// 按 categoryField 分组
data.forEach(item => {
const cat = item[this.categoryField] || 'default';
if (!seriesMap[cat]) {
seriesMap[cat] = {
name: cat,
type: 'scatter',
data: []
};
}
seriesMap[cat].data.push([
item[this.xField],
item[this.yField],
item[this.nameField] || null,
item[this.sizeField] || 1
]);
});
} else {
// 单一系列
const seriesData = data.map(item => [
item[this.xField],
item[this.yField],
item[this.nameField] || null,
item[this.sizeField] || 1
]);
seriesMap['scatter'] = {
type: 'scatter',
data: seriesData
};
}
const series = Object.values(seriesMap);
const xAxisName = this.xField;
const yAxisName = this.yField;
return {
tooltip: {
trigger: 'axis',
formatter: function(params) {
const p = params[0];
return `${p.seriesName}<br/>${xAxisName}: ${p.value[0]}<br/>${yAxisName}: ${p.value[1]}`;
}
},
legend: {
data: Object.keys(seriesMap)
},
xAxis: {
type: 'value',
name: xAxisName
},
yAxis: {
type: 'value',
name: yAxisName
},
series: series
};
}
};
// 注册工厂
bricks.Factory.register('ChartScatter', bricks.ChartScatter);
/*
new bricks.ChartScatter({
user_data: [
{ x: 10, y: 20, size: 30, group: 'Group A', label: 'Point 1' },
{ x: 15, y: 25, size: 40, group: 'Group B', label: 'Point 2' }
],
xField: 'x',
yField: 'y',
sizeField: 'size',
categoryField: 'group',
nameField: 'label'
});
*/