454 lines
14 KiB
Vue
454 lines
14 KiB
Vue
<template>
|
||
<view class="brand-detail">
|
||
<!-- 商户类别比例图 -->
|
||
<view class="brand-type-box">
|
||
<view class="section-header">
|
||
<text class="section-title">商户类别比例图</text>
|
||
</view>
|
||
|
||
<!-- 图表容器 -->
|
||
<view class="chart-container">
|
||
<!-- 图表加载效果 -->
|
||
<ChartLoading v-if="!hasChartData" text="数据加载中..." />
|
||
<!-- 实际图表 -->
|
||
<QiunDataCharts v-else type="pie" :opts="chartOpts" :chartData="chartData" :canvas2d="true"
|
||
:inScrollView="true" canvasId="brandChart" :animation="false" :ontap="true" :ontouch="true"
|
||
tooltipFormat="BrandDetail" />
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 品牌列表 -->
|
||
<view class="brand-list">
|
||
<!-- Tab切换 -->
|
||
<view class="tab-box">
|
||
<scroll-view class="tab-scroll" scroll-x="true" :show-scrollbar="false">
|
||
<view class="tab-content">
|
||
<view :class="selectTab === index + 1 ? 'tab-item select-tab' : 'tab-item'"
|
||
v-for="(item, index) in tabList" :key="index" @click="handleChangeTab(index + 1)">
|
||
{{ item.label }}
|
||
</view>
|
||
</view>
|
||
</scroll-view>
|
||
</view>
|
||
|
||
<!-- 品牌列表容器 -->
|
||
<view class="brand-list-box">
|
||
<!-- 品牌列表加载效果 -->
|
||
<ChartLoading v-if="!hasBrandListData" text="数据加载中..." />
|
||
<!-- 品牌列表内容 -->
|
||
<view v-else>
|
||
<view class="brand-item" v-for="(item, index) in brandListData" :key="index"
|
||
:style="{ marginBottom: index + 1 === brandListData.length ? '0' : '20rpx' }">
|
||
<view class=" brand-left">
|
||
<image class="brand-icon" :src="item.BRAND_INTRO || defaultImg" mode="aspectFill" />
|
||
</view>
|
||
|
||
<view class="brand-right">
|
||
<view class="brand-right-top">
|
||
<view class="brand-right-top-left">{{ item.BRAND_NAME }}</view>
|
||
<view class="brand-right-top-right">
|
||
<!-- 原组件中的服务区数量显示已被注释 -->
|
||
</view>
|
||
</view>
|
||
|
||
<view class="brand-right-bottom">
|
||
<view class="brand-right-bottom-item">{{ item.BRAND_TYPENAME }}</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'
|
||
import ChartLoading from './ChartLoading.vue'
|
||
import request from "@/util/index.js";
|
||
import moment from 'moment'
|
||
import { wrapTreeNode } from "@/util/dateTime";
|
||
|
||
export default {
|
||
components: {
|
||
QiunDataCharts,
|
||
ChartLoading
|
||
},
|
||
|
||
data() {
|
||
return {
|
||
// Tab列表
|
||
tabList: [],
|
||
selectTab: 1, // 当前选中的Tab
|
||
|
||
// 全部的品牌数据
|
||
allBrandObjData: {},
|
||
|
||
// 品牌列表数据
|
||
brandListData: [],
|
||
|
||
// 图表原始数据
|
||
rawData: {
|
||
pieData: []
|
||
},
|
||
|
||
// 默认图片
|
||
defaultImg: 'https://eshangtech.com/cyy_DIB/defaultIcon.png'
|
||
}
|
||
},
|
||
|
||
computed: {
|
||
// 检查是否有图表数据
|
||
hasChartData() {
|
||
return this.rawData.pieData.length > 0
|
||
},
|
||
|
||
// 检查是否有品牌列表数据
|
||
hasBrandListData() {
|
||
return this.brandListData && this.brandListData.length > 0;
|
||
},
|
||
|
||
// 图表数据
|
||
chartData() {
|
||
return {
|
||
series: [{
|
||
data: this.rawData.pieData
|
||
}]
|
||
}
|
||
},
|
||
|
||
// 图表配置
|
||
chartOpts() {
|
||
return {
|
||
padding: [15, 15, 0, 15],
|
||
dataLabel: false,
|
||
legend: {
|
||
show: true,
|
||
position: 'right',
|
||
float: 'center',
|
||
fontSize: 12,
|
||
fontColor: '#333333',
|
||
},
|
||
extra: {
|
||
pie: {
|
||
activeRadius: 10,
|
||
offsetAngle: 0,
|
||
labelWidth: 0,
|
||
border: false,
|
||
borderWidth: 2,
|
||
borderColor: '#FFFFFF',
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
|
||
onReady() {
|
||
this.handleGoMounted()
|
||
},
|
||
|
||
methods: {
|
||
// 初始化挂载
|
||
async handleGoMounted() {
|
||
await this.handleGetData()
|
||
await this.handleBrandTabList()
|
||
},
|
||
|
||
// 获取商户类别比例数据
|
||
async handleGetData() {
|
||
const req = {
|
||
ProvinceCode: "530000",
|
||
type: 'encryption'
|
||
}
|
||
|
||
const data = await this.getBrandStructureAnalysis(req);
|
||
|
||
// 处理数据
|
||
this.processChartData(data.Result_Data.List)
|
||
},
|
||
|
||
// 发起API请求获取商户类别比例数据
|
||
async getBrandStructureAnalysis(params) {
|
||
// 这里使用模拟数据,实际应该调用真实的API
|
||
const data = await request.$posPost(
|
||
"CommercialApi/BaseInfo/GetBrandStructureAnalysis",
|
||
params
|
||
);
|
||
|
||
return data || []
|
||
},
|
||
|
||
// 处理图表数据
|
||
processChartData(data) {
|
||
let pieData = []
|
||
|
||
console.log('datadatadata', data);
|
||
|
||
|
||
// 处理数据:获取商户类别比例数据
|
||
if (data && data.length > 0) {
|
||
data.forEach((item) => {
|
||
pieData.push({
|
||
name: item.name,
|
||
value: Number(item.value)
|
||
})
|
||
})
|
||
}
|
||
|
||
// 更新图表数据
|
||
this.rawData = {
|
||
pieData: pieData
|
||
}
|
||
},
|
||
|
||
// 获取品牌列表数据
|
||
async handleBrandTabList() {
|
||
// 这里需要获取品牌分类和对应的品牌列表
|
||
const tabData = await this.getBusinessTradeTree({
|
||
PROVINCE_CODE: "530000",
|
||
PageIndex: 1
|
||
})
|
||
let list = wrapTreeNode(tabData.Result_Data.List)
|
||
|
||
if (list && list.length > 0) {
|
||
let tableList = []
|
||
list.forEach((item) => {
|
||
tableList.push({
|
||
label: item.AUTOSTATISTICS_NAME,
|
||
value: item.AUTOSTATISTICS_ID
|
||
})
|
||
})
|
||
|
||
this.tabList = tableList
|
||
|
||
// 获取每个分类下的品牌数据
|
||
let obj = {}
|
||
for (let i = 0; i < tableList.length; i++) {
|
||
obj[tableList[i].value] = await this.handleGetTableData(tableList[i].value)
|
||
|
||
if (i === 0) {
|
||
this.brandListData = obj[tableList[i].value]
|
||
}
|
||
}
|
||
|
||
this.allBrandObjData = obj
|
||
}
|
||
},
|
||
|
||
// 发起API请求获取品牌分类
|
||
async getBusinessTradeTree(params) {
|
||
// 这里使用模拟数据,实际应该调用真实的API
|
||
const data = await request.$apiGet(
|
||
"EShangApiMain/BaseInfo/GetBusinessTradeTree",
|
||
params
|
||
);
|
||
|
||
return data || []
|
||
},
|
||
|
||
// 获取表单数据
|
||
async handleGetTableData(BRAND_INDUSTRY) {
|
||
const req = {
|
||
PROVINCE_CODE: "530000",
|
||
BRAND_STATE: 1,
|
||
BRAND_INDUSTRY: BRAND_INDUSTRY
|
||
}
|
||
|
||
const data = await this.getCombineBrandList(req)
|
||
|
||
return data.Result_Data.List.slice(0, 6) // 只取前6个
|
||
},
|
||
|
||
// 发起API请求获取品牌列表
|
||
async getCombineBrandList(params) {
|
||
// 这里使用模拟数据,实际应该调用真实的API
|
||
const data = await request.$apiGet(
|
||
"EShangApiMain/BaseInfo/GetCombineBrandList",
|
||
params
|
||
);
|
||
|
||
return data || []
|
||
},
|
||
|
||
// 切换Tab
|
||
handleChangeTab(value) {
|
||
if (this.allBrandObjData[this.tabList[value - 1].value]) {
|
||
this.brandListData = []
|
||
this.selectTab = value
|
||
this.brandListData = this.allBrandObjData[this.tabList[value - 1].value]
|
||
}
|
||
},
|
||
|
||
// 更新图表数据
|
||
async handleUpdateChart() {
|
||
await this.handleGetData()
|
||
await this.handleBrandTabList()
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped lang="less">
|
||
@text-primary: #333;
|
||
@text-secondary: #666;
|
||
@bg-white: #ffffff;
|
||
|
||
.brand-detail {
|
||
width: 100%;
|
||
margin-top: 24rpx;
|
||
|
||
.brand-type-box {
|
||
margin-bottom: 32rpx;
|
||
|
||
.section-header {
|
||
margin-bottom: 24rpx;
|
||
|
||
.section-title {
|
||
font-size: 30rpx;
|
||
font-weight: 600;
|
||
color: @text-primary;
|
||
}
|
||
}
|
||
|
||
.chart-container {
|
||
background: #fff;
|
||
border-radius: 16rpx;
|
||
padding: 24rpx;
|
||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
|
||
margin-bottom: 32rpx;
|
||
height: 440rpx;
|
||
}
|
||
}
|
||
|
||
.brand-list {
|
||
.tab-box {
|
||
background: #fff;
|
||
border-radius: 16rpx;
|
||
padding: 24rpx;
|
||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
|
||
margin-bottom: 32rpx;
|
||
|
||
.tab-scroll {
|
||
width: 100%;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.tab-content {
|
||
display: flex;
|
||
gap: 24rpx;
|
||
white-space: nowrap;
|
||
|
||
.tab-item {
|
||
font-size: 24rpx;
|
||
font-weight: 600;
|
||
color: @text-secondary;
|
||
text-align: center;
|
||
padding: 12rpx 24rpx;
|
||
border-radius: 8rpx;
|
||
background: #f5f5f5;
|
||
transition: all 0.3s;
|
||
flex-shrink: 0;
|
||
display: inline-block;
|
||
}
|
||
|
||
.select-tab {
|
||
font-weight: 600;
|
||
color: #fff;
|
||
background: linear-gradient(135deg, #1890ff 0%, #46B8F3 100%);
|
||
box-shadow: 0 4rpx 12rpx rgba(24, 144, 255, 0.3);
|
||
}
|
||
}
|
||
}
|
||
|
||
.brand-list-box {
|
||
background: #fff;
|
||
border-radius: 16rpx;
|
||
padding: 24rpx;
|
||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
|
||
min-height: 300rpx;
|
||
/* 设置最小高度以显示加载效果 */
|
||
|
||
.brand-item {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 24rpx;
|
||
border-radius: 12rpx;
|
||
margin-bottom: 20rpx;
|
||
background: #f8f9fa;
|
||
border: 1px solid #e9ecef;
|
||
|
||
&:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.brand-left {
|
||
width: 120rpx;
|
||
height: 120rpx;
|
||
border-radius: 12rpx;
|
||
overflow: hidden;
|
||
margin-right: 24rpx;
|
||
background: #fff;
|
||
|
||
.brand-icon {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
}
|
||
|
||
.brand-right {
|
||
flex: 1;
|
||
|
||
.brand-right-top {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
margin-bottom: 12rpx;
|
||
|
||
.brand-right-top-left {
|
||
font-size: 24rpx;
|
||
font-weight: 600;
|
||
color: @text-primary;
|
||
}
|
||
|
||
.brand-right-top-right {
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.brand-right-top-right-icon {
|
||
width: 24rpx;
|
||
height: 24rpx;
|
||
margin-right: 8rpx;
|
||
}
|
||
|
||
.brand-right-top-right-value {
|
||
font-size: 24rpx;
|
||
font-weight: 600;
|
||
color: @text-primary;
|
||
}
|
||
|
||
.brand-right-top-right-unit {
|
||
font-size: 20rpx;
|
||
color: @text-secondary;
|
||
margin-left: 4rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
.brand-right-bottom {
|
||
.brand-right-bottom-item {
|
||
font-size: 24rpx;
|
||
color: #1890FF;
|
||
text-align: center;
|
||
display: inline-block;
|
||
padding: 2rpx 16rpx;
|
||
background: rgba(24, 144, 255, 0.1);
|
||
border-radius: 8rpx;
|
||
border: 1px solid rgba(24, 144, 255, 0.2);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</style> |