gaoluyang
2 天以前 9d9c62348e3296a597405e6f6416da8efc0fe18b
Merge remote-tracking branch 'origin/dev' into dev
已修改7个文件
已删除1个文件
已添加2个文件
1364 ■■■■■ 文件已修改
src/api/archiveManagement/index.js 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/basicInformation/coal.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/basicInformation/coalFieldMaintenance.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/archiveManagement/index.vue 570 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicInformation/index.vue 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicInformation/indexs.vue 541 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicInformation/mould/coalQualityMaintenance.vue 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procureMent/components/ProductionDialog.vue 142 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/production/components/ProductionDialog.vue 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/production/index.vue 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/archiveManagement/index.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,58 @@
// æ–‡æ¡£ç®¡ç†
import request from '@/utils/request'
// æŸ¥è¯¢æ–‡æ¡£ç®¡ç†æ ‘形结构
export function getTree(query) {
    return request({
        url: '/tree/list',
        method: 'get',
        params: query
    })
}
// æ–°å¢žæˆ–编辑文档信息
export function addOrEditTree(query) {
    return request({
        url: '/tree/addOrEditTree',
        method: 'post',
        data: query
    })
}
// åˆ é™¤æ–‡æ¡£ä¿¡æ¯æ•°æ®
export function delTree(query) {
    return request({
        url: '/tree/delTree',
        method: 'delete',
        data: query
    })
}
// /archive/list
// æŸ¥è¯¢æ–‡æ¡£åˆ—表
export function getArchiveList(query) {
    return request({
        url: '/archive/list',
        method: 'get',
        params: query
    })
}
// /archive/addOrEditArchive
// æ–°å¢žæˆ–编辑文档信息
export function addOrEditArchive(query) {
    return request({
        url: '/archive/addOrEditArchive',
        method: 'post',
        data: query
    })
}
// /archive/delArchive
// åˆ é™¤æ–‡æ¡£ä¿¡æ¯æ•°æ®
export function delArchive(query) {
    return request({
        url: '/archive/delArchive',
        method: 'delete',
        data: query
    })
}
src/api/basicInformation/coal.js
@@ -6,7 +6,7 @@
    return request({
        url: '/coalInfo/list',
        method: 'get',
        data: query
        params: query
    })
}
src/api/basicInformation/coalFieldMaintenance.js
@@ -6,7 +6,7 @@
    return request({
        url: '/coalField/list',
        method: 'get',
        data: query
        params: query
    })
}
// æ–°å¢žæˆ–编辑煤质字段
src/views/archiveManagement/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,570 @@
<template>
  <el-card class="archive-management-card">
    <div class="left">
      <div class="left-content">
        <div class="tree-header">
          <h3>文档管理</h3>
          <el-button type="primary" size="small" @click="append('')" icon="Plus"
            >新增</el-button
          >
        </div>
        <!-- æœç´¢æ¡† -->
        <div class="search-box">
          <el-input
            v-model="filterText"
            placeholder="输入关键字进行搜索"
            size="small"
            clearable
            @input="handleFilter"
          >
            <template #prefix>
              <el-icon><Search /></el-icon>
            </template>
          </el-input>
        </div>
        <div class="tree-container">
          <el-tree
            ref="treeRef"
            :data="treeData"
            :props="props"
            :filter-node-method="filterNode"
            :expand-on-click-node="false"
            :default-expand-all="false"
            node-key="id"
            @node-click="handleNodeClick"
            class="custom-tree"
          >
            <template #default="{ node, data }">
              <div class="tree-node-content" @dblclick="headerDbClick(data)">
                <div class="node-icon">
                  <el-icon
                    v-if="!node.isLeaf"
                    :class="{ expanded: node.expanded }"
                  >
                    <Folder />
                  </el-icon>
                  <el-icon v-else>
                    <Document />
                  </el-icon>
                </div>
                <div class="node-label">
                  <span v-if="!data.isEdit" class="label-text">{{
                    node.label
                  }}</span>
                  <el-input
                    v-else
                    :ref="(el) => setInputRef(el, data)"
                    placeholder="请输入节点名称"
                    v-model="newName"
                    @blur="($event) => handleInputBlur($event, data, node)"
                    @keyup.enter="
                      ($event) => handleInputBlur($event, data, node)
                    "
                    size="small"
                    class="tree-input"
                    autofocus
                  />
                </div>
                <div class="node-actions" v-show="!data.isEdit">
                  <el-button
                    link
                    size="small"
                    @click.stop="append(data)"
                    icon="Plus"
                    title="新增子节点"
                  ></el-button>
                  <el-button
                    link
                    size="small"
                    @click.stop="remove(node, data)"
                    icon="Delete"
                    title="删除"
                  ></el-button>
                </div>
              </div>
            </template>
          </el-tree>
        </div>
      </div>
    </div>
    <div class="right">
      <el-row :gutter="24">
          <el-col :span="2" :offset="20"><el-button :icon="Delete" type="danger">删除</el-button></el-col>
          <el-col :span="2"><el-button :icon="Plus" type="primary">新增</el-button></el-col>
      </el-row>
      <ETable
        :loading="loading"
        :table-data="tableData"
        :columns="columns"
        @selection-change="handleSelectionChange"
        @edit="handleEdit"
        :show-selection="true"
        :border="true"
      >
      </ETable>
      <Pagination
        :total="total"
        :page-size="10"
        :page-count="Math.ceil(total / 10)"
        @page-change="currentPageChange"
      ></Pagination>
    </div>
  </el-card>
