zhangwencui
2 天以前 766ce6b9beedcc89ee83fe5daed0523bbd8c7e33
src/views/reportAnalysis/dataDashboard/components/basic/left-bottom.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,244 @@
<template>
  <div>
    <PanelHeader title="客户营收贡献数值分析" />
    <div class="main-panel panel-item-customers">
      <div class="filters-row">
        <el-select
          v-model="customerValue"
          class="customer-select"
          placeholder="请选择客户"
          clearable
          filterable
          @change="handleFilterChange"
        >
          <el-option
            v-for="item in customerOptions"
            :key="item.value"
            :label="item.label"
            :value="item.value"
          />
        </el-select>
        <DateTypeSwitch v-model="dateType" @change="handleFilterChange" />
      </div>
      <Echarts
          ref="chart"
          :chartStyle="chartStyle"
          :grid="grid"
          :legend="barLegend"
          :series="barSeries1"
          :tooltip="tooltip"
          :xAxis="xAxis1"
          :yAxis="yAxis1"
          :options="{ backgroundColor: 'transparent', textStyle: { color: '#B8C8E0' } }"
          style="height: 260px"
        />
    </div>
  </div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import Echarts from '@/components/Echarts/echarts.vue'
import PanelHeader from '../PanelHeader.vue'
import DateTypeSwitch from '../DateTypeSwitch.vue'
import { customerRevenueAnalysis } from '@/api/viewIndex.js'
import { listCustomer } from '@/api/basicData/customerFile.js'
const dateType = ref(1) // 1=周 2=月 3=季度
const customerValue = ref(null)
const customerOptions = ref([])
// è¥æ”¶åˆ†æžæ•°æ®
const revenueData = ref({
  items: []
})
const chartStyle = {
  width: '100%',
  height: '150%',
}
const grid = {
  left: '3%',
  right: '4%',
  bottom: '3%',
  containLabel: true,
}
const barLegend = {
  show: false,
  textStyle: { color: '#B8C8E0' },
  data: ['营收'],
}
const barSeries1 = ref([
  {
    name: '营收',
    type: 'bar',
    barGap: 0,
    emphasis: {
      focus: 'series',
    },
    itemStyle: {
      color: {
        type: 'linear',
        x: 0,
        y: 1,
        x2: 0,
        y2: 0,
        colorStops: [
          // linear-gradient(360deg, rgba(0,164,237,0) 0%, #4EE4FF 100%)
          { offset: 0, color: 'rgba(0,164,237,0)' },
          { offset: 1, color: '#4EE4FF' },
        ],
      },
    },
    data: [],
  },
])
const tooltip = {
  trigger: 'axis',
  axisPointer: {
    type: 'shadow',
  },
  formatter: function (params) {
    let result = params[0].axisValueLabel + '<br/>'
    params.forEach((item) => {
      result += `<div style="color: #B8C8E0">${item.marker} ${item.seriesName}: ${item.value}</div>`
    })
    return result
  },
}
const xAxis1 = ref([
  {
    type: 'category',
    axisTick: { show: false },
    axisLabel: { color: '#B8C8E0' },
    data: [],
  },
])
const yAxis1 = [
  {
    type: 'value',
    axisLabel: { color: '#B8C8E0' },
  },
]
// èŽ·å–å®¢æˆ·è¥æ”¶åˆ†æžæ•°æ®
const getCustomerRevenueAnalysis = () => {
  if (customerOptions.value.length > 0 && !customerValue.value) {
    // é»˜è®¤é€‰ä¸­ç¬¬ä¸€ä¸ªå®¢æˆ·
    customerValue.value = customerOptions.value[0].value
  }
  if (!customerValue.value) return
  const params = {
    customerId: customerValue.value,
    type: dateType.value
  }
  customerRevenueAnalysis(params)
    .then((res) => {
      xAxis1.value[0].data = []
      barSeries1.value[0].data = []
      const items = res.data?.items || []
      items.forEach((item) => {
        xAxis1.value[0].data.push(item.name)
        barSeries1.value[0].data.push(item.value)
      })
      revenueData.value = res.data
    })
    .catch((error) => {
      console.error('获取客户营收分析失败:', error)
    })
}
const fetchCustomerOptions = async () => {
  try {
    const params = { pageNum: 1, pageSize: 200 }
    const res = await listCustomer(params)
    const records = res?.records || res?.data?.records || res?.rows || []
    customerOptions.value = records.map((r) => ({
      label: r.customerName || r.name || r.customer || '-',
      value: r.id ?? r.customerId ?? r.customerCode ?? r.customerName,
    }))
    // èŽ·å–åˆ°é€‰é¡¹åŽï¼Œå¦‚æžœè¿˜æ²¡é€‰ä¸­ï¼Œé»˜è®¤é€‰ä¸­ç¬¬ä¸€ä¸ª
    if (customerOptions.value.length > 0 && !customerValue.value) {
      customerValue.value = customerOptions.value[0].value
      getCustomerRevenueAnalysis()
    }
  } catch (e) {
    // æŽ¥å£å¼‚常时给一组模拟客户,保证UI可用
    customerOptions.value = [
      { label: '华东精密', value: '华东精密' },
      { label: '星辰电子', value: '星辰电子' },
      { label: '启航科技', value: '启航科技' },
      { label: '铭诚制造', value: '铭诚制造' },
      { label: '远景材料', value: '远景材料' },
    ]
  }
}
const handleFilterChange = () => {
  getCustomerRevenueAnalysis()
}
onMounted(() => {
  fetchCustomerOptions()
})
</script>
<style scoped>
.main-panel {
  display: flex;
  flex-direction: column;
  gap: 20px;
}
.filters-row {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 12px;
  margin-bottom: 10px;
}
.customer-select {
  width: 180px;
}
/* ä¸‹æ‹‰æ¡†é£Žæ ¼ï¼šä¸Ž DateTypeSwitch ä¿æŒä¸€è‡´ï¼ˆæ·±è‰²åŠé€æ˜Žã€æµ…色文字、细边框) */
.customer-select :deep(.el-input__wrapper),
.customer-select :deep(.el-select__wrapper) {
  background-color: rgba(26, 88, 176, 0.3);
  border: 1px solid rgba(255, 255, 255, 0.2);
  box-shadow: none;
}
.customer-select :deep(.el-input__inner) {
  color: rgba(184, 200, 224, 0.9);
}
.customer-select :deep(.el-input__inner::placeholder) {
  color: rgba(184, 200, 224, 0.6);
}
.customer-select :deep(.el-select__caret),
.customer-select :deep(.el-icon) {
  color: rgba(184, 200, 224, 0.8);
}
.panel-item-customers {
  border: 1px solid #1a58b0;
  padding: 18px;
  width: 100%;
  height: 478px;
}
</style>