From 003924b2eab1928fd723ca73be0b1a33342de664 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期二, 27 一月 2026 14:33:00 +0800
Subject: [PATCH] 进销存-升级 1.巡检管理修改上传附件 2.新增销售台账是产品大类查询修改 3.销售台账发货逻辑判断修改,状态展示优化 4.采购审批信息展示优化 5.指标统计页面样式优化
---
src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue | 2
src/views/salesManagement/indicatorStats/index.vue | 537 +++++++++++++++++++++++++++++++++++++++++++++++++---------
2 files changed, 449 insertions(+), 90 deletions(-)
diff --git a/src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue b/src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue
index c3fb6d1..aad5b23 100644
--- a/src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue
+++ b/src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue
@@ -104,7 +104,7 @@
<h4>浜у搧鏄庣粏</h4>
<el-table :data="currentQuotation.products || []" border style="width: 100%">
<el-table-column prop="product" label="浜у搧鍚嶇О" />
- <el-table-column prop="specificationModel" label="瑙勬牸鍨嬪彿" />
+ <el-table-column prop="specification" label="瑙勬牸鍨嬪彿" />
<el-table-column prop="unit" label="鍗曚綅" />
<el-table-column prop="unitPrice" label="鍗曚环">
<template #default="scope">楼{{ Number(scope.row.unitPrice ?? 0).toFixed(2) }}</template>
diff --git a/src/views/salesManagement/indicatorStats/index.vue b/src/views/salesManagement/indicatorStats/index.vue
index 65dae96..8cbeb24 100644
--- a/src/views/salesManagement/indicatorStats/index.vue
+++ b/src/views/salesManagement/indicatorStats/index.vue
@@ -1,82 +1,161 @@
<template>
<div class="app-container indicator-stats">
- <el-card class="box-card">
- <!-- KPI 姹囨�� -->
- <el-row :gutter="20" class="stats-row">
- <el-col :span="8">
- <div class="stat-card">
- <div class="stat-icon" style="background: #ecf5ff;">
- <el-icon :size="30" color="#409eff"><Document /></el-icon>
- </div>
- <div class="stat-content">
- <div class="stat-value">{{ indicatorKpis.orderCount.toLocaleString() }}</div>
- <div class="stat-label">璁㈠崟鏁伴噺</div>
+ <!-- KPI 姹囨�� -->
+ <el-row :gutter="20" class="stats-row">
+ <el-col :xs="24" :sm="12" :md="8">
+ <div class="stat-card stat-card-blue">
+ <div class="stat-icon-wrapper">
+ <div class="stat-icon">
+ <el-icon :size="32"><Document /></el-icon>
</div>
</div>
- </el-col>
- <el-col :span="8">
- <div class="stat-card">
- <div class="stat-icon" style="background: #f0f9ff;">
- <el-icon :size="30" color="#67c23a"><Tickets /></el-icon>
- </div>
- <div class="stat-content">
- <div class="stat-value">楼{{ indicatorKpis.salesAmount.toLocaleString() }}</div>
- <div class="stat-label">閿�鍞</div>
+ <div class="stat-content">
+ <div class="stat-value">{{ indicatorKpis.orderCount.toLocaleString() }}</div>
+ <div class="stat-label">璁㈠崟鏁伴噺</div>
+ </div>
+ <div class="stat-bg-decoration"></div>
+ </div>
+ </el-col>
+ <el-col :xs="24" :sm="12" :md="8">
+ <div class="stat-card stat-card-green">
+ <div class="stat-icon-wrapper">
+ <div class="stat-icon">
+ <el-icon :size="32"><Tickets /></el-icon>
</div>
</div>
- </el-col>
- <el-col :span="8">
- <div class="stat-card">
- <div class="stat-icon" style="background: #fef0f0;">
- <el-icon :size="30" color="#e6a23c"><Van /></el-icon>
- </div>
- <div class="stat-content">
- <div class="stat-value">{{ indicatorKpis.shipRate }}%</div>
- <div class="stat-label">鍙戣揣鐜�</div>
+ <div class="stat-content">
+ <div class="stat-value">楼{{ indicatorKpis.salesAmount.toLocaleString() }}</div>
+ <div class="stat-label">閿�鍞</div>
+ </div>
+ <div class="stat-bg-decoration"></div>
+ </div>
+ </el-col>
+ <el-col :xs="24" :sm="12" :md="8">
+ <div class="stat-card stat-card-orange">
+ <div class="stat-icon-wrapper">
+ <div class="stat-icon">
+ <el-icon :size="32"><Van /></el-icon>
</div>
</div>
- </el-col>
- </el-row>
+ <div class="stat-content">
+ <div class="stat-value">{{ indicatorKpis.shipRate }}%</div>
+ <div class="stat-label">鍙戣揣鐜�</div>
+ </div>
+ <div class="stat-bg-decoration"></div>
+ </div>
+ </el-col>
+ </el-row>
- <!-- 缁村害绛涢�� -->
- <el-row :gutter="20" class="search-row">
- <el-col :span="6">
- <el-tree-select v-model="indicatorFilter.productCategory" placeholder="浜у搧绫诲埆" clearable check-strictly
- :data="productOptions" :render-after-expand="false" style="width: 100%" />
- </el-col>
- <el-col :span="6">
- <el-select v-model="indicatorFilter.customerName" placeholder="瀹㈡埛" clearable filterable>
- <el-option v-for="item in customerOption" :key="item.id" :label="item.customerName" :value="item.customerName" />
- </el-select>
- </el-col>
- <el-col :span="6">
- <el-date-picker v-model="indicatorFilter.dateRange" type="daterange" range-separator="鑷�"
- start-placeholder="寮�濮嬫棩鏈�" end-placeholder="缁撴潫鏃ユ湡" value-format="YYYY-MM-DD" style="width: 100%" />
- </el-col>
- <el-col :span="6" style="text-align: right;">
- <el-button type="primary" @click="applyIndicatorFilter">鏌ヨ</el-button>
- <el-button @click="resetIndicatorFilter">閲嶇疆</el-button>
- </el-col>
- </el-row>
-
- <!-- 鍥捐〃鍖� -->
- <div class="chart-container">
- <div ref="indicatorChartRef" class="chart-wrapper"></div>
+ <!-- 鍥捐〃鍖猴紙鍖呭惈绛涢�夋潯浠讹級 -->
+ <el-card class="chart-card" shadow="hover">
+ <template #header>
+ <div class="card-header">
+ <div class="header-left">
+ <span class="card-title">閿�鍞秼鍔垮垎鏋�</span>
+ <span class="card-subtitle">绛涢�夋潯浠朵粎褰卞搷涓嬫柟鍥捐〃鏁版嵁</span>
+ </div>
+ </div>
+ </template>
+
+ <!-- 鍥捐〃绛涢�夋潯浠� -->
+ <div class="chart-filter-section">
+ <el-row :gutter="16" class="search-row">
+ <el-col :xs="24" :sm="12" :md="6">
+ <div class="filter-item">
+ <label class="filter-label">浜у搧绫诲埆</label>
+ <el-tree-select
+ v-model="indicatorFilter.productCategory"
+ placeholder="璇烽�夋嫨浜у搧绫诲埆"
+ clearable
+ check-strictly
+ :data="productOptions"
+ :render-after-expand="false"
+ style="width: 100%"
+ />
+ </div>
+ </el-col>
+ <el-col :xs="24" :sm="12" :md="6">
+ <div class="filter-item">
+ <label class="filter-label">瀹㈡埛</label>
+ <el-select
+ v-model="indicatorFilter.customerName"
+ placeholder="璇烽�夋嫨瀹㈡埛"
+ clearable
+ filterable
+ style="width: 100%"
+ >
+ <el-option
+ v-for="item in customerOption"
+ :key="item.id"
+ :label="item.customerName"
+ :value="item.customerName"
+ />
+ </el-select>
+ </div>
+ </el-col>
+ <el-col :xs="24" :sm="12" :md="6">
+ <div class="filter-item">
+ <label class="filter-label">鏃ユ湡鑼冨洿</label>
+ <el-date-picker
+ v-model="indicatorFilter.dateRange"
+ type="daterange"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ style="width: 100%"
+ />
+ </div>
+ </el-col>
+ <el-col :xs="24" :sm="12" :md="6">
+ <div class="filter-item filter-buttons">
+ <el-button type="primary" :loading="loading" @click="applyIndicatorFilter">
+ <el-icon><Search /></el-icon>
+ 鏌ヨ鍥捐〃
+ </el-button>
+ <el-button @click="resetIndicatorFilter">
+ <el-icon><Refresh /></el-icon>
+ 閲嶇疆
+ </el-button>
+ </div>
+ </el-col>
+ </el-row>
</div>
- <!-- 涓氱哗缁熻锛堝洟闃熺淮搴︼紝鏃犱釜浜哄鍚嶏級 -->
- <el-table v-if="showTeamPerformance" :data="teamPerformanceList" border stripe style="margin-top: 20px;">
- <el-table-column prop="team" label="閿�鍞洟闃�"/>
- <el-table-column prop="orderCount" label="璁㈠崟鏁�"/>
- <el-table-column prop="salesAmount" label="閿�鍞">
+ <!-- 鍥捐〃灞曠ず鍖� -->
+ <div class="chart-container" v-loading="loading">
+ <div ref="indicatorChartRef" class="chart-wrapper"></div>
+ </div>
+ </el-card>
+
+ <!-- 涓氱哗缁熻锛堝洟闃熺淮搴︼紝鏃犱釜浜哄鍚嶏級 -->
+ <el-card v-if="showTeamPerformance" class="table-card" shadow="hover">
+ <template #header>
+ <div class="card-header">
+ <span class="card-title">鍥㈤槦涓氱哗缁熻</span>
+ </div>
+ </template>
+ <el-table
+ :data="teamPerformanceList"
+ border
+ stripe
+ style="width: 100%"
+ :header-cell-style="{ background: '#f5f7fa', color: '#606266', fontWeight: 'bold' }"
+ >
+ <el-table-column prop="team" label="閿�鍞洟闃�" min-width="120"/>
+ <el-table-column prop="orderCount" label="璁㈠崟鏁�" align="right" min-width="100"/>
+ <el-table-column prop="salesAmount" label="閿�鍞" align="right" min-width="140">
<template #default="scope">楼{{ scope.row.salesAmount.toLocaleString() }}</template>
</el-table-column>
- <el-table-column prop="shipRate" label="鍙戣揣鐜�">
- <template #default="scope">{{ scope.row.shipRate }}</template>
+ <el-table-column prop="shipRate" label="鍙戣揣鐜�" align="right" min-width="100">
+ <template #default="scope">{{ scope.row.shipRate }}%</template>
</el-table-column>
- <el-table-column prop="attainment" label="鐩爣杈炬垚鐜�">
+ <el-table-column prop="attainment" label="鐩爣杈炬垚鐜�" align="center" min-width="120">
<template #default="scope">
- <el-tag :type="scope.row.attainment >= 100 ? 'success' : scope.row.attainment >= 80 ? 'warning' : 'danger'">
+ <el-tag
+ :type="scope.row.attainment >= 100 ? 'success' : scope.row.attainment >= 80 ? 'warning' : 'danger'"
+ effect="dark"
+ >
{{ scope.row.attainment }}%
</el-tag>
</template>
@@ -88,7 +167,7 @@
<script setup>
import { ref, reactive, onMounted, onUnmounted, nextTick } from 'vue'
-import { Document, Van, Tickets } from '@element-plus/icons-vue'
+import { Document, Van, Tickets, Search, Refresh } from '@element-plus/icons-vue'
import * as echarts from 'echarts'
import { getTotalStatistics, getStatisticsTable } from '@/api/salesManagement/indicatorStats'
import { productTreeList } from '@/api/basicData/product.js'
@@ -325,10 +404,8 @@
}
const applyIndicatorFilter = async () => {
- await Promise.all([
- fetchTotalStatistics(),
- fetchStatisticsTable()
- ])
+ // 绛涢�夋潯浠跺彧褰卞搷鍥捐〃鏁版嵁锛屼笉褰卞搷KPI姹囨��
+ await fetchStatisticsTable()
}
const resetIndicatorFilter = () => {
@@ -368,31 +445,313 @@
})
</script>
-<style scoped>
+<style scoped lang="scss">
.indicator-stats {
- padding: 0;
+ padding: 20px;
+ background: #f5f7fa;
+ min-height: calc(100vh - 84px);
}
-.box-card { border: none; box-shadow: none; }
-.search-row { margin-bottom: 20px; }
-.stats-row { margin-bottom: 24px; }
-.stat-card { display: flex; align-items: center; padding: 20px; background: #fff; border-radius: 8px; box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); }
-.stat-icon { width: 60px; height: 60px; display: flex; align-items: center; justify-content: center; border-radius: 8px; margin-right: 16px; }
-.stat-content { flex: 1; }
-.stat-value { font-size: 28px; font-weight: bold; color: #303133; margin-bottom: 4px; }
-.stat-label { font-size: 14px; color: #909399; }
-.chart-container {
- margin: 20px 0;
- padding: 20px;
- background: #fff;
- border-radius: 8px;
- box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+
+.page-header {
+ margin-bottom: 24px;
+ padding: 20px 0;
+
+ .page-title {
+ font-size: 24px;
+ font-weight: 600;
+ color: #303133;
+ margin: 0 0 8px 0;
+ }
+
+ .page-desc {
+ font-size: 14px;
+ color: #909399;
+ margin: 0;
+ }
+}
+
+.stats-row {
+ margin-bottom: 24px;
+}
+
+.stat-card {
+ position: relative;
+ display: flex;
+ align-items: center;
+ padding: 24px;
+ background: #fff;
+ border-radius: 12px;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.08);
+ transition: all 0.3s ease;
+ overflow: hidden;
+
+ &:hover {
+ transform: translateY(-4px);
+ box-shadow: 0 8px 24px 0 rgba(0, 0, 0, 0.12);
+ }
+
+ .stat-icon-wrapper {
+ margin-right: 20px;
+
+ .stat-icon {
+ width: 64px;
+ height: 64px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 12px;
+ transition: all 0.3s ease;
+ }
+ }
+
+ .stat-content {
+ flex: 1;
+ z-index: 1;
+
+ .stat-value {
+ font-size: 32px;
+ font-weight: 700;
+ color: #303133;
+ margin-bottom: 8px;
+ line-height: 1.2;
+ }
+
+ .stat-label {
+ font-size: 14px;
+ color: #909399;
+ font-weight: 500;
+ }
+ }
+
+ .stat-bg-decoration {
+ position: absolute;
+ right: -20px;
+ top: -20px;
+ width: 120px;
+ height: 120px;
+ border-radius: 50%;
+ opacity: 0.1;
+ z-index: 0;
+ }
+
+ &.stat-card-blue {
+ .stat-icon {
+ background: linear-gradient(135deg, #409eff 0%, #66b1ff 100%);
+ color: #fff;
+ }
+
+ .stat-bg-decoration {
+ background: #409eff;
+ }
+ }
+
+ &.stat-card-green {
+ .stat-icon {
+ background: linear-gradient(135deg, #67c23a 0%, #85ce61 100%);
+ color: #fff;
+ }
+
+ .stat-bg-decoration {
+ background: #67c23a;
+ }
+ }
+
+ &.stat-card-orange {
+ .stat-icon {
+ background: linear-gradient(135deg, #e6a23c 0%, #ebb563 100%);
+ color: #fff;
+ }
+
+ .stat-bg-decoration {
+ background: #e6a23c;
+ }
+ }
+}
+
+.chart-card,
+.table-card {
+ margin-bottom: 20px;
+ border-radius: 12px;
+ border: none;
+
+ :deep(.el-card__header) {
+ padding: 18px 20px;
+ border-bottom: 1px solid #ebeef5;
+ background: linear-gradient(135deg, #f5f7fa 0%, #ffffff 100%);
+ }
+
+ :deep(.el-card__body) {
+ padding: 0;
+ }
+}
+
+.card-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+
+ .header-left {
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+ }
+
+ .card-title {
+ font-size: 16px;
+ font-weight: 600;
+ color: #303133;
+ }
+
+ .card-subtitle {
+ font-size: 12px;
+ color: #909399;
+ font-weight: normal;
+ }
+}
+
+.chart-filter-section {
+ padding: 20px;
+ background: #fafbfc;
+ border-bottom: 1px solid #ebeef5;
+ margin-bottom: 0;
+}
+
+.search-row {
+ .filter-item {
+ margin-bottom: 0;
+
+ .filter-label {
+ display: block;
+ font-size: 13px;
+ color: #606266;
+ margin-bottom: 8px;
+ font-weight: 500;
+ }
+
+ &.filter-buttons {
+ display: flex;
+ align-items: flex-end;
+ gap: 10px;
+ padding-top: 28px;
+
+ .el-button {
+ flex: 1;
+ font-size: 14px;
+ }
+ }
+ }
+}
+
+.chart-container {
width: 100%;
overflow: hidden;
+ position: relative;
+ padding: 20px;
+ background: #fff;
+
+ .chart-wrapper {
+ width: 100%;
+ height: 420px;
+ min-width: 0;
+ }
}
-.chart-wrapper {
- width: 100%;
- height: 360px;
- min-width: 0;
+
+.table-card {
+ :deep(.el-table) {
+ border-radius: 8px;
+ overflow: hidden;
+ }
+
+ :deep(.el-table__header-wrapper) {
+ .el-table__header {
+ th {
+ background: #f5f7fa;
+ color: #606266;
+ font-weight: 600;
+ }
+ }
+ }
+
+ :deep(.el-table__body-wrapper) {
+ .el-table__body {
+ tr:hover {
+ background-color: #f5f7fa;
+ }
+ }
+ }
+}
+
+// 鍝嶅簲寮忚璁�
+@media (max-width: 768px) {
+ .indicator-stats {
+ padding: 12px;
+ }
+
+ .stat-card {
+ padding: 20px;
+
+ .stat-content .stat-value {
+ font-size: 24px;
+ }
+
+ .stat-icon-wrapper .stat-icon {
+ width: 56px;
+ height: 56px;
+ }
+ }
+
+ .chart-filter-section {
+ padding: 16px;
+ }
+
+ .search-row {
+ .filter-item.filter-buttons {
+ padding-top: 0;
+ margin-top: 12px;
+ }
+ }
+
+ .chart-container {
+ padding: 16px;
+
+ .chart-wrapper {
+ height: 320px;
+ }
+ }
+
+ .card-header {
+ .header-left {
+ .card-title {
+ font-size: 15px;
+ }
+
+ .card-subtitle {
+ font-size: 11px;
+ }
+ }
+ }
+}
+
+@media (max-width: 576px) {
+ .page-header {
+ .page-title {
+ font-size: 20px;
+ }
+
+ .page-desc {
+ font-size: 12px;
+ }
+ }
+
+ .stat-card {
+ flex-direction: column;
+ text-align: center;
+
+ .stat-icon-wrapper {
+ margin-right: 0;
+ margin-bottom: 12px;
+ }
+ }
}
</style>
--
Gitblit v1.9.3