Merge branch 'dev_银川_中盛建材' of http://114.132.189.42:9002/r/product-inventory-management into dev_银川_中盛建材
已修改5个文件
381 ■■■■ 文件已修改
src/views/index.vue 355 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/processRoute/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/processRoute/processRouteItem/index.vue 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productionOrder/index.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productionProcess/index.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/index.vue
@@ -2,9 +2,9 @@
  <div class="home-page">
    <div class="top-bar">
      <div class="user-box">
        <!-- <img :src="userStore.avatar"
        <img :src="userStore.avatar"
             class="avatar"
             alt="" /> -->
             alt="" />
        <div>
          <div class="hello">{{ userStore.roleName || "系统管理员" }},你好</div>
          <div class="sub">登录时间:{{ userStore.currentLoginTime }}</div>
@@ -61,33 +61,25 @@
        </section>
        <section class="section-card flex-fill-card">
          <div class="section-title-row">
            <div class="section-title">今日待处理</div>
            <el-radio-group v-model="pendingFilter"
                            size="small">
              <el-radio-button label="all">全部</el-radio-button>
              <el-radio-button label="mine">我的</el-radio-button>
              <el-radio-button label="high">高优先</el-radio-button>
            <div class="section-title">区域销售金额分析</div>
            <el-radio-group v-model="chartProductType2"
                            size="small"
                            @change="fetchSalesAmountChartData">
              <el-radio-button label="板材">板材</el-radio-button>
              <el-radio-button label="砌块">砌块</el-radio-button>
            </el-radio-group>
          </div>
          <div class="task-row"
               v-for="task in filteredPendingTasks"
               :key="task.id">
            <div class="task-left">
              <el-tag size="small"
                      :type="task.type">{{ task.level }}</el-tag>
              <span class="task-title">{{ task.title }}</span>
            </div>
            <el-button link
                       type="primary"
                       @click="goTo(task.path)">去处理</el-button>
          </div>
          <el-empty v-if="filteredPendingTasks.length === 0"
                    description="暂无待处理事项"
                    :image-size="80" />
          <Echarts :chartStyle="chartStyle"
                   :grid="grid"
                   :tooltip="barTooltip"
                   :xAxis="salesAmountXAxis"
                   :yAxis="salesAmountYAxis"
                   :series="salesAmountSeries"
                   style="height: 300px" />
        </section>
      </div>
      <div class="right-col">
        <section class="section-card"
        <!-- <section class="section-card"
                 v-if="isSectionVisible('trendCards')">
          <div class="section-title">最近7天关键指标趋势</div>
          <div class="trend-cards">
@@ -111,7 +103,7 @@
              </div>
            </div>
          </div>
        </section>
        </section> -->
        <section class="section-card"
                 v-if="isSectionVisible('planTrend')">
          <div class="section-title-row">
@@ -137,34 +129,25 @@
             v-if="isSectionVisible('qualityChart') || isSectionVisible('costChart')">
          <section class="section-card"
                   v-if="isSectionVisible('qualityChart')">
            <div class="section-title-row">
              <div class="section-title">质检异常分布</div>
              <el-radio-group v-model="chartRangeQuality"
                              size="small"
                              @change="loadQualityData">
                <el-radio-button :label="1">周</el-radio-button>
                <el-radio-button :label="2">月</el-radio-button>
                <el-radio-button :label="3">季度</el-radio-button>
              </el-radio-group>
            </div>
            <div class="section-title">今年能耗用量趋势</div>
            <Echarts :chartStyle="chartStyle"
                     :grid="grid"
                     :tooltip="barTooltip"
                     :xAxis="qualityXAxis"
                     :xAxis="energyConsumptionXAxis"
                     :yAxis="valueYAxis"
                     :series="qualitySeries"
                     :series="energyConsumptionSeries"
                     style="height: 260px" />
          </section>
          <section class="section-card"
                   v-if="isSectionVisible('costChart')">
            <div class="section-title">能耗类型占比</div>
            <div class="section-title">今年能耗类型占比</div>
            <Echarts :chartStyle="chartStyle"
                     :tooltip="pieTooltip"
                     :series="energyTypeSeries"
                     style="height: 260px" />
          </section>
        </div>
        <section class="section-card"
        <!-- <section class="section-card"
                 v-if="isSectionVisible('warningCenter')">
          <div class="section-title">异常预警中心</div>
          <div class="warning-row"
