e0699ce1a404b1d819d7ef0b40cfd2631bb964d1..f3b97d08e13224c6bc1d4f267bdb1a4e0b3690c3
23 小时以前 zhangwencui
参数配置页面开发(未接接口)
f3b97d 对比 | 目录
昨天 zhangwencui
.
881f12 对比 | 目录
昨天 zhangwencui
Merge branch 'dev_银川_中盛建材' of http://114.132.189.42:9002/r/product-inventor...
37231c 对比 | 目录
昨天 zhangwencui
Merge branch 'dev_银川_中盛建材' of http://114.132.189.42:9002/r/product-inventor...
739f25 对比 | 目录
昨天 gongchunyi
fix: 产品规格字段调整
360001 对比 | 目录
昨天 zhangwencui
字段展示修改
bbfdcd 对比 | 目录
昨天 zss
Merge remote-tracking branch 'origin/dev_银川_中盛建材' into dev_银川_中盛建材
f11f38 对比 | 目录
昨天 zss
样式调整
6e54a8 对比 | 目录
昨天 zhangwencui
Merge branch 'dev_银川_中盛建材' of http://114.132.189.42:9002/r/product-inventor...
40fcbc 对比 | 目录
昨天 zhangwencui
数据来源字段显示调整
051e4f 对比 | 目录
昨天 zss
Merge remote-tracking branch 'origin/dev_银川_中盛建材' into dev_银川_中盛建材
ce8295 对比 | 目录
昨天 zss
能耗统计调整
a740b3 对比 | 目录
昨天 zhangwencui
Merge branch 'dev_银川_中盛建材' of http://114.132.189.42:9002/r/product-inventor...
72d156 对比 | 目录
昨天 zhangwencui
产品需求量统计页面数据加单位、加合计行、加搜索
e526b1 对比 | 目录
昨天 gongchunyi
Merge branch 'dev_银川_中盛建材' of http://114.132.189.42:9002/r/product-inventor...
f1a2de 对比 | 目录
昨天 gongchunyi
fix: 数据来源字段显示调整
167c4d 对比 | 目录
昨天 zhangwencui
生产维护树形结构加载慢改成懒加载
4fef2b 对比 | 目录
昨天 zhangwencui
问题修改
044596 对比 | 目录
昨天 zhangwencui
图标变更
150e35 对比 | 目录
昨天 zhangwencui
打包图片变更
c02537 对比 | 目录
已添加5个文件
已修改8个文件
已删除2个文件
1351 ■■■■■ 文件已修改
multiple/assets/favicon/PCDZico.ico 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/favicon/ZSJCLogo.ico 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/logo/PCDZLogo.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/logo/ZSJCLogo.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/config.json 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/favicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
src/api/basicData/newProduct.js 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/basicData/parameterMaintenance.js 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/logo/宁夏中盛建材科技有限公司.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicData/parameterMaintenance/index.vue 836 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicData/product/index.vue 165 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/energyManagement/energyConsumptionStatistical/index.vue 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionPlan/productionPlan/index.vue 143 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionPlan/summaryByProduct/index.vue 91 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vite.config.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/favicon/PCDZico.ico
Binary files differ
multiple/assets/favicon/ZSJCLogo.ico
multiple/assets/logo/PCDZLogo.png
Binary files differ
multiple/assets/logo/ZSJCLogo.png
multiple/config.json
@@ -4,20 +4,20 @@
      "VITE_APP_TITLE": "芯导云(管理信息系统)"
    },
    "screen": "screen/PCDZView.png",
    "logo": "logo/PCDZLogo.png",
    "favicon": "favicon/PCDZico.ico"
    "logo": "logo/ZSJCLogo.png",
    "favicon": "favicon/ZSJCLogo.ico"
  },
  "PCDZ": {
  "ZSJC": {
    "env": {
      "VITE_APP_TITLE": "鹏创电子信息管理",
      "VITE_BASE_API": "http://1.15.17.182:9003",
      "VITE_JAVA_API": "http://1.15.17.182:9002"
      "VITE_APP_TITLE": "中盛建材信息管理",
      "VITE_BASE_API": "http://1.15.17.182:9019",
      "VITE_JAVA_API": "http://1.15.17.182:9018"
    },
    "screen": "screen/PCDZView.png",
    "logo": "logo/PCDZLogo.png",
    "favicon": "favicon/PCDZico.ico"
    "logo": "logo/ZSJCLogo.png",
    "favicon": "favicon/ZSJCLogo.ico"
  },
  "screen": "/src/assets/images/login-background.png",
  "logo": "/src/assets/logo/logo.png",
  "logo": "/src/assets/logo/宁夏中盛建材科技有限公司.png",
  "favicon": "/public/favicon.ico"
}
}
public/favicon.ico

