基於互聯網大牛的前端改進一下,做了個可執行程序,獲取數據後更新到頁面上。
首先看動態效果圖 :
一、 確定需求方案
1、確定產品上線部署的屏幕LED分辨率
1920px*1080px,F11全屏後佔滿整屏且無滾動條。其它分辨率也可自適應。
2、功能模塊
用戶訪問來源分析(餅圖): 包括搜索引擎,聯盟廣告,直接訪問
訪問地區分佈(柱狀圖 + 地圖 + 熱力圖):浙江、上海、廣東、北京
年齡分佈(餅圖):0歲以上、20-29歲、30-39歲、40-49歲、50歲以上
職業分佈(餅圖):電子商務、教育、IT/互聯網、金融、學生、其他
興趣分佈(餅圖):汽車、旅遊、財經、教育、軟件、其他
終端設備分佈(線圖):Android + iOS移動端設備使用量
頻道訪問量Top5(柱狀圖):實時顯示最新Top5頻道
點贊量Top5(餅圖): 實時顯示最新Top5地區
3、部署方式
基於免安裝可執行程序:支持Windows、Linux、Mac等各種操作系統;將程序複製到服務器上即可,無需其它環境依賴;
觀看方式:既可在服務器上直接觀看程序界面,也可在遠程用瀏覽器打開播放,例如Chrome瀏覽器、360瀏覽器等。
二、整體架構設計
1、前端基於Echarts開源庫設計,使用WebStorm編輯器;
2、後端基於Python Web實現,使用Pycharm編輯器;
3、數據傳輸格式:JSON;
4、數據源類型:目前已支持PostgreSQL、MySQL、Oracle、Microsoft SQL Server、SQLite、Excel表格等,還可以定製HTTP API接口方式或其它類型數據庫。
5、數據更新方式:摒棄了前端頁面定時拉取的方式(這種方式帶來嚴重的資源浪費),採用後端數據實時更新,實時推送到前端展示;
三、編碼實現 (基於篇幅及可讀性考慮,此處展示部分關鍵代碼)
1、前端html代碼:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta content="*" http-equiv="Access-Control-Allow-Origin"/>
<title>index</title>
<script src="js/jquery.js" type="text/javascript"></script>
<link href="css/comon0.css" rel="stylesheet">
</head>
<script>
$(window).load(function () {
$(".loading").fadeOut()
})
/****/
$(document).ready(function () {
var whei = $(window).width()
$("html").css({fontSize: whei / 20})
$(window).resize(function () {
var whei = $(window).width()
$("html").css({fontSize: whei / 20})
});
});
</script>
<script src="js/echarts.min.js" type="text/javascript"></script>
<script language="JavaScript" src="js/js.js"></script>
<body>
<div class="canvas" style="opacity: .2">
<iframe frameborder="0" src="js/index.html" style="width: 100%; height: 100%"></iframe>
</div>
<div class="loading">
<div class="loadbox"><img src="picture/loading.gif"> 頁面加載中...</div>
</div>
<div class="head">
<h1>大數據可視化展板 —— 互聯網企業數據分析</h1>
<div class="weather"><!--<img src="picture/weather.png"><span>多雲轉小雨</span>--><span id="showTime"></span></div>
<script>
//alert("aaaaaa");
var t = null;
t = setTimeout(time, 1000);//開始運行
function time() {
clearTimeout(t);//清除定時器
dt = new Date();
var y = dt.getFullYear();
var mt = dt.getMonth() + 1;
var day = dt.getDate();
var h = dt.getHours();//獲取時
var m = dt.getMinutes();//獲取分
var s = dt.getSeconds();//獲取秒
document.getElementById("showTime").innerHTML = y + "年" + mt + "月" + day + "-" + h + "時" + m + "分" + s + "秒";
//async_data();
t = setTimeout(time, 1000); //設定定時器,循環運行
}
</script>
</div>
<div class="mainbox">
<ul class="clearfix">
<li>
<div class="boxall" style="height: 3.2rem">
<div class="alltitle">用戶訪問來源</div>
<div class="allnav" id="echart1"></div>
<div class="boxfoot"></div>
</div>
<div class="boxall" style="height: 3.2rem">
<div class="alltitle">訪問地區分佈</div>
<div class="allnav" id="echart2"></div>
<div class="boxfoot"></div>
</div>
<div class="boxall" style="height: 3.2rem">
<div style="height:100%; width: 100%;">
<div class="sy" id="fb1"></div>
<div class="sy" id="fb2"></div>
<div class="sy" id="fb3"></div>
</div>
<div class="boxfoot">
</div>
</div>
</li>
<li>
<div class="bar">
<div class="barbox">
<ul class="clearfix">
<li class="pulll_left counter " id="total_pv">12581189</li>
<li class="pulll_left counter" id="total_income">3912410</li>
</ul>
</div>
<div class="barbox2">
<ul class="clearfix">
<li class="pulll_left">總閱讀量(pv)</li>
<li class="pulll_left">總收益</li>
</ul>
</div>
</div>
<div class="map">
<div class="map1"><img src="picture/lbx.png"></div>
<div class="map2"><img src="picture/jt.png"></div>
<div class="map3"><img src="picture/map.png"></div>
<div class="map4" id="map_1"></div>
</div>
</li>
<li>
<div class="boxall" style="height:3.4rem">
<div class="alltitle">終端設備分佈</div>
<div class="allnav" id="echart4"></div>
<div class="boxfoot"></div>
</div>
<div class="boxall" style="height: 3.2rem">
<div class="alltitle">頻道訪問量Top5</div>
<div class="allnav" id="echart5"></div>
<div class="boxfoot"></div>
</div>
<div class="boxall" style="height: 3rem">
<div class="alltitle">點贊量Top5</div>
<div class="allnav" id="echart6"></div>
<div class="boxfoot"></div>
</div>
</li>
</ul>
</div>
<div class="back"></div>
<script src="js/china.js" type="text/javascript"></script>
<script src="js/area_echarts.js" type="text/javascript"></script>
</body>
</html>
2、前端js代碼:
var echarts_series_data = [
{value: 335, name: '直接訪問'},
{value: 310, name: '郵件營銷'},
{value: 234, name: '聯盟廣告'},
];
$(function() {
echarts_1();
echarts_2();
echarts_4();
echarts_31();
echarts_32();
echarts_33();
echarts_5();
echarts_6();
function echarts_1() {
var myChart = echarts.init(document.getElementById('echart1'));
option = {
title: {
// text: '某站點用戶訪問來源',
// subtext: '純屬虛構',
left: 'center'
},
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b} : {c} ({d}%)'
},
legend: {
// orient: 'vertical',
left: 'left',
// data: echarts_data
},
series: [
{
name: '訪問來源',
type: 'pie',
radius: '55%',
center: ['50%', '60%'],
data: echarts_series_data,
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
};
// 使用剛指定的配置項和數據顯示圖表。
myChart.setOption(option);
window.addEventListener("resize", function () {
myChart.resize();
});
}
function echarts_2() {
// 基於準備好的dom,初始化echarts實例
var myChart = echarts.init(document.getElementById('echart2'));
var echarts_data = ['浙江', '上海', '江蘇', '廣東', '北京', '深圳', '安徽'];
var echarts_series_data = [1500, 1200, 600, 200, 300, 300, 900];
option = {
// backgroundColor: '#00265f',
tooltip: {
trigger: 'axis',
axisPointer: { type: 'shadow'}
},
grid: {
left: '0%',
top:'10px',
right: '0%',
bottom: '4%',
containLabel: true
},
xAxis: [{
type: 'category',
data: echarts_data,
axisLine: {
show: true,
lineStyle: {
color: "rgba(255,255,255,.1)",
width: 1,
type: "solid"
},
},
axisTick: {
show: false,
},
axisLabel: {
interval: 0,
// rotate:50,
show: true,
splitNumber: 15,
textStyle: {
color: "rgba(255,255,255,.6)",
fontSize: '12',
},
},
}],
yAxis: [{
type: 'value',
axisLabel: {
//formatter: '{value} %'
show:true,
textStyle: {
color: "rgba(255,255,255,.6)",
fontSize: '12',
},
},
axisTick: {
show: false,
},
axisLine: {
show: true,
lineStyle: {
color: "rgba(255,255,255,.1 )",
width: 1,
type: "solid"
},
},
splitLine: {
lineStyle: {
color: "rgba(255,255,255,.1)",
}
}
}],
series: [
{
type: 'bar',
data: echarts_series_data,
barWidth:'35%', //柱子寬度
// barGap: 1, //柱子之間間距
itemStyle: {
normal: {
color:'#27d08a',
opacity: 1,
barBorderRadius: 5,
}
}
}
]
};
// 使用剛指定的配置項和數據顯示圖表。
myChart.setOption(option);
window.addEventListener("resize", function () {
myChart.resize();
});
}
function echarts_5() {
// 基於準備好的dom,初始化echarts實例
var myChart = echarts.init(document.getElementById('echart5'));
option = {
dataset: {
source: [
['數量', '項目'],
[ 28, 'C\C++'],
[ 48, 'Java'],
[ 61, 'Php'],
[ 92, 'Python'],
[ 101, 'Go']
]
},
// grid: {containLabel: true},
grid: {
left: '0%',
top:'10px',
right: '0%',
bottom: '4%',
containLabel: true
},
xAxis: [{
type: 'value',
// type: 'category',
// data: echarts_data,
axisLine: {
show: true,
lineStyle: {
color: "rgba(255,255,255,.1)",
width: 1,
type: "solid"
},
},
axisTick: {
show: false,
},
axisLabel: {
interval: 0,
// rotate:50,
show: true,
splitNumber: 15,
textStyle: {
color: "rgba(255,255,255,.6)",
fontSize: '12',
},
},
}],
yAxis: [{
type: 'category',
// type: 'value',
axisLabel: {
//formatter: '{value} %'
show: true,
textStyle: {
color: "rgba(255,255,255,.6)",
fontSize: '12',
},
},
axisTick: {
show: false,
},
axisLine: {
show: true,
lineStyle: {
color: "rgba(255,255,255,.1 )",
width: 1,
type: "solid"
},
},
splitLine: {
lineStyle: {
color: "rgba(255,255,255,.1)",
}
}
}],
series: [
{
type: 'bar',
encode: {
// Map the "amount" column to X axis.
x: '數量',
// Map the "product" column to Y axis
y: '產品'
}
}
]
};
// 使用剛指定的配置項和數據顯示圖表。
myChart.setOption(option);
window.addEventListener("resize", function () {
myChart.resize();
});
}
function echarts_4() {
// 基於準備好的dom,初始化echarts實例
var myChart = echarts.init(document.getElementById('echart4'));
option = {
tooltip: {
trigger: 'axis',
axisPointer: {
lineStyle: {
color: '#dddc6b'
}
}
},
legend: {
top:'0%',
data:['安卓','IOS'],
textStyle: {
color: 'rgba(255,255,255,.5)',
fontSize: '12',
}
},
grid: {
left: '10',
top: '30',
right: '10',
bottom: '10',
containLabel: true
},
xAxis: [{
type: 'category',
boundaryGap: false,
axisLabel: {
textStyle: {
color: "rgba(255,255,255,.6)",
fontSize: 12,
},
},
axisLine: {
lineStyle: {
color: 'rgba(255,255,255,.2)'
}
},
data: ['01', '02', '03', '04', '05', '06', '07', '08', '09', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24']
}, {
axisPointer: {show: false},
axisLine: {show: false},
position: 'bottom',
offset: 20,
}],
yAxis: [{
type: 'value',
axisTick: {show: false},
axisLine: {
lineStyle: {
color: 'rgba(255,255,255,.1)'
}
},
axisLabel: {
textStyle: {
color: "rgba(255,255,255,.6)",
fontSize: 12,
},
},
splitLine: {
lineStyle: {
color: 'rgba(255,255,255,.1)'
}
}
}],
series: [
{
name: '安卓',
type: 'line',
smooth: true,
symbol: 'circle',
symbolSize: 5,
showSymbol: false,
lineStyle: {
normal: {
color: '#0184d5',
width: 2
}
},
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(1, 132, 213, 0.4)'
}, {
offset: 0.8,
color: 'rgba(1, 132, 213, 0.1)'
}], false),
shadowColor: 'rgba(0, 0, 0, 0.1)',
}
},
itemStyle: {
normal: {
color: '#0184d5',
borderColor: 'rgba(221, 220, 107, .1)',
borderWidth: 12
}
},
data: [3, 4, 3, 4, 3, 4, 3, 6, 2, 4, 2, 4,3, 4, 3, 4, 3, 4, 3, 6, 2, 4, 2, 4]
},
{
name: 'IOS',
type: 'line',
smooth: true,
symbol: 'circle',
symbolSize: 5,
showSymbol: false,
lineStyle: {
normal: {
color: '#00d887',
width: 2
}
},
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(0, 216, 135, 0.4)'
}, {
offset: 0.8,
color: 'rgba(0, 216, 135, 0.1)'
}], false),
shadowColor: 'rgba(0, 0, 0, 0.1)',
}
},
itemStyle: {
normal: {
color: '#00d887',
borderColor: 'rgba(221, 220, 107, .1)',
borderWidth: 12
}
},
data: [5, 3, 5, 6, 1, 5, 3, 5, 6, 4, 6, 4, 8, 3, 5, 6, 1, 5, 3, 7, 2, 5, 1, 4]
},
]
};
// 使用剛指定的配置項和數據顯示圖表。
myChart.setOption(option);
window.addEventListener("resize", function () {
myChart.resize();
});
}
function echarts_6() {
// 基於準備好的dom,初始化echarts實例
var myChart = echarts.init(document.getElementById('echart6'));
var dataStyle = {
normal: {
label: {
show: false
},
labelLine: {
show: false
},
//shadowBlur: 40,
//shadowColor: 'rgba(40, 40, 40, 1)',
}
};
var placeHolderStyle = {
normal: {
color: 'rgba(255,255,255,.05)',
label: {show: false,},
labelLine: {show: false}
},
emphasis: {
color: 'rgba(0,0,0,0)'
}
};
option = {
color: ['#0f63d6', '#0f78d6', '#0f8cd6', '#0fa0d6', '#0fb4d6'],
tooltip: {
show: true,
formatter: "{a} : {c} "
},
legend: {
itemWidth: 10,
itemHeight: 10,
itemGap: 12,
bottom: '3%',
data: ['浙江', '上海', '廣東', '北京', '深圳'],
textStyle: {
color: 'rgba(255,255,255,.6)',
}
},
series: [
{
name: '浙江',
type: 'pie',
clockWise: false,
center: ['50%', '42%'],
radius: ['59%', '70%'],
itemStyle: dataStyle,
hoverAnimation: false,
data: [{
value: 80,
name: '01'
}, {
value: 20,
name: 'invisible',
tooltip: {show: false},
itemStyle: placeHolderStyle
}]
},
{
name: '上海',
type: 'pie',
clockWise: false,
center: ['50%', '42%'],
radius: ['49%', '60%'],
itemStyle: dataStyle,
hoverAnimation: false,
data: [{
value: 70,
name: '02'
}, {
value: 30,
name: 'invisible',
tooltip: {show: false},
itemStyle: placeHolderStyle
}]
},
{
name: '廣東',
type: 'pie',
clockWise: false,
hoverAnimation: false,
center: ['50%', '42%'],
radius: ['39%', '50%'],
itemStyle: dataStyle,
data: [{
value: 65,
//name: '03'
}, {
value: 35,
//name: 'invisible',
//tooltip: {show: false},
itemStyle: placeHolderStyle
}]
} ]
};
// 使用剛指定的配置項和數據顯示圖表。
myChart.setOption(option);
window.addEventListener("resize", function () {
myChart.resize();
});
}
function echarts_31() {
// 基於準備好的dom,初始化echarts實例
var myChart = echarts.init(document.getElementById('fb1'));
option = {
title: [{
text: '年齡分佈',
left: 'center',
textStyle: {
color: '#fff',
fontSize:'16'
}
}],
tooltip: {
trigger: 'item',
formatter: "{a} <br/>{b}: {c} ({d}%)",
position:function(p){ //其中p爲當前鼠標的位置
return [p[0] + 10, p[1] - 10];
}
},
legend: {
top:'70%',
itemWidth: 10,
itemHeight: 10,
data:['0歲以下','20-29歲','30-39歲','40-49歲','50歲以上'],
textStyle: {
color: 'rgba(255,255,255,.5)',
fontSize:'12',
}
},
series: [
{
name:'年齡分佈',
type:'pie',
center: ['50%', '42%'],
radius: ['40%', '60%'],
color: ['#065aab', '#066eab', '#0682ab', '#0696ab', '#06a0ab','#06b4ab','#06c8ab','#06dcab','#06f0ab'],
label: {show:false},
labelLine: {show:false},
data:[
{value:1, name:'0歲以下'},
{value:4, name:'20-29歲'},
{value:2, name:'30-39歲'},
{value:2, name:'40-49歲'},
{value:1, name:'50歲以上'},
]
}
]
};
// 使用剛指定的配置項和數據顯示圖表。
myChart.setOption(option);
window.addEventListener("resize", function () {
myChart.resize();
});
}
function echarts_32() {
// 基於準備好的dom,初始化echarts實例
var myChart = echarts.init(document.getElementById('fb2'));
option = {
title: [{
text: '職業分佈',
left: 'center',
textStyle: {
color: '#fff',
fontSize: '16'
}
}],
tooltip: {
trigger: 'item',
formatter: "{a} <br/>{b}: {c} ({d}%)",
position:function(p){ //其中p爲當前鼠標的位置
return [p[0] + 10, p[1] - 10];
}
},
legend: {
top:'70%',
itemWidth: 10,
itemHeight: 10,
data:['電子商務','教育','IT/互聯網','金融','學生','其他'],
textStyle: {
color: 'rgba(255,255,255,.5)',
fontSize:'12',
}
},
series: [
{
name:'職業分佈',
type:'pie',
center: ['50%', '42%'],
radius: ['40%', '60%'],
color: ['#065aab', '#066eab', '#0682ab', '#0696ab', '#06a0ab','#06b4ab','#06c8ab','#06dcab','#06f0ab'],
label: {show:false},
labelLine: {show:false},
data:[
{value:5, name:'電子商務'},
{value:1, name:'教育'},
{value:6, name:'IT/互聯網'},
{value:2, name:'金融'},
{value:1, name:'學生'},
{value:1, name:'其他'},
]
}
]
};
// 使用剛指定的配置項和數據顯示圖表。
myChart.setOption(option);
window.addEventListener("resize", function () {
myChart.resize();
});
}
function echarts_33() {
// 基於準備好的dom,初始化echarts實例
var myChart = echarts.init(document.getElementById('fb3'));
option = {
title: [{
text: '興趣分佈',
left: 'center',
textStyle: {
color: '#fff',
fontSize: '16'
}
}],
tooltip: {
trigger: 'item',
formatter: "{a} <br/>{b}: {c} ({d}%)",
position:function(p){ //其中p爲當前鼠標的位置
return [p[0] + 10, p[1] - 10];
}
},
legend: {
top:'70%',
itemWidth: 10,
itemHeight: 10,
data:['汽車','旅遊','財經','教育','軟件','其他'],
textStyle: {
color: 'rgba(255,255,255,.5)',
fontSize:'12',
}
},
series: [
{
name:'興趣分佈',
type:'pie',
center: ['50%', '42%'],
radius: ['40%', '60%'],
color: ['#065aab', '#066eab', '#0682ab', '#0696ab', '#06a0ab','#06b4ab','#06c8ab','#06dcab','#06f0ab'],
label: {show:false},
labelLine: {show:false},
data:[
{value:2, name:'汽車'},
{value:3, name:'旅遊'},
{value:1, name:'財經'},
{value:4, name:'教育'},
{value:8, name:'軟件'},
{value:1, name:'其他'},
]
}
]
};
// 使用剛指定的配置項和數據顯示圖表。
myChart.setOption(option);
window.addEventListener("resize", function () {
myChart.resize();
});
}
})
//async_data();
function async_data() {
// 異步加載數據
$.getJSON('json/echart1.json').done(function (data) {
var myChart = echarts.init(document.getElementById('echart1'));
myChart.setOption({
series: [{
data: data
}]
});
});//end $.getJSON
$.getJSON('json/echart2.json').done(function (data) {
var myChart = echarts.init(document.getElementById('echart2'));
myChart.setOption({
xAxis: data["xAxis"],
series:data["series"]
});
}); //end $.getJSON
$.getJSON('json/echart4.json').done(function (data) {
var myChart = echarts.init(document.getElementById('echart4'));
myChart.setOption({
legend: data["legend"],
xAxis: data["xAxis"],
series: data["series"]
});
});//end $.getJSON
$.getJSON('json/echart5.json').done(function (data) {
var myChart = echarts.init(document.getElementById('echart5'));
myChart.setOption({
dataset: data["dataset"]
});
});//end $.getJSON
$.getJSON('json/echart6.json').done(function (data) {
var myChart = echarts.init(document.getElementById('echart6'));
myChart.setOption({
legend: data["legend"],
series: data["series"]
});
});//end $.getJSON
$.getJSON('json/echart31.json').done(function (data) {
var myChart = echarts.init(document.getElementById('fb1'));
// console.log(data["legend"])
myChart.setOption({
title: data["title"],
legend: data["legend"],
series: data["series"]
});
});//end $.getJSON
$.getJSON('json/echart32.json').done(function (data) {
var myChart = echarts.init(document.getElementById('fb2'));
// console.log(data["legend"])
myChart.setOption({
title: data["title"],
legend: data["legend"],
series: data["series"]
});
});//end $.getJSON
$.getJSON('json/echart33.json').done(function (data) {
var myChart = echarts.init(document.getElementById('fb3'));
// console.log(data["legend"])
myChart.setOption({
title: data["title"],
legend: data["legend"],
series: data["series"]
});
});//end $.getJSON
$.getJSON('json/common.json').done(function (data) {
document.getElementById('total_pv').innerText = data["total_pv"]
document.getElementById('total_income').innerText = data["total_income"]
});//end $.getJSON
}
3、後端python代碼
#author QQ "6550523" or weixin "6550523"
import _thread
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtWebEngineWidgets import QWebEngineView
from pyecharts import Geo
from PyQt5.QtCore import QUrl
from win32api import GetSystemMetrics
from PyQt5 import QtGui
from httpserver import *
from asyncJson import *
class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.loadfinished = False
self.setWindowTitle('大屏展示')
self.showMaximized()
#全屏顯示
self.showFullScreen()
self.isFullScreen = True
self.webview = WebEngineView()
# self.webview.load(QUrl("file:///index.html"))
self.webview.load(QUrl("http://localhost:8888/index.html"))
self.setCentralWidget(self.webview)
QShortcut(QtGui.QKeySequence("Escape"), self, self.Esc)
self.webview.loadFinished.connect(self.SetLoadFinished)
_thread.start_new_thread(HttpServer, ())
_thread.start_new_thread(self.ChangeData, ())
def SetLoadFinished(self):
self.loadfinished = True
#按ESC全屏或縮小
def Esc(self):
if self.isFullScreen == True :
self.isFullScreen = False
#不加這句的話,標題欄就看不到了
self.showNormal()
#設置固定寬高
self.setGeometry(GetSystemMetrics(0)/2, GetSystemMetrics(1)/2, 1280, 768)
#再移動到屏幕中央
screen = QDesktopWidget().screenGeometry()
size = self.geometry()
self.move((screen.width() - size.width()) / 2, (screen.height() - size.height()) / 2)
else:
self.showFullScreen()
self.isFullScreen = True
class WebEngineView(QWebEngineView):
windowList = []
# 重寫createwindow()
def createWindow(self, QWebEnginePage_WebWindowType):
new_webview = WebEngineView()
new_window = MainWindow()
new_window.setCentralWidget(new_webview)
#new_window.show()
return new_webview
if __name__ == "__main__":
app = QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
四、上線運行
本次分享結束,如有疑問歡迎討論!QQ和微信號相同 6550523