|
@@ -36,11 +36,11 @@
|
|
|
</tr>
|
|
</tr>
|
|
|
</tbody>
|
|
</tbody>
|
|
|
</table>
|
|
</table>
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
<!-- 分页控件 -->
|
|
<!-- 分页控件 -->
|
|
|
<div class="pagination">
|
|
<div class="pagination">
|
|
|
- <button
|
|
|
|
|
- :disabled="currentPage === 1"
|
|
|
|
|
|
|
+ <button
|
|
|
|
|
+ :disabled="currentPage === 1"
|
|
|
@click="prevPage"
|
|
@click="prevPage"
|
|
|
class="page-button"
|
|
class="page-button"
|
|
|
>
|
|
>
|
|
@@ -49,8 +49,8 @@
|
|
|
<span class="page-info">
|
|
<span class="page-info">
|
|
|
第 {{ currentPage }} 页,共 {{ totalPages }} 页
|
|
第 {{ currentPage }} 页,共 {{ totalPages }} 页
|
|
|
</span>
|
|
</span>
|
|
|
- <button
|
|
|
|
|
- :disabled="currentPage === totalPages"
|
|
|
|
|
|
|
+ <button
|
|
|
|
|
+ :disabled="currentPage === totalPages"
|
|
|
@click="nextPage"
|
|
@click="nextPage"
|
|
|
class="page-button"
|
|
class="page-button"
|
|
|
>
|
|
>
|
|
@@ -107,7 +107,7 @@ export default {
|
|
|
},
|
|
},
|
|
|
async fetchData() {
|
|
async fetchData() {
|
|
|
try {
|
|
try {
|
|
|
- const response = await axios.get('/api/analysis/co-purchase');
|
|
|
|
|
|
|
+ const response = await axios.get('/prod-api/api/analysis/co-purchase');
|
|
|
this.coPurchaseData = response.data || [];
|
|
this.coPurchaseData = response.data || [];
|
|
|
this.renderNetworkChart(this.coPurchaseData);
|
|
this.renderNetworkChart(this.coPurchaseData);
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
@@ -120,27 +120,27 @@ export default {
|
|
|
const chartEl = this.$refs.networkChart;
|
|
const chartEl = this.$refs.networkChart;
|
|
|
if (!chartEl || !data) return;
|
|
if (!chartEl || !data) return;
|
|
|
const myChart = echarts.init(chartEl);
|
|
const myChart = echarts.init(chartEl);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 统计每个节点的出现次数(核心度)
|
|
// 统计每个节点的出现次数(核心度)
|
|
|
const nodeCount = {};
|
|
const nodeCount = {};
|
|
|
// 统计每条连线的权重
|
|
// 统计每条连线的权重
|
|
|
const linkWeights = {};
|
|
const linkWeights = {};
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
data.forEach(item => {
|
|
data.forEach(item => {
|
|
|
// 统计节点出现次数
|
|
// 统计节点出现次数
|
|
|
nodeCount[item.productAId] = (nodeCount[item.productAId] || 0) + 1;
|
|
nodeCount[item.productAId] = (nodeCount[item.productAId] || 0) + 1;
|
|
|
nodeCount[item.productBId] = (nodeCount[item.productBId] || 0) + 1;
|
|
nodeCount[item.productBId] = (nodeCount[item.productBId] || 0) + 1;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 统计连线权重
|
|
// 统计连线权重
|
|
|
const linkKey = `${item.productAId}-${item.productBId}`;
|
|
const linkKey = `${item.productAId}-${item.productBId}`;
|
|
|
linkWeights[linkKey] = (linkWeights[linkKey] || 0) + item.coPurchaseCount;
|
|
linkWeights[linkKey] = (linkWeights[linkKey] || 0) + item.coPurchaseCount;
|
|
|
});
|
|
});
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 创建节点和连线
|
|
// 创建节点和连线
|
|
|
const nodes = [];
|
|
const nodes = [];
|
|
|
const links = [];
|
|
const links = [];
|
|
|
const nodeSet = new Set();
|
|
const nodeSet = new Set();
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 用于自动聚类的颜色分类
|
|
// 用于自动聚类的颜色分类
|
|
|
const categories = [
|
|
const categories = [
|
|
|
{ name: '社群1', itemStyle: { color: '#FF6B6B' } },
|
|
{ name: '社群1', itemStyle: { color: '#FF6B6B' } },
|
|
@@ -150,11 +150,11 @@ export default {
|
|
|
{ name: '社群5', itemStyle: { color: '#FFEAA7' } },
|
|
{ name: '社群5', itemStyle: { color: '#FFEAA7' } },
|
|
|
{ name: '社群6', itemStyle: { color: '#DDA0DD' } }
|
|
{ name: '社群6', itemStyle: { color: '#DDA0DD' } }
|
|
|
];
|
|
];
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 用于社群聚类的简单算法
|
|
// 用于社群聚类的简单算法
|
|
|
const nodeCategories = {};
|
|
const nodeCategories = {};
|
|
|
let categoryIndex = 0;
|
|
let categoryIndex = 0;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
data.forEach(item => {
|
|
data.forEach(item => {
|
|
|
// 添加节点A
|
|
// 添加节点A
|
|
|
if (!nodeSet.has(item.productAId)) {
|
|
if (!nodeSet.has(item.productAId)) {
|
|
@@ -163,22 +163,22 @@ export default {
|
|
|
const count = nodeCount[item.productAId];
|
|
const count = nodeCount[item.productAId];
|
|
|
// 节点大小范围:15-50
|
|
// 节点大小范围:15-50
|
|
|
const symbolSize = Math.min(15 + count * 5, 50);
|
|
const symbolSize = Math.min(15 + count * 5, 50);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 简单的社群聚类:根据第一个关联商品确定社群
|
|
// 简单的社群聚类:根据第一个关联商品确定社群
|
|
|
if (!nodeCategories[item.productAId]) {
|
|
if (!nodeCategories[item.productAId]) {
|
|
|
nodeCategories[item.productAId] = categoryIndex % categories.length;
|
|
nodeCategories[item.productAId] = categoryIndex % categories.length;
|
|
|
categoryIndex++;
|
|
categoryIndex++;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- nodes.push({
|
|
|
|
|
- id: item.productAId,
|
|
|
|
|
- name: item.productAId,
|
|
|
|
|
- symbolSize: symbolSize,
|
|
|
|
|
|
|
+
|
|
|
|
|
+ nodes.push({
|
|
|
|
|
+ id: item.productAId,
|
|
|
|
|
+ name: item.productAId,
|
|
|
|
|
+ symbolSize: symbolSize,
|
|
|
category: nodeCategories[item.productAId],
|
|
category: nodeCategories[item.productAId],
|
|
|
value: count // 用于tooltip显示
|
|
value: count // 用于tooltip显示
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 添加节点B
|
|
// 添加节点B
|
|
|
if (!nodeSet.has(item.productBId)) {
|
|
if (!nodeSet.has(item.productBId)) {
|
|
|
nodeSet.add(item.productBId);
|
|
nodeSet.add(item.productBId);
|
|
@@ -186,22 +186,22 @@ export default {
|
|
|
const count = nodeCount[item.productBId];
|
|
const count = nodeCount[item.productBId];
|
|
|
// 节点大小范围:15-50
|
|
// 节点大小范围:15-50
|
|
|
const symbolSize = Math.min(15 + count * 5, 50);
|
|
const symbolSize = Math.min(15 + count * 5, 50);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 简单的社群聚类:根据第一个关联商品确定社群
|
|
// 简单的社群聚类:根据第一个关联商品确定社群
|
|
|
if (!nodeCategories[item.productBId]) {
|
|
if (!nodeCategories[item.productBId]) {
|
|
|
nodeCategories[item.productBId] = categoryIndex % categories.length;
|
|
nodeCategories[item.productBId] = categoryIndex % categories.length;
|
|
|
categoryIndex++;
|
|
categoryIndex++;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- nodes.push({
|
|
|
|
|
- id: item.productBId,
|
|
|
|
|
- name: item.productBId,
|
|
|
|
|
- symbolSize: symbolSize,
|
|
|
|
|
|
|
+
|
|
|
|
|
+ nodes.push({
|
|
|
|
|
+ id: item.productBId,
|
|
|
|
|
+ name: item.productBId,
|
|
|
|
|
+ symbolSize: symbolSize,
|
|
|
category: nodeCategories[item.productBId],
|
|
category: nodeCategories[item.productBId],
|
|
|
value: count // 用于tooltip显示
|
|
value: count // 用于tooltip显示
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 添加连线
|
|
// 添加连线
|
|
|
const linkKey = `${item.productAId}-${item.productBId}`;
|
|
const linkKey = `${item.productAId}-${item.productBId}`;
|
|
|
const weight = linkWeights[linkKey];
|
|
const weight = linkWeights[linkKey];
|