src/api/basicData/newProduct.js
@@ -9,6 +9,14 @@
        params: query
    })
}
// äº§å“æ ‘查询2
export function productTreeListQuery(query) {
    return request({
        url: '/productMaterial/listQuery',
        method: 'get',
        params: query
    })
}
// äº§å“å­ç±»æ–°å¢ž
export function addOrEditProduct(query) {
    return request({
src/api/basicData/parameterMaintenance.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,46 @@
// å‚数维护页面接口
import request from '@/utils/request'
// æŸ¥è¯¢å‚数列表
export function parameterListPage(query) {
    return request({
        url: '/basic/parameter/listPage',
        method: 'get',
        params: query
    })
}
// æ–°å¢žå‚æ•°
export function addParameter(data) {
    return request({
        url: '/basic/parameter/add',
        method: 'post',
        data: data
    })
}
// ç¼–辑参数
export function updateParameter(data) {
    return request({
        url: '/basic/parameter/update',
        method: 'post',
        data: data
    })
}
// åˆ é™¤å‚æ•°
export function delParameter(ids) {
    return request({
        url: '/basic/parameter/del',
        method: 'delete',
        data: Array.isArray(ids) ? ids : [ids]
    })
}
// èŽ·å–äº§å“ç±»åž‹åˆ—è¡¨
export function getProductTypes() {
    return request({
        url: '/basic/product/typeList',
        method: 'get'
    })
}
src/assets/logo/ÄþÏÄÖÐÊ¢½¨²Ä¿Æ¼¼ÓÐÏÞ¹«Ë¾.png
src/views/basicData/parameterMaintenance/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,836 @@
<template>
  <div class="app-container">
    <div class="search_form">
      <div>
        <span class="search_title ml10">参数名称:</span>
        <el-input v-model="searchForm.materialCode"
                  style="width: 200px"
                  placeholder="请输入参数名称"
                  clearable />
        <span class="search_title ml10">关联产品类型:</span>
        <el-input v-model="searchForm.productName"
                  style="width: 200px"
                  placeholder="请输入关联产品类型"
                  clearable />
        <el-button type="primary"
                   @click="handleQuery"
                   style="margin-left: 10px">搜索</el-button>
        <el-button @click="handleReset">重置</el-button>
        <el-button type="primary"
                   @click="handleAdd"
                   style="margin-left: 10px">新增参数</el-button>
        <el-button type="primary"
                   @click="handleProductTypeMaintenance"
                   style="margin-left: 10px">产品类型维护</el-button>
      </div>
    </div>
    <div class="table_list">
      <PIMTable rowKey="materialCode"
                :column="tableColumn"
                :tableData="tableData"
                :page="page"
                height="calc(100vh - 320px)"
                :tableLoading="tableLoading"
                :isSelection="false"
                @pagination="pagination">
      </PIMTable>
    </div>
    <!-- æ–°å¢ž/编辑对话框 -->
    <el-dialog v-model="dialogVisible"
               :title="dialogTitle"
               width="500px">
      <el-form :model="formData"
               :rules="rules"
               ref="formRef"
               label-width="120px">
        <el-form-item label="参数编号"
                      prop="parameterCode">
          <el-input v-model="formData.parameterCode"
                    placeholder="请输入参数编号" />
        </el-form-item>
        <el-form-item label="参数名称"
                      prop="parameterName">
          <el-input v-model="formData.parameterName"
                    placeholder="请输入参数名称" />
        </el-form-item>
        <el-form-item label="参数模式"
                      prop="parameterFormat">
          <el-select v-model="formData.parameterType2"
                     placeholder="请选择参数类型">
            <el-option label="单值"
                       value="1" />
            <el-option label="区间"
                       value="2" />
          </el-select>
        </el-form-item>
        <el-form-item label="参数类型"
                      prop="parameterType">
          <el-select v-model="formData.parameterType"
                     @change="handleParameterTypeChange"
                     placeholder="请选择参数类型">
            <el-option label="数值格式"
                       value="数值格式" />
            <el-option label="文本格式"
                       value="文本格式" />
            <el-option label="下拉选项"
                       value="下拉选项" />
            <el-option label="时间格式"
                       value="时间格式" />
          </el-select>
        </el-form-item>
        <el-form-item v-if="formData.parameterType === '下拉选项'"
                      label="数据字典"
                      prop="parameterFormat">
          <el-select v-model="formData.parameterFormat"
                     placeholder="请选择数据字典">
            <el-option v-for="item in dictTypes"
                       :key="item.dictType"
                       :label="item.dictName"
                       :value="item.dictType" />
          </el-select>
        </el-form-item>
        <el-form-item v-else-if="formData.parameterType === '时间格式'"
                      label="时间格式"
                      prop="parameterFormat">
          <el-select v-model="formData.parameterFormat"
                     placeholder="请选择时间格式">
            <el-option label="YYYY-MM-DD HH:mm:ss"
                       value="YYYY-MM-DD HH:mm:ss" />
            <el-option label="YYYY-MM-DD"
                       value="YYYY-MM-DD" />
          </el-select>
        </el-form-item>
        <el-form-item v-else
                      label="参数格式"
                      prop="parameterFormat">
          <el-input v-model="formData.parameterFormat"
                    placeholder="请输入参数格式" />
        </el-form-item>
        <el-form-item label="关联产品类型"
                      prop="parameterValue">
          <el-select v-model="formData.parameterValue"
                     placeholder="请选择关联产品类型">
            <el-option v-for="item in productTypes"
                       :key="item.value"
                       :label="item.label"
                       :value="item.value" />
          </el-select>
        </el-form-item>
        <el-form-item label="标准值"
                      v-if="formData.parameterType2 === '1'"
                      prop="standardValue">
          <el-input v-model="formData.standardValue"
                    placeholder="请输入标准值" />
        </el-form-item>
        <el-form-item label="最大值"
                      v-if="formData.parameterType2 === '2'"
                      prop="standardValue">
          <el-input v-model="formData.standardValue"
                    placeholder="请输入标准值" />
        </el-form-item>
        <el-form-item label="最小值"
                      v-if="formData.parameterType2 === '2'"
                      prop="standardValue">
          <el-input v-model="formData.standardValue"
                    placeholder="请输入标准值" />
        </el-form-item>
        <el-form-item label="单位"
                      prop="unit">
          <el-input v-model="formData.unit"
                    placeholder="请输入单位" />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="dialogVisible = false">取消</el-button>
          <el-button type="primary"
                     @click="handleSubmit">确定</el-button>
        </span>
      </template>
    </el-dialog>
    <!-- äº§å“ç±»åž‹ç»´æŠ¤å¯¹è¯æ¡† -->
    <el-dialog v-model="productTypeDialogVisible"
               title="产品类型维护"
               width="600px">
      <div class="product-type-header">
        <el-button type="primary"
                   @click="handleAddProductType">新增产品类型</el-button>
      </div>
      <el-table :data="productTypeList"
                border
                style="width: 100%; margin-top: 10px; margin-bottom: 20px">
        <!-- <el-table-column prop="typeCode"
                         label="类型编码"
                         width="150" /> -->
        <el-table-column prop="typeName"
                         label="类型名称" />
        <el-table-column label="操作"
                         width="150">
          <template #default="scope">
            <el-button link
                       type="primary"
                       @click="handleEditProductType(scope.row)">编辑</el-button>
            <el-button link
                       type="danger"
                       @click="handleDeleteProductType(scope.row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-dialog>
    <!-- æ–°å¢ž/编辑产品类型对话框 -->
    <el-dialog v-model="productTypeFormVisible"
               :title="productTypeDialogTitle"
               width="400px">
      <el-form :model="productTypeForm"
               :rules="productTypeRules"
               ref="productTypeFormRef"
               label-width="100px">
        <!-- <el-form-item label="类型编码"
                      prop="typeCode">
          <el-input v-model="productTypeForm.typeCode"
                    placeholder="请输入类型编码" />
        </el-form-item> -->
        <el-form-item label="类型名称"
                      prop="typeName">
          <el-input v-model="productTypeForm.typeName"
                    placeholder="请输入类型名称" />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="productTypeFormVisible = false">取消</el-button>
          <el-button type="primary"
                     @click="handleProductTypeSubmit">确定</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
  import { onMounted, ref, reactive } from "vue";
  import {
    parameterListPage,
    addParameter,
    updateParameter,
    delParameter,
    getProductTypes as getProductTypesApi,
  } from "@/api/basicData/parameterMaintenance.js";
  import { listType } from "@/api/system/dict/type";
  import PIMTable from "@/components/PIMTable/PIMTable.vue";
  import { ElMessage, ElMessageBox } from "element-plus";
  const tableColumn = ref([
    {
      label: "参数编号",
      prop: "parameterCode",
      className: "code-cell",
    },
    {
      label: "参数名称",
      prop: "parameterName",
    },
    {
      label: "参数模式",
      prop: "parameterType2",
    },
    {
      label: "参数类型",
      prop: "parameterType",
      dataType: "tag",
      formatType: params => {
        const typeMap = {
          æ•°å€¼æ ¼å¼: "primary",
          æ–‡æœ¬æ ¼å¼: "info",
          ä¸‹æ‹‰é€‰é¡¹: "warning",
          æ—¶é—´æ ¼å¼: "success",
        };
        return typeMap[params] || "default";
      },
    },
    {
      label: "参数格式",
      prop: "parameterFormat",
    },
    {
      label: "关联产品类型",
      prop: "parameterValue",
    },
    {
      label: "标准值",
      prop: "standardValue",
      className: row => {
        return row.parameterType == "数值格式" ? "quantity-cell" : "";
      },
    },
    {
      label: "最大值",
      prop: "standardValue",
      className: row => {
        return row.parameterType == "数值格式" ? "quantity-cell" : "";
      },
    },
    {
      label: "最小值",
      prop: "standardValue",
      className: row => {
        return row.parameterType == "数值格式" ? "quantity-cell" : "";
      },
    },
    {
      label: "单位",
      prop: "unit",
    },
    {
      label: "操作",
      dataType: "action",
      width: "150",
      operation: [
        {
          name: "编辑",
          clickFun: row => {
            handleEdit(row);
          },
        },
        {
          name: "删除",
          clickFun: row => {
            handleDelete(row);
          },
        },
      ],
    },
  ]);
  const tableData = ref([]);
  const tableLoading = ref(false);
  const page = reactive({
    current: 1,
    size: 10,
    total: 0,
  });
  // æœç´¢è¡¨å•
  const searchForm = reactive({
    materialCode: "",
    productName: "",
  });
  // å¯¹è¯æ¡†ç›¸å…³
  const dialogVisible = ref(false);
  const dialogTitle = ref("");
  const formRef = ref(null);
  const formData = reactive({
    parameterCode: "",
    parameterName: "",
    parameterType2: "1",
    parameterType: "",
    parameterFormat: "",
    parameterValue: "",
    standardValue: "",
    unit: "",
  });
  const rules = reactive({
    parameterCode: [
      { required: true, message: "请输入参数编号", trigger: "blur" },
    ],
    parameterName: [
      { required: true, message: "请输入参数名称", trigger: "blur" },
    ],
    parameterType: [
      { required: true, message: "请选择参数类型", trigger: "change" },
    ],
    parameterFormat: [
      { required: true, message: "请选择参数格式", trigger: "change" },
    ],
    parameterValue: [
      { required: true, message: "请选择关联产品类型", trigger: "change" },
    ],
    standardValue: [{ required: true, message: "请输入标准值", trigger: "blur" }],
    unit: [{ required: true, message: "请输入单位", trigger: "blur" }],
  });
  const productTypes = ref([]);
  const isEdit = ref(false);
  // äº§å“ç±»åž‹ç»´æŠ¤ç›¸å…³
  const productTypeDialogVisible = ref(false);
  const productTypeFormVisible = ref(false);
  const productTypeDialogTitle = ref("");
  const productTypeFormRef = ref(null);
  const productTypeList = ref([]);
  const productTypeForm = reactive({
    id: null,
    // typeCode: "",
    typeName: "",
  });
  const productTypeRules = reactive({
    // typeCode: [{ required: true, message: "请输入类型编码", trigger: "blur" }],
    typeName: [{ required: true, message: "请输入类型名称", trigger: "blur" }],
  });
  const isProductTypeEdit = ref(false);
  const handleParameterTypeChange = () => {
    if (formData.parameterType === "数值格式") {
      formData.parameterFormat = "#.0000";
    } else if (formData.parameterType === "时间格式") {
      formData.parameterFormat = "YYYY-MM-DD HH:mm:ss";
    } else {
      formData.parameterFormat = "";
    }
  };
  // äº§å“ç±»åž‹ç»´æŠ¤æŒ‰é’®ç‚¹å‡»äº‹ä»¶
  const handleProductTypeMaintenance = () => {
    productTypeDialogVisible.value = true;
    getProductTypeList();
  };
  // èŽ·å–äº§å“ç±»åž‹åˆ—è¡¨
  const getProductTypeList = () => {
    productTypeList.value = [
      { id: 1, typeCode: "TYPE001", typeName: "3.5砌块" },
      { id: 2, typeCode: "TYPE002", typeName: "5.0砌块" },
      { id: 3, typeCode: "TYPE003", typeName: "板材" },
    ];
  };
  // æ–°å¢žäº§å“ç±»åž‹
  const handleAddProductType = () => {
    isProductTypeEdit.value = false;
    productTypeDialogTitle.value = "新增产品类型";
    productTypeForm.id = null;
    productTypeForm.typeCode = "";
    productTypeForm.typeName = "";
    productTypeFormVisible.value = true;
  };
  // ç¼–辑产品类型
  const handleEditProductType = row => {
    isProductTypeEdit.value = true;
    productTypeDialogTitle.value = "编辑产品类型";
    productTypeForm.id = row.id;
    productTypeForm.typeCode = row.typeCode;
    productTypeForm.typeName = row.typeName;
    productTypeFormVisible.value = true;
  };
  // åˆ é™¤äº§å“ç±»åž‹
  const handleDeleteProductType = row => {
    ElMessageBox.confirm("确定要删除该产品类型吗?", "提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
    })
      .then(() => {
        ElMessage.success("删除成功");
        getProductTypeList();
      })
      .catch(() => {});
  };
  // æäº¤äº§å“ç±»åž‹è¡¨å•
  const handleProductTypeSubmit = () => {
    productTypeFormRef.value.validate(valid => {
      if (valid) {
        ElMessage.success(isProductTypeEdit.value ? "编辑成功" : "新增成功");
        productTypeFormVisible.value = false;
        getProductTypeList();
      }
    });
  };
  // æŸ¥è¯¢åˆ—表
  /** æœç´¢æŒ‰é’®æ“ä½œ */
  const handleQuery = () => {
    page.current = 1;
    getList();
  };
  /** é‡ç½®æŒ‰é’®æ“ä½œ */
  const handleReset = () => {
    searchForm.materialCode = "";
    searchForm.productName = "";
    page.current = 1;
    getList();
  };
  const pagination = obj => {
    page.current = obj.page;
    page.size = obj.limit;
    getList();
  };
  const getList = () => {
    tableLoading.value = true;
    // æ³¨é‡ŠæŽ‰API调用,使用假数据
    /*const params = { ...searchForm, ...page };
                                                                    parameterListPage(params)
                                                                      .then(res => {
                                                                        tableLoading.value = false;
                                                                        tableData.value = res.data;
                                                                        page.total = res.total || 0;
                                                                      })
                                                                      .catch(() => {
                                                                        tableLoading.value = false;
                                                                      });*/
    // å‡æ•°æ®
    setTimeout(() => {
      tableLoading.value = false;
      tableData.value = [
        {
          id: 1,
          parameterCode: "PARAM001",
          parameterName: "长度",
          parameterType2: "1",
          parameterType: "数值格式",
          parameterFormat: "",
          parameterValue: "type1",
          standardValue: "100",
          unit: "mm",
        },
        {
          id: 2,
          parameterCode: "PARAM002",
          parameterName: "温度",
          parameterType2: "2",
          parameterType: "数值格式",
          parameterFormat: "",
          parameterValue: "type1",
          standardValue: "25",
          unit: "℃",
        },
        {
          id: 3,
          parameterCode: "PARAM003",
          parameterName: "颜色",
          parameterType2: "1",
          parameterType: "文本格式",
          parameterFormat: "",
          parameterValue: "type2",
          standardValue: "红色",
          unit: "",
        },
        {
          id: 4,
          parameterCode: "PARAM004",
          parameterName: "状态",
          parameterType2: "1",
          parameterType: "下拉选项",
          parameterFormat: "status",
          parameterValue: "type3",
          standardValue: "正常",
          unit: "",
        },
        {
          id: 5,
          parameterCode: "PARAM005",
          parameterName: "创建时间",
          parameterType2: "1",
          parameterType: "时间格式",
          parameterFormat: "YYYY-MM-DD HH:mm:ss",
          parameterValue: "type2",
          standardValue: "2024-01-01 00:00:00",
          unit: "",
        },
      ];
      page.total = 5;
    }, 500);
  };
  // èŽ·å–äº§å“ç±»åž‹åˆ—è¡¨
  const getProductTypes = () => {
    // æ³¨é‡ŠæŽ‰API调用,使用假数据
    /*getProductTypesApi()
                                                                      .then(res => {
                                                                        productTypes.value = res.data || [];
                                                                      })
                                                                      .catch(() => {
                                                                        // å¤±è´¥æ—¶ä½¿ç”¨æ¨¡æ‹Ÿæ•°æ®
                                                                        productTypes.value = [
                                                                          { label: "3.5砌块", value: "type1" },
                                                                          { label: "5.0砌块", value: "type2" },
                                                                          { label: "板材", value: "type3" },
                                                                        ];
                                                                      });*/
    // å‡æ•°æ®
    productTypes.value = [
      { label: "3.5砌块", value: "type1" },
      { label: "5.0砌块", value: "type2" },
      { label: "板材", value: "type3" },
    ];
  };
  // æ–°å¢žæŒ‰é’®ç‚¹å‡»äº‹ä»¶
  const handleAdd = () => {
    isEdit.value = false;
    dialogTitle.value = "新增参数";
    // é‡ç½®è¡¨å•
    formData.parameterCode = "";
    formData.parameterName = "";
    formData.parameterType2 = "1";
    formData.parameterType = "";
    formData.parameterFormat = "";
    formData.parameterValue = "";
    formData.standardValue = "";
    formData.unit = "";
    dialogVisible.value = true;
  };
  // ç¼–辑按钮点击事件
  const handleEdit = row => {
    isEdit.value = true;
    dialogTitle.value = "编辑参数";
    // å¡«å……表单数据
    formData.parameterCode = row.parameterCode;
    formData.parameterName = row.parameterName;
    formData.parameterType2 = row.parameterType2 || "1";
    formData.parameterType = row.parameterType;
    formData.parameterFormat = row.parameterFormat;
    formData.parameterValue = row.parameterValue;
    formData.standardValue = row.standardValue;
    formData.unit = row.unit;
    dialogVisible.value = true;
  };
  // åˆ é™¤æŒ‰é’®ç‚¹å‡»äº‹ä»¶
  const handleDelete = row => {
    ElMessageBox.confirm("确定要删除这条数据吗?", "提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
    })
      .then(() => {
        // æ³¨é‡ŠæŽ‰API调用,使用假数据
        /*delParameter(row.id)
                                                                      .then(res => {
                                                                        ElMessage.success("删除成功");
                                                                        getList();
                                                                      })
                                                                      .catch(() => {
                                                                        ElMessage.error("删除失败");
                                                                      });*/
        // å‡æ•°æ®æ¨¡æ‹Ÿ
        ElMessage.success("删除成功");
        getList();
      })
      .catch(() => {
        // å–消删除
      });
  };
  // æäº¤è¡¨å•
  const handleSubmit = () => {
    formRef.value.validate(valid => {
      if (valid) {
        // æ³¨é‡ŠæŽ‰API调用,使用假数据
        /*const api = isEdit.value ? updateParameter : addParameter;
                                                                      api(formData)
                                                                        .then(res => {
                                                                          ElMessage.success(isEdit.value ? "编辑成功" : "新增成功");
                                                                          dialogVisible.value = false;
                                                                          getList();
                                                                        })
                                                                        .catch(() => {
                                                                          ElMessage.error(isEdit.value ? "编辑失败" : "新增失败");
                                                                        });*/
        // å‡æ•°æ®æ¨¡æ‹Ÿ
        ElMessage.success(isEdit.value ? "编辑成功" : "新增成功");
        dialogVisible.value = false;
        getList();
      } else {
        return false;
      }
    });
  };
  const dictTypes = ref([]);
  const getDictTypes = () => {
    listType({ pageNum: 1, pageSize: 1000 }).then(res => {
      dictTypes.value = res.rows || [];
    });
  };
  onMounted(() => {
    getDictTypes();
    getList();
    getProductTypes();
  });
</script>
<style scoped lang="scss">
  .app-container {
    padding: 24px;
    background-color: #f0f2f5;
    min-height: calc(100vh - 48px);
  }
  .search_form {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 24px;
    padding: 20px;
    background-color: #ffffff;
    border-radius: 6px;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
    transition: all 0.3s ease;
    &:hover {
      box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.08);
    }
    .search_title {
      color: #606266;
      font-size: 14px;
      font-weight: 500;
    }
    .ml10 {
      margin-left: 10px;
    }
  }
  .table_list {
    background-color: #ffffff;
    border-radius: 6px;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
    overflow: hidden;
    height: calc(100vh - 230px);
  }
  :deep(.el-table) {
    border: none;
    border-radius: 6px;
    overflow: hidden;
    box-shadow: 0 4px 16px rgba(102, 126, 234, 0.1);
    .el-table__header-wrapper {
      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
      th {
        background: transparent;
        font-weight: 600;
        // color: #ffffff;
        border-bottom: none;
        padding: 16px 0;
        letter-spacing: 0.5px;
      }
    }
    .el-table__body-wrapper {
      tr {
        transition: all 0.3s ease;
        &:hover {
          background: linear-gradient(
            90deg,
            rgba(102, 126, 234, 0.05) 0%,
            rgba(118, 75, 162, 0.05) 100%
          );
          transform: scale(1.002);
          box-shadow: 0 2px 8px rgba(102, 126, 234, 0.1);
        }
        td {
          border-bottom: 1px solid #f0f0f0;
          padding: 14px 0;
          color: #303133;
        }
      }
      tr.current-row {
        background: linear-gradient(
          90deg,
          rgba(102, 126, 234, 0.08) 0%,
          rgba(118, 75, 162, 0.08) 100%
        );
      }
      // æ•°å€¼å­—段样式
      .quantity-cell,
      .volume-cell,
      .dimension-cell {
        font-weight: 600;
        color: #409eff;
        font-family: "Courier New", monospace;
        text-shadow: 0 1px 2px rgba(64, 158, 255, 0.2);
      }
      // è§„格字段样式
      .spec-cell {
        color: #67c23a;
        font-weight: 500;
        padding: 4px 8px;
        border-radius: 4px;
      }
      // ç¼–码字段样式
      .code-cell {
        color: #e6a23c;
        font-family: "Courier New", monospace;
        font-weight: 500;
        padding: 4px 8px;
        border-radius: 4px;
      }
      // æ—¥æœŸå­—段样式
      .date-cell {
        color: #909399;
        font-style: italic;
      }
    }
    .el-table__empty-block {
      padding: 60px 0;
      background-color: #fafafa;
    }
  }
  .pagination-container {
    display: flex;
    justify-content: flex-end;
    padding: 16px 20px;
    background-color: #ffffff;
    border-top: 1px solid #ebeef5;
    border-radius: 0 0 12px 12px;
  }
  :deep(.el-button) {
    transition: all 0.3s ease;
    &:hover {
      transform: translateY(-1px);
    }
  }
  @media (max-width: 768px) {
    .app-container {
      padding: 16px;
    }
    .search_form {
      flex-direction: column;
      align-items: flex-start;
      gap: 12px;
      .el-form {
        width: 100%;
        .el-form-item {
          width: 100%;
        }
      }
      .el-button {
        margin-right: 12px;
      }
    }
    :deep(.el-table) {
      th,
      td {
        padding: 10px 0;
        font-size: 12px;
      }
    }
  }