@@ -182,42 +165,31 @@
          <el-empty v-if="warningList.length === 0"
                    description="暂无异常预警"
                    :image-size="80" />
        </section>
        </section> -->
        <section class="section-card mini-table-wrap"
                 v-if="isSectionVisible('planTable')">
          <div class="section-title">生产计划执行明细</div>
          <div class="section-title">最近报工</div>
          <el-table :data="planTable"
                    size="small"
                    stripe>
            <el-table-column prop="planNo"
                             label="计划单号"
                             label="班次"
                             min-width="150" />
            <el-table-column prop="product"
                             label="产品"
                             label="创建人"
                             min-width="120" />
            <el-table-column prop="product"
                             label="报工时间"
                             min-width="120" />
            <el-table-column prop="qty"
                             label="计划量"
                             label="产品"
                             min-width="90" />
            <el-table-column prop="issued"
                             label="已下发"
                             label="生产数量"
                             min-width="90" />
            <el-table-column prop="status"
                             label="状态"
                             min-width="100" />
            <el-table-column label="操作"
                             min-width="120">
              <template #default="{ row }">
                <el-button link
                           type="primary"
                           @click="goTo(routePathMap.plan)">查看</el-button>
                <el-button v-if="row.status !== '已完成'"
                           link
                           type="success"
                           @click="goTo(routePathMap.dispatch)">
                  下发
                </el-button>
              </template>
            </el-table-column>
            <el-table-column prop="issued"
                             label="合格数量"
                             min-width="90" />
          </el-table>
        </section>
      </div>
@@ -298,6 +270,8 @@
    qualityInspectionStatistics,
    nonComplianceWarning,
  } from "@/api/viewIndex.js";
  import { energyConsumptionDetailStatistics } from "@/api/energyManagement/energyType";
  import { getSalesAmountAnalysis } from "@/api/reportAnalysis/salesStatistics";
  const router = useRouter();
  const userStore = useUserStore();
