|
@@ -1,9 +1,32 @@
|
|
|
<template>
|
|
|
- <div style="width: 100%; padding: 12px">
|
|
|
+ <div style="width: 100%; padding: 5px 12px 0 12px">
|
|
|
<el-scrollbar>
|
|
|
<div class="scrollbar-flex-content">
|
|
|
- <el-card v-for="item in 50" :key="item" class="scrollbar-demo-item">
|
|
|
- {{ item }}
|
|
|
+ <el-card
|
|
|
+ v-for="(item, index) in cardData"
|
|
|
+ :key="item.productlineId"
|
|
|
+ body-style="padding: 0;box-sizing: border-box; position: relative; width: 100%;"
|
|
|
+ class="scrollbar-demo-item"
|
|
|
+ :class="{ selected: selectedCardIndex === index }"
|
|
|
+ @click="selectCard(index, item)">
|
|
|
+ <div class="pct-chart" :id="`chart${index}-${item.productlineId}`"></div>
|
|
|
+ <el-popover placement="bottom" :width="150" trigger="click" >
|
|
|
+ <template #reference>
|
|
|
+ <el-icon class="custom-icon" @click.stop=""><MoreFilled /></el-icon>
|
|
|
+ </template>
|
|
|
+ <div class="custom-popoer">
|
|
|
+ <el-button :icon="Edit" text size="small">编辑</el-button>
|
|
|
+ <el-button :icon="Delete" text size="small" style="margin-left: 0;">删除</el-button>
|
|
|
+ </div>
|
|
|
+ </el-popover>
|
|
|
+ <div style="padding: 10px; position: relative">
|
|
|
+ <div class="product-line-name">{{ item.productlineName }}</div>
|
|
|
+
|
|
|
+ <div class="custom-part">
|
|
|
+ <div class="total-sales">{{ item.totalSales }}</div>
|
|
|
+ <span class="label">总销售额</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</el-card>
|
|
|
</div>
|
|
|
</el-scrollbar>
|
|
@@ -11,15 +34,96 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
-import { onMounted, inject } from 'vue'
|
|
|
-import { storeToRefs } from 'pinia'
|
|
|
-import { useShopInfo } from '/@/stores/shopInfo'
|
|
|
+import { onMounted, inject, ref, nextTick, watchEffect } from 'vue'
|
|
|
+import { getProductCardData } from '../api'
|
|
|
+import * as echarts from 'echarts'
|
|
|
+import { Edit, Delete } from '@element-plus/icons-vue'
|
|
|
+
|
|
|
+const profile = <any>inject('profile')
|
|
|
+
|
|
|
+const cardData = ref([])
|
|
|
+const pieChartRefs = ref<HTMLDivElement[]>([])
|
|
|
+
|
|
|
+const selectedCardIndex = ref(0)
|
|
|
+
|
|
|
+async function fetchProductCardData() {
|
|
|
+ try {
|
|
|
+ const { data } = await getProductCardData({ profileId: profile.value.profile_id })
|
|
|
+ cardData.value = data
|
|
|
+ // console.log('🚀 ~ cardData.value', cardData.value)
|
|
|
+ } catch (error) {
|
|
|
+ console.log('error:', error)
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
-const shopInfo = useShopInfo()
|
|
|
-const { profile } = storeToRefs(shopInfo)
|
|
|
-const dateRange = <any>inject('dateRange')
|
|
|
+function initChart() {
|
|
|
+ cardData.value.forEach((item, index) => {
|
|
|
+ const chartId = `chart${index}-${item.productlineId}`
|
|
|
+ const el = document.getElementById(chartId)
|
|
|
+ // const el:any = document.querySelector('#' + chartId)
|
|
|
+ if (el) {
|
|
|
+ const pieChart = echarts.init(el)
|
|
|
+ const option = {
|
|
|
+ animation: false,
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ silent: true,
|
|
|
+ avoidLabelOverlap: true,
|
|
|
+ label: {
|
|
|
+ show: true,
|
|
|
+ position: 'center',
|
|
|
+ formatter: '{d}%',
|
|
|
+ },
|
|
|
+ emphasis: {
|
|
|
+ disable: true,
|
|
|
+ scale: false,
|
|
|
+ shadowBlur: 0,
|
|
|
+ hoverAnimation: false,
|
|
|
+ label: {
|
|
|
+ show: true,
|
|
|
+ fontSize: 12,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ labelLine: {
|
|
|
+ show: false,
|
|
|
+ },
|
|
|
+ radius: ['75%', '100%'],
|
|
|
+ type: 'pie',
|
|
|
+ data: [
|
|
|
+ {
|
|
|
+ value: item.salesPercentage,
|
|
|
+ name: item.productlineName,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 100 - item.salesPercentage,
|
|
|
+ name: '',
|
|
|
+ itemStyle: {
|
|
|
+ color: '#f1eff5',
|
|
|
+ },
|
|
|
+ label: {
|
|
|
+ show: false,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ }
|
|
|
+ pieChart.setOption(option)
|
|
|
+ pieChartRefs.value[chartId] = pieChart
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
|
|
|
+function selectCard(index: number, item: any) {
|
|
|
+ selectedCardIndex.value = index
|
|
|
+ console.log('🚀 ~ selectedCardIndex.value', selectedCardIndex.value)
|
|
|
+ console.log('Selected card data:', item)
|
|
|
+}
|
|
|
|
|
|
+onMounted(async () => {
|
|
|
+ await fetchProductCardData()
|
|
|
+ initChart()
|
|
|
+})
|
|
|
</script>
|
|
|
|
|
|
<style scoped>
|
|
@@ -29,14 +133,61 @@ const dateRange = <any>inject('dateRange')
|
|
|
.scrollbar-demo-item {
|
|
|
flex-shrink: 0;
|
|
|
display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- width: 100px;
|
|
|
- height: 50px;
|
|
|
- margin: 10px;
|
|
|
- text-align: center;
|
|
|
+ width: 202px;
|
|
|
+ height: 92px;
|
|
|
+ margin: 10px 5px;
|
|
|
border-radius: 4px;
|
|
|
- background: var(--el-color-danger-light-9);
|
|
|
- color: var(--el-color-danger);
|
|
|
+ box-sizing: border-box;
|
|
|
+ border: 1px solid transparent; /* 添加透明边框 */
|
|
|
+ transition: border-color 0.3s; /* 可选,使边框颜色改变更平滑 */
|
|
|
+ cursor: pointer;
|
|
|
+}
|
|
|
+.product-line-name {
|
|
|
+ position: relative;
|
|
|
+ padding: 0 12px 8px 0;
|
|
|
+ color: #4e5969;
|
|
|
+ font-weight: 700;
|
|
|
+ font-size: 13px;
|
|
|
+ line-height: 17px;
|
|
|
+ overflow: hidden;
|
|
|
+ white-space: nowrap;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+}
|
|
|
+.custom-part {
|
|
|
+ padding-top: 8px;
|
|
|
+}
|
|
|
+.total-sales {
|
|
|
+ color: #4e5969;
|
|
|
+ font-size: 13px;
|
|
|
+ font-weight: 700;
|
|
|
+}
|
|
|
+.label {
|
|
|
+ padding-right: 4px;
|
|
|
+ color: #c9cdd4;
|
|
|
+ font-size: 12px;
|
|
|
+}
|
|
|
+.pct-chart {
|
|
|
+ box-sizing: border-box;
|
|
|
+ position: absolute;
|
|
|
+ top: 34px;
|
|
|
+ right: 5%;
|
|
|
+ width: 50px;
|
|
|
+ height: 50px;
|
|
|
+}
|
|
|
+.selected {
|
|
|
+ border: 1px solid #3359b5;
|
|
|
+}
|
|
|
+.custom-icon {
|
|
|
+ position: absolute;
|
|
|
+ top: 8px;
|
|
|
+ right: 5%;
|
|
|
+ z-index: 2;
|
|
|
+ color: #c9cdd4;
|
|
|
+ /* padding: 4px; */
|
|
|
+ transform: rotate(90deg);
|
|
|
+}
|
|
|
+.custom-popoer {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
}
|
|
|
</style>
|