</style>
src/views/basicData/product/index.vue
@@ -6,7 +6,7 @@
                  style="width: 210px"
                  placeholder="输入关键字进行搜索"
                  @change="searchFilter"
                  @clear="searchFilter"
                  @clear="searchFilter1"
                  clearable
                  prefix-icon="Search" />
        <el-button type="primary"
@@ -32,8 +32,7 @@
            <div class="custom-tree-node">
              <span class="tree-node-content">
                <el-icon class="tree-icon">
                  <component :is="data.children && data.children.length > 0
                  ? node.expanded ? 'FolderOpened' : 'Folder' : 'Tickets'" />
                  <component :is="node.expanded ? 'FolderOpened' : 'Folder'" />
                </el-icon>
                <span class="tree-node-label">{{ data.label }}</span>
              </span>
@@ -77,7 +76,7 @@
      </div>
    </div>
    <div class="right">
      <div style="margin-bottom: 10px"
      <div style="margin-bottom: 10px; display: flex; align-items: center; gap: 10px"
           v-if="isShowButton">
        <el-button type="primary"
                   @click="openModelDia('add')">
@@ -85,9 +84,18 @@
        </el-button>
        <ImportExcel :product-id="currentId"
                     @uploadSuccess="getModelList" />
        <el-input v-model="specification"
                  placeholder="规格型号"
                  style="width: 150px"
                  clearable
                  @change="getModelList" />
        <el-input v-model="materialCode"
                  placeholder="物料编号"
                  style="width: 150px"
                  clearable
                  @change="getModelList" />
        <el-button type="danger"
                   @click="handleDelete"
                   style="margin-left: 10px"
                   plain>
          åˆ é™¤
        </el-button>