@@ -566,6 +540,149 @@
    },
  ]);
  // 能耗用量趋势图表
  const energyConsumptionXAxis = reactive({
    type: "category",
    data: [],
    axisLabel: {
      rotate: 45,
    },
  });
  const energyConsumptionSeries = reactive([
    {
      name: "用水量",
      type: "bar",
      data: [],
      itemStyle: { color: "#409EFF" },
    },
    {
      name: "用电量",
      type: "bar",
      data: [],
      itemStyle: { color: "#E6A23C" },
    },
    {
      name: "用气量",
      type: "bar",
      data: [],
      itemStyle: { color: "#67C23A" },
    },
  ]);
  // 销售金额图表
  const chartProductType2 = ref("砌块");
  const salesAmountChartData = ref({
    dates: [],
    customerTrends: [],
  });
  const salesAmountXAxis = reactive({
    type: "value",
    axisLabel: {
      interval: "auto",
      formatter: value => {
        // 格式化金额,显示为更易读的形式
        if (value >= 10000) {
          return (value / 10000).toFixed(0) + "万";
        }
        return value;
      },
    },
    axisTick: {
      interval: "auto",
    },
  });
  const salesAmountYAxis = reactive({
    type: "category",
    data: [],
    axisLabel: {
      rotate: 0,
    },
  });
  const salesAmountSeries = reactive([]);
  // 获取销售金额分析图表数据
  const fetchSalesAmountChartData = async () => {
    try {
      const response = await getSalesAmountAnalysis({
        type: chartProductType2.value,
        days: "年", // 默认年
      });
      if (response?.data) {
        salesAmountChartData.value = response.data;
        updateSalesAmountChart();
      }
    } catch (error) {
      console.error("获取销售金额分析图表数据失败:", error);
      // 使用模拟数据
      salesAmountChartData.value = {
        dates: [
          "2026-01-01",
          "2025-01-01",
          "2024-01-01",
          "2023-01-01",
          "2022-01-01",
        ],
        customerTrends: [
          { 内蒙古: 100, 银川: 200, 自提: 300, 其他: 150, 全部: 750 },
          { 内蒙古: 80, 银川: 180, 自提: 280, 其他: 130, 全部: 670 },
          { 内蒙古: 90, 银川: 190, 自提: 290, 其他: 140, 全部: 710 },
          { 内蒙古: 70, 银川: 170, 自提: 270, 其他: 120, 全部: 630 },
          { 内蒙古: 110, 银川: 210, 自提: 310, 其他: 160, 全部: 790 },
        ],
      };
      updateSalesAmountChart();
    }
  };
  // 更新销售金额图表
  const updateSalesAmountChart = () => {
    const { customerTrends = [] } = salesAmountChartData.value;
    // 计算每个销售区域的总销售额(过滤掉"全部")
    const areaTotalMap = new Map();
    customerTrends.forEach(item => {
      Object.keys(item).forEach(key => {
        // 过滤掉"全部"销售区域
        if (key !== "全部") {
          const value = item[key] || 0;
          if (areaTotalMap.has(key)) {
            areaTotalMap.set(key, areaTotalMap.get(key) + value);
          } else {
            areaTotalMap.set(key, value);
          }
        }
      });
    });
    // 转换为数组
    const salesAreas = Array.from(areaTotalMap.keys());
    const colors = [
      "#00A4ED",
      "#34D8F7",
      "#4A8BFF",
      "#8A6BFF",
      "#C8C447",
      "#FF6B6B",
    ];
    // 更新Y轴数据(现在是销售区域)
    salesAmountYAxis.data = salesAreas;
    // 更新系列数据(每个销售区域的总销售额)
    salesAmountSeries.splice(0, salesAmountSeries.length);
    salesAmountSeries.push({
      name: "销售金额",
      data: salesAreas.map(area => areaTotalMap.get(area)),
      type: "bar",
      itemStyle: { color: "#00A4ED" },
    });
  };
  // 模拟能耗数据
  const energyData = reactive({
    water: 120,
@@ -573,28 +690,87 @@
    gas: 80,
  });
  // 更新能耗类型占比图表
  // 更新能耗类型占比图表和能耗用量趋势图表
  const updateEnergyTypeChart = () => {
    const { water, electricity, gas } = energyData;
    const total = water + electricity + gas;
    // 构建参数:今年的年初到年末以及天数
    const currentYear = new Date().getFullYear();
    const params = {
      startDate: `${currentYear}-01-01`,
      endDate: `${currentYear}-12-31`,
      days: 365,
      state: "年",
    };
    energyTypeSeries[0].data = [
      {
        value: total > 0 ? ((water / total) * 100).toFixed(2) : 0,
        name: "水",
        itemStyle: { color: "#409EFF" },
      },
      {
        value: total > 0 ? ((electricity / total) * 100).toFixed(2) : 0,
        name: "电",
        itemStyle: { color: "#E6A23C" },
      },
      {
        value: total > 0 ? ((gas / total) * 100).toFixed(2) : 0,
        name: "气",
        itemStyle: { color: "#F56C6C" },
      },
    ];
    // 调用接口获取数据
    energyConsumptionDetailStatistics(params)
      .then(res => {
        if (res.code === 200) {
          const data = res.data;
          // 处理能耗类型占比数据
          const energyTypeData = data.energyCostDtos || [];
          // 计算各能耗类型的总消耗量
          let total = 0;
          const typeMap = {
            水: 0,
            电: 0,
            气: 0,
          };
          // 准备能耗用量趋势图表数据
          const dates = [];
          const waterConsumptionData = [];
          const electricityConsumptionData = [];
          const gasConsumptionData = [];
          energyTypeData.forEach(item => {
            // 收集日期和各能耗类型数据
            if (item.meterReadingDate) {
              dates.push(item.meterReadingDate);
              waterConsumptionData.push(item.waterConsumption || 0);
              electricityConsumptionData.push(item.electricityConsumption || 0);
              gasConsumptionData.push(item.gasConsumption || 0);
            }
            // 计算总消耗量
            if (item.waterConsumption)
              typeMap.水 += Number(item.waterConsumption);
            if (item.electricityConsumption)
              typeMap.电 += Number(item.electricityConsumption);
            if (item.gasConsumption) typeMap.气 += Number(item.gasConsumption);
          });
          total = typeMap.水 + typeMap.电 + typeMap.气;
          // 更新能耗类型占比图表数据
          energyTypeSeries[0].data = [
            {
              value: total > 0 ? ((typeMap.水 / total) * 100).toFixed(2) : 0,
              name: "水",
              itemStyle: { color: "#409EFF" },
            },
            {
              value: total > 0 ? ((typeMap.电 / total) * 100).toFixed(2) : 0,
              name: "电",
              itemStyle: { color: "#E6A23C" },
            },
            {
              value: total > 0 ? ((typeMap.气 / total) * 100).toFixed(2) : 0,
              name: "气",
              itemStyle: { color: "#F56C6C" },
            },
          ];
          // 更新能耗用量趋势图表数据
          energyConsumptionXAxis.data = dates;
          energyConsumptionSeries[0].data = waterConsumptionData;
          energyConsumptionSeries[1].data = electricityConsumptionData;
          energyConsumptionSeries[2].data = gasConsumptionData;
        }
      })
      .catch(err => {
        console.error("获取能耗数据异常:", err);
      });
  };
  const planTable = reactive([]);
@@ -1030,19 +1206,20 @@
  };
  const refreshDashboardData = () => {
    loadHomeTodos();
    loadOrderAndProgress();
    loadPlanTrend();
    loadQualityData();
    loadCostComposition();
    loadWarningCenter();
    // loadHomeTodos();
    // loadOrderAndProgress();
    // loadPlanTrend();
    // loadQualityData();
    // loadCostComposition();
    // loadWarningCenter();
    updateEnergyTypeChart();
    fetchSalesAmountChartData();
    lastUpdatedAt.value = new Date().toLocaleString();
  };
  onMounted(() => {
    // initSectionConfig();
    // refreshDashboardData();
    refreshDashboardData();
  });