</template>
<script setup>
import { onMounted, ref, nextTick } from "vue";
import ETable from "@/components/Table/ETable.vue";
import { ElButton, ElInput, ElIcon } from "element-plus";
import Pagination from "@/components/Pagination/index.vue";
import {
  Plus,
  Search,
  Folder,
  Document,
  Delete,
} from "@element-plus/icons-vue";
import {
  getTree,
  addOrEditTree,
  delTree,
  getArchiveList,
  addOrEditArchive,
  delArchive,
} from "@/api/archiveManagement";
const loading = ref(false);
const tableData = ref([]);
const treeData = ref([]);
const newName = ref("");
const inputRefs = ref(new Map()); // å­˜å‚¨è¾“入框引用
const filterText = ref(""); // æœç´¢å…³é”®å­—
const treeRef = ref(); // æ ‘组件引用
const total = ref(0); // æ€»è®°å½•æ•°
const current = ref(1); // å½“前页码
const columns = [
  { prop: "name", label: "名称", minWidth: 180 },
  { prop: "type", label: "类型", minWidth: 120 },
  { prop: "status", label: "状态", minWidth: 100 },
];
const handleSelectionChange = (selection) => {
  console.log("Selected rows:", selection);
};
// æœç´¢è¿‡æ»¤åŠŸèƒ½
const handleFilter = () => {
  treeRef.value?.filter(filterText.value);
};
const filterNode = (value, data) => {
  if (!value) return true;
  return data.name?.toLowerCase().includes(value.toLowerCase());
};
// å¤„理节点点击
const handleNodeClick = async (data) => {
  console.log("点击节点:", data);
  let res = await getArchiveList(data.id);
  tableData.value = res.data?.records || res.data || [];
  console.log(data)
};
const currentPageChange = (id) => {
  console.log(id);
};
// åŒå‡»ç¼–辑节点
const headerDbClick = (comeTreeData) => {
  comeTreeData.isEdit = true;
  newName.value = comeTreeData.name;
  nextTick(() => {
    const inputEl = inputRefs.value.get(comeTreeData.id || comeTreeData);
    if (inputEl) {
      inputEl.focus();
      inputEl.select();
    }
  });
};
// è®¾ç½®è¾“入框引用的方法
const setInputRef = (el, data) => {
  if (el) {
    inputRefs.value.set(data.id || data, el);
    if (data.isEdit) {
      nextTick(() => {
        // el.focus();
        // el.select();
      });
    }
  }
};
// å¤„理输入框失焦
const handleInputBlur = async (event, comeTreeData, node) => {
  if (!comeTreeData.isEdit) return; // å¦‚果不是编辑状态,直接返回
  if (event.relatedTarget && event.relatedTarget.tagName === "BUTTON") {
    return;
  }
  comeTreeData.isEdit = false;
  const newValue = newName.value.trim();
  if (comeTreeData.name === newValue) {
    console.log("没有修改内容");
    return;
  }
  if (newValue === "") {
    console.warn("输入不能为空");
    newName.value = comeTreeData.name || "新节点";
    return;
  }
  try {
    comeTreeData.name = newValue;
    // èŽ·å–çˆ¶èŠ‚ç‚¹çš„id - é€šè¿‡ node å‚数更准确地获取
    let parentId = null;
    if (node && node.parent && node.parent.data) {
      parentId = node.parent.data.id;
    }
    await addOrEditTree({
      name: newValue,
      parentId: parentId || null, // å¦‚果没有父节点,则为 null
    });
  } catch (error) {
    console.error("存储失败", error);
    comeTreeData.name = comeTreeData.name || "新节点";
  }
  console.log("保存成功:", newValue);
};
onMounted(async () => {
  await getList();
});
const props = {
  label: "name",
  children: "children", // æ”¹ä¸º children ä»¥åŒ¹é…æ ‡å‡†ç»“æž„
  isLeaf: "leaf",
};
const remove = async (node, data) => {
  console.log("删除节点:", data);
  if (!data || !data.id) {
    console.warn("无法删除未定义或无效的节点");
    return;
  }
  console.log("删除节点 ID:", data.id);
  let { code, msg } = await delTree([data.id]);
  if (code !== 200) {
    ElMessage.warning("删除失败, " + msg);
  } else {
    ElMessage.success("删除成功");
  }
  await getList();
};
const append = async (data) => {
  if (data === "") {
    // æ–°å¢žæ ¹èŠ‚ç‚¹
    console.log("新增根节点");
    const newNode = {
      id: Date.now(),
      name: "新节点",
      isEdit: true,
    };
    treeData.value.push(newNode);
    newName.value = "新节点";
    nextTick(() => {
      const inputEl = inputRefs.value.get(newNode.id || newNode);
      if (inputEl) {
        inputEl.focus();
        inputEl.select();
      }
    });
  } else {
    const hasChildren = data.children && data.children.length > 0;
    const nodeKey = data.id || data;
    const node = treeRef.value?.getNode(nodeKey);
    const isExpanded = node?.expanded; // å¦‚果有子级且未展开,先展开节点
    if (hasChildren && !isExpanded) {
      console.log(treeRef.value, "展开节点", nodeKey);
      if (
        treeRef.value &&
        treeRef.value.store &&
        treeRef.value.store.nodesMap[nodeKey]
      ) {
        treeRef.value.store.nodesMap[nodeKey].expanded = true;
      }
    }
    const newNode = {
      id: Date.now(),
      name: "新子节点",
      isEdit: true,
    };
    if (!data.children) {
      data.children = [];
    }
    data.children.push(newNode);
    newName.value = "新子节点";
    // æ ¹æ®æ˜¯å¦éœ€è¦å±•开来决定延迟时间
    const delay = hasChildren && !isExpanded ? 200 : 50;
    // ç­‰å¾…DOM更新完成后再聚焦
    nextTick(() => {
      setTimeout(() => {
        const inputEl = inputRefs.value.get(newNode.id || newNode);
        if (inputEl) {
          inputEl.focus();
          inputEl.select();
          // æ»šåŠ¨åˆ°æ–°å¢žçš„èŠ‚ç‚¹ä½ç½®
          inputEl.$el?.scrollIntoView?.({
            behavior: "smooth",
            block: "nearest",
          });
        }
      }, delay);
    });
  }
};
const handleEdit = () => {};
// ç§»é™¤æ‡’加载,直接获取数据
const getList = async () => {
  try {
    let res = await getTree();
    if (res.code === 200) {
      treeData.value = res.data?.records || res.data || [];
    } else {
      console.error("Failed to fetch tree data:", res.message);
      treeData.value = [];
    }
  } catch (error) {
    console.error("获取树形数据失败:", error);
    treeData.value = [];
  }
};
</script>
<style scoped lang="scss">
.custom-tree-node {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  padding-right: 8px;
}
// æ ‘形菜单样式
.tree-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
  padding-bottom: 12px;
  border-bottom: 1px solid #e4e7ed;
  h3 {
    margin: 0;
    font-size: 16px;
    font-weight: 600;
    color: #303133;
  }
}
.search-box {
  margin-bottom: 16px;
  .el-input {
    border-radius: 6px;
    :deep(.el-input__wrapper) {
      border-radius: 6px;
      box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
      &:hover {
        box-shadow: 0 1px 6px rgba(0, 0, 0, 0.15);
      }
      &.is-focus {
        box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
      }
    }
  }
}
.tree-container {
  flex: 1;
  overflow-y: auto;
  border: 1px solid #dcdfe6;
  border-radius: 8px;
  background: #fff;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
  .custom-tree {
    padding: 8px;
    background: transparent;
    :deep(.el-tree-node) {
      .el-tree-node__content {
        height: 36px;
        padding: 0 8px;
        border-radius: 6px;
        margin: 2px 0;
        transition: all 0.2s ease;
        &:hover {
          background-color: #f0f9ff;
        }
        &.is-current {
          background-color: #e6f7ff;
          border: 1px solid #91d5ff;
        }
      }
      .el-tree-node__expand-icon {
        color: #606266;
        font-size: 14px;
        padding: 6px;
        &.expanded {
          transform: rotate(90deg);
        }
        &.is-leaf {
          color: transparent;
        }
      }
    }
  }
}
.tree-node-content {
  display: flex;
  align-items: center;
  width: 100%;
  padding: 4px 0;
  .node-icon {
    margin-right: 8px;
    color: #faad14;
    display: flex;
    align-items: center;
    .el-icon {
      font-size: 16px;
      &.expanded {
        color: #1890ff;
      }
    }
  }
  .node-label {
    flex: 1;
    min-width: 0;
    .label-text {
      font-size: 14px;
      color: #303133;
      cursor: pointer;
      display: block;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      &:hover {
        color: #1890ff;
      }
    }
  }
  .node-actions {
    opacity: 0;
    transition: opacity 0.2s ease;
    display: flex;
    .el-button {
      padding: 4px;
      margin-left: 4px;
      color: #909399;
      min-height: auto;
      &:hover {
        color: #1890ff;
        background-color: #f0f9ff;
      }
      &.el-button--text:hover {
        background-color: #f0f9ff;
      }
    }
  }
  &:hover .node-actions {
    opacity: 1;
  }
}
// è¾“入框样式美化
.tree-input {
  flex: 1;
  :deep(.el-input__wrapper) {
    border-radius: 4px;
    border: 1px solid #d9d9d9;
    transition: all 0.2s ease;
    &:hover {
      border-color: #40a9ff;
    }
    &.is-focus {
      border-color: #1890ff;
      box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
    }
  }
  :deep(.el-input__inner) {
    padding: 4px 8px;
    font-size: 14px;
    color: #303133;
    &::placeholder {
      color: #bfbfbf;
    }
  }
}
.el-card {
  width: calc(100% - 40px);
  height: calc(100vh - 130px);
  margin: 20px;
  box-sizing: border-box;
  .left {
    width: 30%;
    height: calc(100vh - 160px);
    background-color: #fafafa;
    padding: 16px;
    float: left;
    box-sizing: border-box;
    border-radius: 8px;
    .left-content {
      width: 100%;
      height: 100%;
      display: flex;
      flex-direction: column;
    }
  }
  .right {
    width: 70%;
    height: calc(100vh - 160px);
    padding: 0px 10px;
    float: left;
  }
}
.archive-management-card{
  margin: 0;
}
</style>
src/views/basicInformation/index.vue
@@ -416,7 +416,10 @@
  loading.value = true;
  tabName.value = tab.props.name;
  tableData.value = [];
  pageNum.value = 1;
  pageSizes.value = 10;
  total.value = 0;
  queryParams.searchAll = "";
  // æ ¹æ®æ ‡ç­¾é¡µç±»åž‹è®¾ç½®å¯¹åº”的列配置
  const tabConfig = {
    supplier: () => {
@@ -615,7 +618,7 @@
      ElMessage.error("删除接口未配置");
      return;
    }
    console.log(deleteIds)
    const res = await deleteApi(deleteIds);
    
    if (res.code !== 200 && res.msg !== "操作成功") {
src/views/basicInformation/indexs.vue
ÎļþÒÑɾ³ý
src/views/basicInformation/mould/coalQualityMaintenance.vue
@@ -118,12 +118,11 @@
 */
const initFormData = (newForm) => {
  formData.value = { ...newForm };
  console.log(formData.value)
  // å¤„理 coalFieldList å­—段:编辑时需要将字符串转换为数组供多选组件使用
  if (newForm.coalFields) {
    if (typeof newForm.coalFields === 'string') {
  if (newForm.fieldIds) {
    if (typeof newForm.fieldIds === 'string') {
      // å°†å­—符串转换为ID数组,然后匹配对应的选项对象
      const ids = parseCoalFields(newForm.coalFields);
      const ids = parseCoalFields(newForm.fieldIds);
      formData.value.coalFieldList = ids.map(id => {
        const option = fieldOptions.find(opt => opt.value === id);
        return option || { fields: `字段${id}`, value: id };
src/views/procureMent/components/ProductionDialog.vue
@@ -33,46 +33,64 @@
              <el-option label="吨" value="吨" />
              <el-option label="千克" value="千克" />
            </el-select>
        </el-form-item>
        <el-form-item label="采购数量" prop="purchaseQuantity">
          <el-input v-model.number="form.purchaseQuantity" placeholder="请输入"  >
        </el-form-item>        <el-form-item label="采购数量" prop="purchaseQuantity">
          <el-input
            v-model.number="form.purchaseQuantity"
            placeholder="请输入"
            @blur="handleQuantityBlur"
          >
            <template v-slot:suffix>
            <i style="font-style:normal;">{{form.unit?form.unit:''}}</i>
          </template>
          </el-input>
        </el-form-item><el-form-item label="税率" prop="taxRate">
          <el-input
            v-model.number="form.taxRate"
            placeholder="请输入税率"
            @blur="handleTaxRateBlur"
          >
            <template v-slot:suffix>
            <i style="font-style:normal;">%</i>
          </template>
            </el-input>
        </el-form-item>
        <el-form-item label="单价(不含税)" prop="priceExcludingTax">
          <el-input v-model.number="form.priceExcludingTax" placeholder="请输入" >
          <el-input
            v-model.number="form.priceExcludingTax"
            placeholder="请输入"
            @blur="handlePriceBlur"
          >
            <template v-slot:suffix>
            <i style="font-style:normal;">元</i>
          </template>
          </el-input>
        </el-form-item>        <el-form-item label="单价(含税)" prop="priceIncludingTax">
          <el-input
            v-model.number="form.priceIncludingTax"
            placeholder="自动计算"
          >
            <template v-slot:suffix>
            <i style="font-style:normal;">元</i>
          </template>
          </el-input>
        </el-form-item>
        <el-form-item label="总价(不含税)" prop="totalPriceExcludingTax">
          <el-input v-model.number="form.totalPriceExcludingTax" placeholder="请输入" >
            <template v-slot:suffix>
            <i style="font-style:normal;">元</i>
          </template>
          </el-input>
        </el-form-item>
        <el-form-item label="单价(含税)" prop="priceIncludingTax">
          <el-input v-model.number="form.priceIncludingTax" placeholder="请输入" >
          <el-input
            v-model.number="form.totalPriceExcludingTax"
            placeholder="自动计算"
          >
            <template v-slot:suffix>
            <i style="font-style:normal;">元</i>
          </template>
          </el-input>
        </el-form-item>
        <el-form-item label="总价(含税)" prop="totalPriceIncludingTax">
          <el-input v-model.number="form.totalPriceIncludingTax" placeholder="请输入" >
          <el-input
            v-model.number="form.totalPriceIncludingTax"
            placeholder="自动计算"
          >
            <template v-slot:suffix>
            <i style="font-style:normal;">元</i>
          </template>
          </el-input>
        </el-form-item>
        <el-form-item label="税率" prop="taxRate">
          <el-input v-model="form.taxRate" placeholder="请输入税率" >
            <template v-slot:suffix>
            <i style="font-style:normal;">%</i>
          </template>
            </el-input>
        </el-form-item>
@@ -111,7 +129,7 @@
</template>
<script setup name="ProductionDialog">
import { ref, defineProps, watch, onMounted, nextTick } from "vue";
import { ref, defineProps, watch, onMounted, nextTick, computed  } from "vue";
import { ElMessage } from "element-plus";
import useUserStore from '@/store/modules/user'
import {addOrEditPR} from "@/api/procureMent";
@@ -134,8 +152,89 @@
  required: true,
  type: Object,
});
const toFixed = (num, precision = 2) => {
  if (isNaN(num) || num === null || num === undefined || num === '') {
    return 0;
  }
  return Math.floor(parseFloat(num) * Math.pow(10, precision)) / Math.pow(10, precision);
};
// å«ç¨Žå•价计算
const unitPriceWithTax = computed(() => {
  const priceExcludingTax = parseFloat(form.value.priceExcludingTax) || 0;
  const taxRate = parseFloat(form.value.taxRate) || 0;
  if (!priceExcludingTax || !taxRate) {
    return 0;
  }
  const result = priceExcludingTax * (1 + taxRate / 100);
  return toFixed(result, 2);
});
// å«ç¨Žæ€»ä»·è®¡ç®—
const totalUnitPriceWithTax = computed(() => {
  const priceExcludingTax = parseFloat(form.value.priceExcludingTax) || 0;
  const taxRate = parseFloat(form.value.taxRate) || 0;
  const purchaseQuantity = parseFloat(form.value.purchaseQuantity) || 0;
  if (!priceExcludingTax || !taxRate || !purchaseQuantity) {
    return 0;
  }
  const unitPriceWithTaxValue = priceExcludingTax * (1 + taxRate / 100);
  const result = unitPriceWithTaxValue * purchaseQuantity;
  return toFixed(result, 2);
});
// ä¸å«ç¨Žæ€»ä»·è®¡ç®—
const taxExclusiveTotalPrice = computed(() => {
  const purchaseQuantity = parseFloat(form.value.purchaseQuantity) || 0;
  const priceExcludingTax = parseFloat(form.value.priceExcludingTax) || 0;
  if (!purchaseQuantity || !priceExcludingTax) {
    return 0;
  }
  const result = purchaseQuantity * priceExcludingTax;
  return toFixed(result, 2);
});
// ç›‘听计算值变化,同步到 form å¯¹è±¡ä¸­
watch(unitPriceWithTax, (newValue) => {
  form.value.priceIncludingTax = newValue;
});
watch(totalUnitPriceWithTax, (newValue) => {
  form.value.totalPriceIncludingTax = newValue;
});
watch(taxExclusiveTotalPrice, (newValue) => {
  form.value.totalPriceExcludingTax = newValue;
});
const userStore = useUserStore()
const userInfo = ref({});
// å¤„理税率输入框失焦,确保精度
const handleTaxRateBlur = () => {
  if (form.value.taxRate !== null && form.value.taxRate !== undefined && form.value.taxRate !== '') {
    form.value.taxRate = toFixed(parseFloat(form.value.taxRate), 2);
  }
};
// å¤„理不含税单价输入框失焦,确保精度
const handlePriceBlur = () => {
  if (form.value.priceExcludingTax !== null && form.value.priceExcludingTax !== undefined && form.value.priceExcludingTax !== '') {
    form.value.priceExcludingTax = toFixed(parseFloat(form.value.priceExcludingTax), 2);
  }
};
// å¤„理采购数量输入框失焦,确保精度
const handleQuantityBlur = () => {
  if (form.value.purchaseQuantity !== null && form.value.purchaseQuantity !== undefined && form.value.purchaseQuantity !== '') {
    form.value.purchaseQuantity = toFixed(parseFloat(form.value.purchaseQuantity), 3); // æ•°é‡ä¿ç•™3位小数
  }
};
onMounted(async () => {
  let res = await userStore.getInfo()
  userInfo.value = res;
@@ -176,6 +275,7 @@
const formRef = ref(null);
// æäº¤è¡¨å•
const handleSubmit = async () => {
  console.log("提交表单", form.value);
  if (!formRef.value) return;
  await formRef.value.validate(async (valid) => {
    if (valid) {
src/views/production/components/ProductionDialog.vue
@@ -1,4 +1,4 @@
<template>
div<template>
  <el-dialog
    v-model="dialogVisible"
    :title="dialogType === 'add' ? '新增生产加工' : '编辑生产加工'"
@@ -17,9 +17,9 @@
      @row-click="handleRowClick"
      :editableColumns="['used']"
    />
    <div v-if="tableData.length > 0" class="empty-table">
    <div class="empty-table">
    <h1>生产明细</h1>
      <el-row :gutter="10">
      <el-row :gutter="10" v-if="tableData.length > 0">
      <el-col :span="2">
        <el-button type="primary" @click="addNewRow">
          <el-icon>
@@ -45,6 +45,7 @@
      </el-col> -->
    </el-row>
    <ProductionDetailsTable
     v-if="tableData.length > 0"
      v-model="detailsTableData"
      :border="false"
      :show-operations="true"
@@ -52,8 +53,9 @@
      @input-change="handleDetailsChange"
      @delete-row="handleDeleteRow"
    />
    </div>
      <div style="margin-top: 20px;" v-else>暂无数据,请选择配置数据</div>
    </div>
    <template #footer>
      <div class="dialog-footer">
@@ -452,4 +454,7 @@
.el-row > .el-col > h1 {
  font-weight: bolder;
}
.empty-table > .el-row{
  margin-bottom: 12px;
}
</style>
src/views/production/index.vue
@@ -32,17 +32,17 @@
import Pagination from "@/components/Pagination/index.vue";
const childRef = ref(null);
const columns = [
  { prop: "category", label: "煤种", width: 150 },
  { prop: "unit", label: "单位", width: 120 },
  { prop: "productionVolume", label: "生产数量", width: 150 },
  { prop: "laborCost", label: "人工成本", width: 150 },
  { prop: "materialCost", label: "原料成本", width: 120 },
  { prop: "equipmentCost", label: "设备费用", width: 143 },
  { prop: "totalCost", label: "总成本", width: 150 },
  { prop: "totalPrice", label: "总售价", width: 150 },
  { prop: "profit", label: "利润", width: 100 },
  { prop: "reviewer", label: "复记人", width: 120 },
  { prop: "date", label: "日期", width: 150 },
  { prop: "category", label: "煤种", minWidth: 150 },
  { prop: "unit", label: "单位", minWidth: 120 },
  { prop: "productionVolume", label: "生产数量", minWidth: 150 },
  { prop: "laborCost", label: "人工成本", minWidth: 150 },
  { prop: "materialCost", label: "原料成本", minWidth: 120 },
  { prop: "equipmentCost", label: "设备费用", minWidth: 143 },
  { prop: "totalCost", label: "总成本", minWidth: 150 },
  { prop: "totalPrice", label: "总售价", minWidth: 150 },
  { prop: "profit", label: "利润", minWidth: 100 },
  { prop: "reviewer", label: "复记人", minWidth: 120 },
  { prop: "date", label: "日期", minWidth: 150 },
];
// æœç´¢è¡¨å•数据