@@ -95,10 +103,11 @@
      <PIMTable rowKey="id"
                :column="tableColumn"
                :tableData="tableData"
                :page="page"
                :isSelection="true"
                :isShowPagination="false"
                @selection-change="handleSelectionChange"
                :tableLoading="tableLoading"></PIMTable>
                :tableLoading="tableLoading"
                @pagination="pagination"></PIMTable>
    </div>
    <el-dialog v-model="productDia"
               title="产品"
@@ -129,6 +138,7 @@
              <el-select v-model="form.inventoryCategoryId"
                         placeholder="请选择存货类别"
                         clearable
                         filterable
                         style="width: 100%">
                <el-option v-for="item in inventoryCategoryList"
                           :key="item.id"
@@ -145,6 +155,7 @@
              <el-select v-model="form.materialTypeId"
                         placeholder="请选择物料类型"
                         clearable
                         filterable
                         style="width: 100%">
                <el-option v-for="item in materialTypeList"
                           :key="item.id"
@@ -206,6 +217,15 @@
                        @keydown.enter.prevent />
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="物料编码:"
                          prop="materialCode">
              <el-input v-model="modelForm.materialCode"
                        placeholder="请输入物料编码"
                        clearable
                        @keydown.enter.prevent />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
@@ -214,6 +234,7 @@
              <el-select v-model="modelForm.supplyType"
                         placeholder="请选择供应方式"
                         clearable
                         filterable
                         style="width: 100%">
                <el-option label="自制"
                           value="自制" />