</script>
src/views/productionManagement/processRoute/index.vue
@@ -247,6 +247,7 @@
        bomId: row.bomId || null,
        description: row.description || "",
        type: "route",
        status: row.status || false,
      },
    });
  };
src/views/productionManagement/processRoute/processRouteItem/index.vue
@@ -47,13 +47,15 @@
         class="section-header">
      <div class="section-title">工艺路线项目列表</div>
      <div class="section-actions">
        <div class="sort-tip">拖拽表格排序</div>
        <div v-if="!routeInfo.status"
             class="sort-tip">拖拽表格排序</div>
        <el-button icon="Grid"
                   @click="toggleView"
                   style="margin-right: 10px;">
          卡片视图
        </el-button>
        <el-button type="primary"
        <el-button v-if="!routeInfo.status"
                   type="primary"
                   @click="handleAdd">新增</el-button>
      </div>
    </div>
@@ -97,6 +99,7 @@
        </template>
      </el-table-column>
      <el-table-column label="操作"
                       v-if="!routeInfo.status"
                       align="center"
                       fixed="right"
                       width="150">
@@ -119,13 +122,15 @@
      <div class="section-header">
        <div class="section-title">工艺路线项目列表</div>
        <div class="section-actions">
          <div class="sort-tip">长按拖拽卡片排序</div>
          <div v-if="!routeInfo.status"
               class="sort-tip">长按拖拽卡片排序</div>
          <el-button icon="Menu"
                     @click="toggleView"
                     style="margin-right: 10px;">
            表格视图
          </el-button>
          <el-button type="primary"
                     v-if="!routeInfo.status"
                     @click="handleAdd">新增</el-button>
        </div>
      </div>
@@ -150,6 +155,7 @@
              <el-button type="primary"
                         link
                         size="small"
                         v-if="!routeInfo.status"
                         @click="handleEdit(item)"
                         :disabled="item.isComplete">编辑</el-button>
              <el-button type="info"
@@ -159,6 +165,7 @@
              <el-button type="danger"
                         link
                         size="small"
                         v-if="!routeInfo.status"
                         @click="handleDelete(item)"
                         :disabled="item.isComplete">删除</el-button>
            </div>
@@ -262,7 +269,7 @@
                      <span v-else>{{ row.unit }}</span>
                    </template>
                  </el-table-column>
                   <el-table-column prop="unitPrice"
                  <el-table-column prop="unitPrice"
                                   label="单价">
                    <template #default="{ row }">
                      <el-form-item v-if="bomDataValue.isEdit"
@@ -541,6 +548,7 @@
      dictLabel: route.query.dictLabel || "",
      bomId: route.query.bomId || null,
      description: route.query.description || "",
      status: route.query.status === "true" ? true : false,
    };
    if (pageType.value === "order") {
      queryList2(route.query.orderId)
src/views/productionManagement/productionOrder/index.vue
@@ -212,7 +212,7 @@
                  </div>
                  <div class="info-item">
                    <div class="info-label">已下发方数</div>
                    <div class="info-value">{{ item.assignedQuantity ? `${item.assignedQuantity}` : 0 }}<span style="color:rgba(214, 134, 22, 0.76)"> 方</span></div>
                    <div class="info-value">{{ item.totalAssignedQuantity ? `${item.totalAssignedQuantity}` : 0 }}<span style="color:rgba(214, 134, 22, 0.76)"> 方</span></div>
                  </div>
                  <div class="info-item">
                    <div class="info-label">尺寸</div>
@@ -539,7 +539,7 @@
    },
    {
      label: "已下发方数",
      prop: "assignedQuantity",
      prop: "totalAssignedQuantity",
      width: "150px",
      className: "spec-cell",
      formatData: cell => (cell ? `${cell}方` : 0),
@@ -870,6 +870,7 @@
                  volume: plan.volume,
                  status: plan.status,
                  assignedQuantity: plan.assignedQuantity,
                  totalAssignedQuantity: plan.totalAssignedQuantity,
                  length: plan.length,
                  width: plan.width,
                  height: plan.height,
src/views/productionManagement/productionProcess/index.vue
@@ -492,8 +492,8 @@
      label: "参数模式",
      prop: "valueMode",
      dataType: "tag",
      formatType: row => (row.valueMode === "1" ? "success" : "warning"),
      formatData: row => (row.valueMode === "1" ? "单值" : "区间"),
      formatType: row => (row == "1" ? "success" : "warning"),
      formatData: row => (row == "1" ? "单值" : "区间"),
    },
    {
      label: "参数类型",