3 天以前 1c829f9177eab675b22be4d20ef2761ed1bbb423
src/views/reportAnalysis/dataDashboard/components/basic/left-bottom.vue
@@ -9,6 +9,8 @@
          placeholder="请选择客户"
          clearable
          filterable
          popper-class="customer-select-dropdown"
          :teleported="false"
          @change="handleFilterChange"
        >
          <el-option
@@ -30,36 +32,45 @@
          :tooltip="tooltip"
          :xAxis="xAxis1"
          :yAxis="yAxis1"
          :options="{ backgroundColor: 'transparent', textStyle: { color: '#B8C8E0' } }"
          style="height: 260px"
        />
          :options="{ backgroundColor: 'transparent', textStyle: { color: '#8FA3C8' } }"
          style="height: 370px"
        >
          <div v-if="loaded && !hasRevenueData" class="chart-empty">暂无营收数据</div>
        </Echarts>
    </div>
  </div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { ref, computed, onMounted } from 'vue'
import Echarts from '@/components/Echarts/echarts.vue'
import PanelHeader from '../PanelHeader.vue'
import DateTypeSwitch from '../DateTypeSwitch.vue'
import { qualityStatistics } from '@/api/viewIndex.js'
import { customerRevenueAnalysis } from '@/api/viewIndex.js'
import { listCustomer } from '@/api/basicData/customerFile.js'
import { BI, withTooltip } from '../../theme.js'
const dateType = ref(1) // 1=周 2=月 3=季度
const dateType = ref(3) // 1=周 2=月 3=季度,默认季度
const customerValue = ref(null)
const customerOptions = ref([])
// 质检统计对象
const qualityStatisticsObject = ref({
  supplierNum: 0,
  processNum: 0,
  factoryNum: 0,
// 营收分析数据
const revenueData = ref({
  items: []
})
const chartStyle = {
  width: '100%',
  height: '150%',
  height: '100%',
}
// 是否已拿到响应(区分加载中与真的无数据)
const loaded = ref(false)
// 有数据才显示柱子
const hasRevenueData = computed(
  () => (revenueData.value.items || []).some((i) => Number(i.value) > 0)
)
const grid = {
  left: '3%',
@@ -70,7 +81,7 @@
const barLegend = {
  show: false,
  textStyle: { color: '#B8C8E0' },
  textStyle: { color: BI.text },
  data: ['营收'],
}
@@ -90,9 +101,8 @@
        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' },
          { offset: 0, color: 'rgba(74, 108, 240, 0)' },
          { offset: 1, color: '#4A6CF0' },
        ],
      },
    },
@@ -100,7 +110,7 @@
  },
])
const tooltip = {
const tooltip = withTooltip({
  trigger: 'axis',
  axisPointer: {
    type: 'shadow',
@@ -108,17 +118,19 @@
  formatter: function (params) {
    let result = params[0].axisValueLabel + '<br/>'
    params.forEach((item) => {
      result += `<div style="color: #B8C8E0">${item.marker} ${item.seriesName}: ${item.value}</div>`
      const val = Number(item.value || 0).toLocaleString('zh-CN')
      result += `<div>${item.marker} ${item.seriesName}: ${val} 元</div>`
    })
    return result
  },
}
})
const xAxis1 = ref([
  {
    type: 'category',
    axisTick: { show: false },
    axisLabel: { color: '#B8C8E0' },
    axisLine: { show: false },
    axisLabel: { color: BI.text, fontSize: 12 },
    data: [],
  },
])
@@ -126,29 +138,46 @@
const yAxis1 = [
  {
    type: 'value',
    axisLabel: { color: '#B8C8E0' },
    axisLabel: { color: BI.text, fontSize: 12 },
    axisLine: { show: false },
    axisTick: { show: false },
    splitLine: { lineStyle: { color: 'rgba(143, 163, 200, 0.15)' } },
  },
]
// 质检统计
const qualityStatisticsInfo = () => {
  qualityStatistics()
// 获取客户营收分析数据
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
  }
  loaded.value = false
  customerRevenueAnalysis(params)
    .then((res) => {
      // 切换筛选条件时,先清空再填充,避免重复 push
      xAxis1.value[0].data = []
      barSeries1.value[0].data = []
      res.data.item.forEach((item) => {
        xAxis1.value[0].data.push(item.date)
        // 这里暂用 supplierNum 作为柱状图数值(接口返回里当前也有这三个字段)
        barSeries1.value[0].data.push(item.supplierNum)
      const items = res.data?.items || []
      items.forEach((item) => {
        xAxis1.value[0].data.push(item.name)
        barSeries1.value[0].data.push(Number(item.value) || 0)
      })
      qualityStatisticsObject.value.supplierNum = res.data.supplierNum
      qualityStatisticsObject.value.processNum = res.data.processNum
      qualityStatisticsObject.value.factoryNum = res.data.factoryNum
      revenueData.value = res.data || { items: [] }
    })
    .catch((error) => {
      console.error('获取质检统计失败:', error)
      console.error('获取客户营收分析失败:', error)
      revenueData.value = { items: [] }
    })
    .finally(() => {
      loaded.value = true
    })
}
@@ -161,6 +190,12 @@
      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 = [
@@ -174,14 +209,11 @@
}
const handleFilterChange = () => {
  // 目前 qualityStatistics 接口未携带筛选参数,这里先统一触发刷新,避免重复数据
  // 若后端后续支持 customerId/type,可在 qualityStatistics() 处改为传参
  qualityStatisticsInfo()
  getCustomerRevenueAnalysis()
}
onMounted(() => {
  fetchCustomerOptions()
  qualityStatisticsInfo()
})
</script>
@@ -207,28 +239,59 @@
/* 下拉框风格:与 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);
  background-color: rgba(20, 32, 66, 0.55);
  border: 1px solid #1e3160;
  box-shadow: none;
}
.customer-select :deep(.el-input__inner) {
  color: rgba(184, 200, 224, 0.9);
  color: #8fa3c8;
}
.customer-select :deep(.el-input__inner::placeholder) {
  color: rgba(184, 200, 224, 0.6);
  color: rgba(143, 163, 200, 0.6);
}
.customer-select :deep(.el-select__caret),
.customer-select :deep(.el-icon) {
  color: rgba(184, 200, 224, 0.8);
  color: #8fa3c8;
}
.panel-item-customers {
  border: 1px solid #1a58b0;
  border: 1px solid var(--bi-panel-border);
  background: var(--bi-panel-bg);
  border-radius: 8px;
  padding: 18px;
  width: 100%;
  height: 478px;
}
.chart-empty {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 370px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--bi-text);
  font-size: 14px;
  letter-spacing: 1px;
  pointer-events: none;
}
</style>
<style>
/* 全屏模式下下拉框层级修复 */
.customer-select-dropdown {
  z-index: 10001 !important;
}
/* 确保在全屏容器内的下拉框也能正常显示 */
.scale-container:fullscreen .customer-select-dropdown,
.scale-container:-webkit-full-screen .customer-select-dropdown,
.scale-container:-ms-fullscreen .customer-select-dropdown {
  z-index: 10001 !important;
}
</style>