@@ -280,6 +301,7 @@
    delProductModel,
    modelListPage,
    productTreeList,
    productTreeListQuery,
    addOrEditProductConfig,
    updateOrEditProductConfig,
    delProductConfig,
@@ -305,6 +327,8 @@
  const expandedKeys = ref([]);
  const inventoryCategoryList = ref([]);
  const materialTypeList = ref([]);
  const specification = ref("");
  const materialCode = ref("");
  const getloadData = () => {
    loadData()
@@ -357,6 +381,10 @@
      prop: "specification",
    },
    {
      label: "物料编码",
      prop: "materialCode",
    },
    {
      label: "单位",
      prop: "baseUnit",
    },
@@ -379,6 +407,11 @@
  const tableLoading = ref(false);
  const isShowButton = ref(false);
  const selectedRows = ref([]);
  const page = reactive({
    current: 1,
    size: 10,
    total: 0,
  });
  const data = reactive({
    form: {
@@ -401,11 +434,13 @@
    modelForm: {
      specification: "",
      supplyType: "",
      materialCode: "",
      id: null,
    },
    modelRules: {
      specification: [{ required: true, message: "请输入", trigger: "blur" }],
      supplyType: [{ required: true, message: "请选择", trigger: "change" }],
      materialCode: [{ required: true, message: "请输入", trigger: "blur" }],
    },
    configForm: {
      configName: "",
@@ -424,29 +459,20 @@
  // æŸ¥è¯¢äº§å“æ ‘
  const getProductTreeList = () => {
    treeLoad.value = true;
    productTreeList()
    productTreeList({ type: 2 })
      .then(res => {
        // è½¬æ¢æ–°çš„æ•°æ®æ ¼å¼
        const newList = [];
        expandedKeys.value = [];
        for (const category of res.data) {
          // æ·»åŠ åˆ†ç±»èŠ‚ç‚¹
          // æ·»åŠ åˆ†ç±»èŠ‚ç‚¹ï¼ˆåªè¿”å›žä¸€å±‚æ•°æ®ï¼Œä¸åŒ…å«å­èŠ‚ç‚¹ï¼‰
          const categoryNode = {
            label: category.configName,
            id: category.configId,
            isLeaf: false,
            children: category.materialList.map(item => ({
              id: item.id,
              isLeaf: true,
              label: item.materialName,
              inventoryCategoryId: item.inventoryCategoryId,
              materialTypeId: item.materialTypeId,
              remark: item.remark,
              baseUnit: item.baseUnit,
            })),
            children: [], // åˆå§‹åŒ–为空数组,点击时再加载
          };
          newList.push(categoryNode);
          expandedKeys.value.push(category.configName);
        }
        list.value = newList;
        treeLoad.value = false;
@@ -455,9 +481,64 @@
        treeLoad.value = false;
      });
  };
  const searchFilter1 = () => {
    getProductTreeList();
  };
  // è¿‡æ»¤äº§å“æ ‘
  const searchFilter = () => {
    proxy.$refs.tree.filter(search.value);
    if (!search.value) {
      // å¦‚果搜索关键字为空,重新加载原始数据
      // getProductTreeList();
      return;
    }
    treeLoad.value = true;
    // è°ƒç”¨ productTreeListQuery æŽ¥å£è¿›è¡Œæœç´¢
    productTreeListQuery({ materialName: search.value })
      .then(res => {
        // å¤„理返回的数据
        const newList = [];
        if (res.data && res.data.length > 0) {
          for (const category of res.data) {
            for (const item of list.value) {
              if (item.id == category.configId) {
                item.children = (category.materialList || []).map(item => ({
                  id: item.id,
                  isLeaf: true,
                  label: item.materialName,
                  inventoryCategoryId: item.inventoryCategoryId,
                  materialTypeId: item.materialTypeId,
                  remark: item.remark,
                  baseUnit: item.baseUnit,
                }));
                break;
              }
            }
            // è½¬æ¢æ•°æ®æ ¼å¼
            // const categoryNode = {
            //   label: category.configName,
            //   id: category.configId,
            //   isLeaf: false,
            //   children: (category.materialList || []).map(item => ({
            //     id: item.id,
            //     isLeaf: true,
            //     label: item.materialName,
            //     inventoryCategoryId: item.inventoryCategoryId,
            //     materialTypeId: item.materialTypeId,
            //     remark: item.remark,
            //     baseUnit: item.baseUnit,
            //   })),
            // };
            // newList.push(categoryNode);
          }
        }
        // ä½¿ç”¨ el-tree çš„内置过滤功能搜索
        proxy.$refs.tree.filter(search.value);
        treeLoad.value = false;
      })
      .catch(err => {
        treeLoad.value = false;
      });
  };
  // æ‰“开产品弹框
  const openProDia = (type, data) => {
@@ -508,12 +589,14 @@
    modelForm.value.specification = "";
    modelForm.value.supplyType = "";
    modelForm.value.id = null;
    modelForm.value.materialCode = null;
    if (type === "edit" && data) {
      // ç¼–辑模式,回填数据
      modelForm.value.specification = data.specification || "";
      modelForm.value.supplyType = data.supplyType || "";
      modelForm.value.id = data.skuId || null;
      modelForm.value.materialCode = data.materialCode || null;
    }
  };
  // æäº¤äº§å“åç§°ä¿®æ”¹
@@ -647,8 +730,35 @@
  };
  // é€‰æ‹©äº§å“
  const handleNodeClick = (val, node, el) => {
    // ç‚¹å‡»éžå¶å­èŠ‚ç‚¹æ—¶ï¼Œä¸æ‰§è¡Œä»¥ä¸‹é€»è¾‘
    // ç‚¹å‡»éžå¶å­èŠ‚ç‚¹æ—¶ï¼ŒåŠ è½½å­èŠ‚ç‚¹æ•°æ®
    if (!val.isLeaf) {
      // è°ƒç”¨ productTreeListQuery æŽ¥å£èŽ·å–å­èŠ‚ç‚¹æ•°æ®
      // treeLoad.value = true;
      productTreeListQuery({ materialTypeId: val.id })
        .then(res => {
          // å¤„理返回的数据
          if (res.data && res.data.length > 0) {
            const materialList = res.data[0].materialList || [];
            // è½¬æ¢å­èŠ‚ç‚¹æ•°æ®æ ¼å¼
            const children = materialList.map(item => ({
              id: item.id,
              isLeaf: true,
              label: item.materialName,
              inventoryCategoryId: item.inventoryCategoryId,
              materialTypeId: item.materialTypeId,
              remark: item.remark,
              baseUnit: item.baseUnit,
            }));
            // æ›´æ–°èŠ‚ç‚¹çš„å­èŠ‚ç‚¹
            val.children = children;
            // å±•开节点
            node.expanded = true;
          }
          // treeLoad.value = false;
        })
        .catch(err => {
          // treeLoad.value = false;
        });
      return;
    }
    // åˆ¤æ–­æ˜¯å¦ä¸ºå¶å­èŠ‚ç‚¹
@@ -667,6 +777,7 @@
        const params = {
          materialId: currentId.value,
          specification: modelForm.value.specification,
          materialCode: modelForm.value.materialCode,
          supplyType: modelForm.value.supplyType,
        };
        if (modelOperationType.value === "add") {
@@ -699,6 +810,11 @@
  };
  // æŸ¥è¯¢è§„格型号
  const pagination = obj => {
    page.current = obj.page;
    page.size = obj.limit;
    getModelList();
  };
  const getModelList = () => {
    if (!currentId.value) {
      return;
@@ -706,9 +822,14 @@
    tableLoading.value = true;
    modelListPage({
      materialId: currentId.value,
      current: page.current,
      size: page.size,
      specification: specification.value,
      materialCode: materialCode.value,
    }).then(res => {
      console.log("res", res);
      tableData.value = res.data;
      tableData.value = res.data.records || [];
      page.total = res.data.total;
      tableLoading.value = false;
    });
  };
src/views/energyManagement/energyConsumptionStatistical/index.vue
@@ -180,9 +180,13 @@
                         label="序号"
                         width="60"
                         align="center" />
        <el-table-column prop="timePeriod"
                         :label="timeColumnLabel"
                         align="center" />
        <el-table-column prop="meterReadingDate"
                         label="日期"
                         align="right">
          <template #default="scope">
            <span class="consumption-value">{{ scope.row.meterReadingDate }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="waterConsumption"
                         label="用水量(吨)"
                         align="right">
@@ -190,11 +194,11 @@
            <span class="consumption-value">{{ scope.row.waterConsumption }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="waterAmount"
        <el-table-column prop="waterCost"
                         label="æ°´è´¹(元)"
                         align="right">
          <template #default="scope">
            <span class="amount-value">{{ scope.row.waterAmount }}</span>
            <span class="amount-value">{{ scope.row.waterCost }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="electricityConsumption"
@@ -204,11 +208,11 @@
            <span class="consumption-value">{{ scope.row.electricityConsumption }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="electricityAmount"
        <el-table-column prop="electricityCost"
                         label="电费(元)"
                         align="right">
          <template #default="scope">
            <span class="amount-value">{{ scope.row.electricityAmount }}</span>
            <span class="amount-value">{{ scope.row.electricityCost }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="gasConsumption"
@@ -218,11 +222,11 @@
            <span class="consumption-value">{{ scope.row.gasConsumption }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="gasAmount"
        <el-table-column prop="gasCost"
                         label="气费(元)"
                         align="right">
          <template #default="scope">
            <span class="amount-value">{{ scope.row.gasAmount }}</span>
            <span class="amount-value">{{ scope.row.gasCost }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="totalConsumption"
@@ -237,7 +241,7 @@
                         align="right"
                         fixed="right">
          <template #default="scope">
            <span class="total-amount-value">Â¥{{ scope.row.totalAmount }}</span>
            <span class="total-amount-value">Â¥{{ scope.row.totalCost }}</span>
          </template>
        </el-table-column>
      </el-table>
@@ -443,7 +447,7 @@
      },
      xAxis: {
        type: "category",
        data: data.map(item => item.timePeriod),
        data: data.map(item => item.meterReadingDate),
        axisLabel: { rotate: statisticsType.value === "day" ? 45 : 0 },
      },
      yAxis: {
@@ -494,7 +498,7 @@
      },
      xAxis: {
        type: "category",
        data: data.map(item => item.timePeriod),
        data: data.map(item => item.meterReadingDate),
        axisLabel: { rotate: statisticsType.value === "day" ? 45 : 0 },
      },
      yAxis: {
@@ -505,21 +509,21 @@
        {
          name: "æ°´è´¹",
          type: "line",
          data: data.map(item => item.waterAmount),
          data: data.map(item => item.waterCost),
          smooth: true,
          itemStyle: { color: "#409EFF" },
        },
        {
          name: "电费",
          type: "line",
          data: data.map(item => item.electricityAmount),
          data: data.map(item => item.electricityCost),
          smooth: true,
          itemStyle: { color: "#E6A23C" },
        },
        {
          name: "气费",
          type: "line",
          data: data.map(item => item.gasAmount),
          data: data.map(item => item.gasCost),
          smooth: true,
          itemStyle: { color: "#67C23A" },
        },
@@ -595,15 +599,15 @@
  const updateAmountTypeChart = () => {
    const data = tableData.value;
    const totalWaterAmount = data.reduce(
      (sum, item) => sum + parseFloat(item.waterAmount),
      (sum, item) => sum + parseFloat(item.waterCost),
      0
    );
    const totalElectricityAmount = data.reduce(
      (sum, item) => sum + parseFloat(item.electricityAmount),
      (sum, item) => sum + parseFloat(item.electricityCost),
      0
    );
    const totalGasAmount = data.reduce(
      (sum, item) => sum + parseFloat(item.gasAmount),
      (sum, item) => sum + parseFloat(item.gasCost),
      0
    );
src/views/productionPlan/productionPlan/index.vue
@@ -248,6 +248,7 @@
                      prop="productMaterialSkuId">
          <el-select v-model="form.productMaterialSkuId"
                     @change="handleChangeSpecification"
                     filterable
                     placeholder="请选择">
            <el-option v-for="item in specificationOptions"
                       :key="item.skuId"
@@ -301,8 +302,14 @@
        </el-form-item>
        <el-form-item label="强度"
                      prop="strength">
          <el-input v-model="form.strength"
                    placeholder="请输入强度" />
          <el-select v-model="form.strength"
                     placeholder="请选择强度"
                     style="width: 100%">
            <el-option label="A3.5"
                       value="A3.5" />
            <el-option label="A5.0"
                       value="A5.0" />
          </el-select>
        </el-form-item>
        <el-form-item label="备注 1"
                      prop="remarkOne">
@@ -342,16 +349,33 @@
    productionPlanCombine,
  } from "@/api/productionPlan/productionPlan.js";
  import PIMTable from "./components/PIMTable.vue";
  import { modelListPage, productTreeList } from "@/api/basicData/newProduct.js";
  import {
    modelListPage,
    productTreeList,
    productTreeListQuery,
  } from "@/api/basicData/newProduct.js";
  const { proxy } = getCurrentInstance();
  const tableColumn = ref([
    {
      label: "数据来源",
      width: "100px",
      prop: "dataSourceType",
      dataType: "tag",
      formatType: params => {
        const typeMap = {
          2: "warning",
          1: "primary",
        };
        return typeMap[params] || "info";
      },
      formatData: cell => (cell == 1 ? "钉钉同步" : "手动新增"),
    },
    {
      label: "申请单编号",
      prop: "applyNo",
      width: "150px",
      className: "code-cell",
    },
    {
      label: "客户名称",
@@ -361,14 +385,15 @@
    {
      label: "产品名称",
      prop: "productName",
      width: "100px",
      width: "200px",
      dataType: "tag",
      formatType: params => {
        const typeMap = {
          æ¿æ: "primary",
          ç Œå—: "info",
        };
        return typeMap[params] || "info";
        // const typeMap = {
        //   æ¿æ: "primary",
        //   ç Œå—: "warning",
        // };
        // return typeMap[params] || "info";
        return "primary";
      },
    },
    {
@@ -381,46 +406,73 @@
      label: "物料编码",
      prop: "materialCode",
      width: "150px",
      className: "code-cell",
    },
    {
      label: "块数",
      prop: "quantity",
      className: "quantity-cell",
      formatData: cell => (cell ? `${cell}块` : ""),
    },
    {
      label: "方数",
      prop: "volume",
      width: "150px",
      className: "volume-cell",
      formatData: cell => (cell ? `${cell}方` : ""),
    },
    {
      label: "下发状态",
      prop: "status",
      width: "150px",
      className: "status-cell",
      dataType: "tag",
      formatType: params => {
        const typeMap = {
          0: "warning",
          1: "primary",
          2: "info",
        };
        return typeMap[params] || "info";
      },
      formatData: cell => {
        const statusMap = {
          0: "待下发",
          1: "部分下发",
          2: "已下发",
        };
        return statusMap[cell] || "";
      },
    },
    {
      label: "已下发方数",
      prop: "assignedQuantity",
      width: "150px",
      className: "spec-cell",
      formatData: cell => (cell ? `${cell}方` : 0),
    },
    {
      label: "长",
      prop: "length",
      className: "dimension-cell",
      formatData: cell => (cell ? `${cell}mm` : ""),
    },
    {
      label: "宽",
      prop: "width",
      className: "dimension-cell",
      formatData: cell => (cell ? `${cell}mm` : ""),
    },
    {
      label: "高",
      prop: "height",
      className: "dimension-cell",
      formatData: cell => (cell ? `${cell}mm` : ""),
    },
    {
      label: "流水号",
      prop: "serialNo",
      width: "150px",
      className: "code-cell",
    },
    // {
    //   label: "流水号",
    //   prop: "serialNo",
    //   width: "150px",
    //   className: "code-cell",
    // },
    {
      label: "计划开始日期",
      prop: "startDate",
@@ -439,18 +491,15 @@
      label: "强度",
      prop: "strength",
    },
    // {
    //   label: "数据来源",
    //   width: "100px",
    //   prop: "dataSourceType",
    //   formatData: cell => (cell == 1 ? "同步" : "手动"),
    // },
    {
      label: "备注 1",
      width: "150px",
      prop: "remarkOne",
    },
    {
      label: "备注 2",
      width: "150px",
      prop: "remarkTwo",
    },
@@ -465,6 +514,10 @@
          name: "编辑",
          type: "primary",
          link: true,
          showHide: row => {
            return row.status == 0;
            //status,0:待下发,1:部分下发,2:已下发
          },
          clickFun: row => {
            handleEdit(row);
          },
@@ -473,6 +526,9 @@
          name: "删除",
          type: "danger",
          link: true,
          showHide: row => {
            return row.status == 0;
          },
          clickFun: row => {
            handleDelete(row);
          },
@@ -480,12 +536,12 @@
        {
          name: "下发",
          type: "text",
          disabled: row => {
          showHide: row => {
            // è®¡ç®—剩余方数
            const remainingVolume =
              (row.volume || 0) - (row.assignedQuantity || 0);
            // å¦‚果剩余方数小于等于0,禁止选择
            return remainingVolume <= 0;
            return remainingVolume > 0;
          },
          clickFun: row => {
            // å•独下发操作
@@ -597,6 +653,7 @@
    productMaterialSkuId: [
      { required: true, message: "请选择产品规格", trigger: "change" },
    ],
    volume: [{ required: true, message: "请输入方数", trigger: "blur" }],
    productMaterialId: [
      { required: true, message: "请选择产品", trigger: "change" },
    ],
@@ -626,7 +683,7 @@
  };
  const fetchProductOptions = () => {
    return productTreeList().then(res => {
    return productTreeList({ type: 2 }).then(res => {
      productOptions.value = convertIdToValue(res.data);
      return res;
    });
@@ -658,19 +715,31 @@
  const fetchSpecificationOptions = materialId => {
    specificationOptions.value = [];
    if (materialId) {
      modelListPage({ materialId: materialId }).then(res => {
        specificationOptions.value = res.data;
      });
      modelListPage({ materialId: materialId, size: -1, current: -1 }).then(
        res => {
          specificationOptions.value = res.data.records;
        }
      );
    }
  };
  const handleChangeSpecification = value => {
    form.materialCode = undefined;
    const selectedModel = specificationOptions.value.find(
      item => item.id === value
      item => item.skuId === value
    );
    if (selectedModel) {
      form.materialCode = selectedModel.materialCode;
      // è§£æžè§„格字符串获取长宽高
      const specification = selectedModel.specification;
      if (specification) {
        const dimensions = specification.match(/^(\d+)\*(\d+)\*(\d+)$/);
        if (dimensions && dimensions.length === 4) {
          form.length = parseInt(dimensions[1]);
          form.width = parseInt(dimensions[2]);
          form.height = parseInt(dimensions[3]);
        }
      }
    }
  };
@@ -1092,8 +1161,16 @@
  const handleSubmit = () => {
    formRef.value.validate(valid => {
      if (valid) {
        if (form.volume === 0) {
          proxy.$modal.msgError("方数不能为0");
          return;
        }
        if (form.v === "add") {
          payload.id = null;
        }
        const payload = { ...form };
        if (operationType.value === "add") {
          payload.id = null;
          productionPlanAdd(payload)
            .then(() => {
              proxy.$modal.msgSuccess(
@@ -1179,7 +1256,6 @@
        color: #ffffff;
        border-bottom: none;
        padding: 16px 0;
        font-size: 14px;
        letter-spacing: 0.5px;
      }
    }
@@ -1202,7 +1278,6 @@
          border-bottom: 1px solid #f0f0f0;
          padding: 14px 0;
          color: #303133;
          font-size: 13px;
        }
      }
@@ -1221,7 +1296,6 @@
        font-weight: 600;
        color: #409eff;
        font-family: "Courier New", monospace;
        font-size: 14px;
        text-shadow: 0 1px 2px rgba(64, 158, 255, 0.2);
      }
@@ -1246,7 +1320,6 @@
      // æ—¥æœŸå­—段样式
      .date-cell {
        color: #909399;
        font-size: 12px;
        font-style: italic;
      }
src/views/productionPlan/summaryByProduct/index.vue
@@ -1,13 +1,33 @@
<template>
  <div class="app-container">
    <div class="search_form">
      <div>
        <span class="search_title ml10">物料编码:</span>
        <el-input v-model="searchForm.materialCode"
                  style="width: 200px"
                  placeholder="请输入物料编码"
                  clearable />
        <span class="search_title ml10">产品名称:</span>
        <el-input v-model="searchForm.productName"
                  style="width: 200px"
                  placeholder="请输入产品名称"
                  clearable />
        <el-button type="primary"
                   @click="handleQuery"
                   style="margin-left: 10px">搜索</el-button>
        <el-button @click="handleReset">重置</el-button>
      </div>
    </div>
    <div class="table_list">
      <PIMTable rowKey="materialCode"
                :column="tableColumn"
                :tableData="tableData"
                :page="page"
                height="calc(100vh - 200px)"
                height="calc(100vh - 280px)"
                :tableLoading="tableLoading"
                :isSelection="false"
                :isShowSummary="true"
                :summaryMethod="summaryMethod"
                @pagination="pagination">
      </PIMTable>
    </div>
@@ -23,49 +43,45 @@
    {
      label: "物料编码",
      prop: "materialCode",
      className: "code-cell",
    },
    {
      label: "产品名称",
      prop: "productName",
      dataType: "tag",
      formatType: params => {
        const typeMap = {
          æ¿æ: "primary",
          ç Œå—: "info",
        };
        return typeMap[params] || "info";
        return "primary";
      },
    },
    {
      label: "产品规格",
      prop: "productSpec",
      prop: "specification",
      className: "spec-cell",
    },
    {
      label: "长",
      prop: "length",
      className: "dimension-cell",
      formatData: cell => (cell ? `${cell}mm` : ""),
    },
    {
      label: "宽",
      prop: "width",
      className: "dimension-cell",
      formatData: cell => (cell ? `${cell}mm` : ""),
    },
    {
      label: "高",
      prop: "height",
      className: "dimension-cell",
      formatData: cell => (cell ? `${cell}mm` : ""),
    },
    {
      label: "块数",
      prop: "quantity",
      className: "quantity-cell",
      formatData: cell => (cell ? `${cell}块` : ""),
    },
    {
      label: "方数",
      prop: "volume",
      className: "volume-cell",
      formatData: cell => (cell ? `${cell}方` : ""),
    },
  ]);
  const tableData = ref([]);
@@ -78,13 +94,21 @@
  // æœç´¢è¡¨å•
  const searchForm = reactive({
    materialCode: "",
    productName: "",
    productSpec: "",
  });
  // æŸ¥è¯¢åˆ—表
  /** æœç´¢æŒ‰é’®æ“ä½œ */
  const handleQuery = () => {
    page.current = 1;
    getList();
  };
  /** é‡ç½®æŒ‰é’®æ“ä½œ */
  const handleReset = () => {
    searchForm.materialCode = "";
    searchForm.productName = "";
    page.current = 1;
    getList();
  };
@@ -109,6 +133,31 @@
      .catch(() => {
        tableLoading.value = false;
      });
  };
  // æ±‡æ€»æ–¹æ³•
  const summaryMethod = ({ columns, data }) => {
    const sums = [];
    columns.forEach((column, index) => {
      if (index === 0) {
        sums[index] = "总计";
        return;
      }
      if (column.property === "quantity") {
        const total = data.reduce((acc, item) => {
          return acc + (Number(item.quantity) || 0);
        }, 0);
        sums[index] = `${total}块`;
      } else if (column.property === "volume") {
        const total = data.reduce((acc, item) => {
          return acc + (Number(item.volume) || 0);
        }, 0);
        sums[index] = `${total.toFixed(4)}方`;
      } else {
        sums[index] = "";
      }
    });
    return sums;
  };
  onMounted(() => {
@@ -137,6 +186,16 @@
    &:hover {
      box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.08);
    }
    .search_title {
      color: #606266;
      font-size: 14px;
      font-weight: 500;
    }
    .ml10 {
      margin-left: 10px;
    }
  }
  .table_list {
@@ -144,7 +203,7 @@
    border-radius: 6px;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
    overflow: hidden;
    height: calc(100vh - 150px);
    height: calc(100vh - 230px);
  }
  :deep(.el-table) {
@@ -162,7 +221,6 @@
        color: #ffffff;
        border-bottom: none;
        padding: 16px 0;
        font-size: 14px;
        letter-spacing: 0.5px;
      }
    }
@@ -185,7 +243,6 @@
          border-bottom: 1px solid #f0f0f0;
          padding: 14px 0;
          color: #303133;
          font-size: 13px;
        }
      }
@@ -204,7 +261,6 @@
        font-weight: 600;
        color: #409eff;
        font-family: "Courier New", monospace;
        font-size: 14px;
        text-shadow: 0 1px 2px rgba(64, 158, 255, 0.2);
      }
@@ -228,7 +284,6 @@
      // æ—¥æœŸå­—段样式
      .date-cell {
        color: #909399;
        font-size: 12px;
        font-style: italic;
      }
    }
vite.config.js
@@ -8,7 +8,7 @@
  const { VITE_APP_ENV } = env;
  const baseUrl =
      env.VITE_APP_ENV === "development"
          ? "http://192.168.1.248:9090"
          ? "http://192.168.1.234:9019"
          : env.VITE_BASE_API;
  const javaUrl =
      env.VITE_APP_ENV === "development"