开发通用查看单条数据的详情页面 优化基础模块 优化生产加工数据匹配渲染问题
已修改4个文件
已添加1个文件
1002 ■■■■ 文件已修改
src/components/Table/ETable.vue 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/dialog/Descriptions.vue 230 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicInformation/index.vue 522 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicInformation/mould/supplier.vue 225 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/production/index.vue 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Table/ETable.vue
@@ -32,20 +32,13 @@
      </el-table-column>
    </template>
    <!-- æ“ä½œåˆ— -->
    <el-table-column v-if="showOperations" :label="operationsLabel" :width="operationsWidth" fixed="right" align="center">
    <el-table-column v-if="showOperations" :label="operationsLabel" :width="operationsWidth" :show-overflow-tooltip="false" fixed="right" align="center">
      <template #default="scope">
        <slot name="operations" :row="scope.row">
          <el-button v-if="operations.includes('edit')" link type="primary" size="small"
            @click="handleEdit(scope.row)">编辑</el-button>
          <el-button v-if="operations.includes('viewFile')" link type="primary" size="small"
          <el-button v-if="operations.includes('viewRow')" link type="primary" size="small"
            @click="handleView(scope.row)">查看附件</el-button>
          <!--            <el-button-->
          <!--              v-if="operations.includes('delete')"-->
          <!--              link-->
          <!--              type="danger"-->
          <!--              size="small"-->
          <!--              @click="handleDelete(scope.row)"-->
          <!--            >删除</el-button>-->
        </slot>
      </template>
    </el-table-column>
@@ -168,7 +161,7 @@
};
// å¤„理选择变化、编辑、删除和导出操作
const emit = defineEmits(['selection-change', 'edit', 'delete', 'export'])
const emit = defineEmits(['selection-change', 'edit', 'delete', 'export', 'viewRow'])
const handleSelectionChange = (selection) => {
  emit('selection-change', selection)
}
@@ -176,7 +169,7 @@
  emit('edit', row)
}
const handleView = (row) => {
  emit('viewFile', row)
  emit('viewRow', row)
}
const handleDelete = (row) => {
  ElMessageBox.confirm(
src/components/dialog/Descriptions.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,230 @@
<template>
  <el-dialog v-model="descriptionsVisible" :title="title" width="60%" :close-on-click-modal="false">
    <el-card>
      <el-descriptions
        class="margin-top"
        :title="descriptionsTitle"
        :column="column"
        :size="size"
        :border="border"
      >
        <template v-if="showOperations" #extra>
          <slot name="extra">
            <el-button type="primary" @click="handleEdit" v-if="!isViewOnly">编辑</el-button>
          </slot>
        </template>        <!-- åŠ¨æ€æ¸²æŸ“æ‰€æœ‰æ•°æ®é¡¹ -->
        <el-descriptions-item
          v-for="(item, key) in filteredData"
          :key="`desc-item-${key}`"
          :label="getFieldLabel(key)"
          :span="getFieldSpan(key)"
        >
          {{ formatValue(item, key) }}
        </el-descriptions-item>
      </el-descriptions>
    </el-card>
    <template #footer>
      <div class="dialog-footer">
        <el-button @click="handleClose">关闭</el-button>
        <el-button v-if="!isViewOnly" type="primary" @click="handleEdit">编辑</el-button>
      </div>
    </template>
  </el-dialog>
</template>
<script setup>
import { defineProps, computed } from "vue";
const props = defineProps({
  // å¼¹çª—标题
  title: {
    type: String,
    default: "详情信息"
  },
  // æ•°æ®å¯¹è±¡
  formData: {
    type: Object,
    default: () => ({})
  },
  // æ˜¯å¦ä¸ºæŸ¥çœ‹æ¨¡å¼
  isViewOnly: {
    type: Boolean,
    default: true
  },
  // æè¿°ç»„件标题
  descriptionsTitle: {
    type: String,
    default: ""
  },
  // åˆ—æ•°
  column: {
    type: Number,
    default: 2
  },
  // å°ºå¯¸
  size: {
    type: String,
    default: "default",
    validator: (value) => ["large", "default", "small"].includes(value)
  },
  // æ˜¯å¦æ˜¾ç¤ºè¾¹æ¡†
  border: {
    type: Boolean,
    default: true
  },
  // æ˜¯å¦æ˜¾ç¤ºæ“ä½œæŒ‰é’®
  showOperations: {
    type: Boolean,
    default: true
  },
  // å­—段映射配置 { key: { label: '显示名称', span?: è·¨åˆ—æ•°, formatter?: æ ¼å¼åŒ–函数 } }
  fieldConfig: {
    type: Object,
    default: () => ({})
  },
  // éœ€è¦æŽ’除显示的字段
  excludeFields: {
    type: Array,
    default: () => ['id', 'createTime', 'updateTime', 'deleted']
  },  // éœ€è¦åŒ…含显示的字段(如果设置了,则只显示这些字段)
  includeFields: {
    type: Array,
    default: () => []
  },
  // å­—段标签映射表 { key: '显示名称' }
  fieldLabels: {
    type: Object,
    default: () => ({})
  }
});
const descriptionsVisible = defineModel("descriptionsVisible", {
  type: Boolean,
  default: false,
});
const emit = defineEmits(["update:descriptionsVisible", "edit", "close"]);
// è¿‡æ»¤åŽçš„æ•°æ®
const filteredData = computed(() => {
  if (!props.formData || typeof props.formData !== 'object') {
    return {};
  }
  const data = { ...props.formData };
  let result = {};
  // å¦‚果指定了包含字段,则只显示这些字段
  if (props.includeFields.length > 0) {
    props.includeFields.forEach(field => {
      if (data.hasOwnProperty(field)) {
        result[field] = data[field];
      }
    });
  } else {
    // å¦åˆ™æŽ’除指定字段
    Object.keys(data).forEach(key => {
      if (!props.excludeFields.includes(key)) {
        result[key] = data[key];
      }
    });
  }
  return result;
});
// èŽ·å–å­—æ®µæ˜¾ç¤ºæ ‡ç­¾
const getFieldLabel = (key) => {
  // 1. ä¼˜å…ˆä½¿ç”¨ fieldConfig ä¸­çš„æ ‡ç­¾é…ç½®
  if (props.fieldConfig[key]?.label) {
    return props.fieldConfig[key].label;
  }
  // 2. å…¶æ¬¡ä½¿ç”¨ä¼ å…¥çš„字段映射表
  if (props.fieldLabels[key]) {
    return props.fieldLabels[key];
  }
  // 3. æœ€åŽä½¿ç”¨é»˜è®¤çš„字段名转换(驼峰转空格)
  return key.replace(/([A-Z])/g, ' $1').replace(/^./, str => str.toUpperCase());
};
// èŽ·å–å­—æ®µè·¨åˆ—æ•°
const getFieldSpan = (key) => {
  return props.fieldConfig[key]?.span || 1;
};
// æ ¼å¼åŒ–值
const formatValue = (value, key) => {
  // ä¼˜å…ˆä½¿ç”¨é…ç½®çš„æ ¼å¼åŒ–函数
  if (props.fieldConfig[key]?.formatter && typeof props.fieldConfig[key].formatter === 'function') {
    return props.fieldConfig[key].formatter(value);
  }
  // é»˜è®¤æ ¼å¼åŒ–
  if (value === null || value === undefined || value === '') {
    return '--';
  }
  // æ•°ç»„格式化
  if (Array.isArray(value)) {
    return value.join(', ');
  }
  // å¯¹è±¡æ ¼å¼åŒ–
  if (typeof value === 'object') {
    return JSON.stringify(value);
  }
  // æ—¥æœŸæ ¼å¼åŒ–
  if (key.toLowerCase().includes('time') || key.toLowerCase().includes('date')) {
    try {
      const date = new Date(value);
      if (!isNaN(date.getTime())) {
        return date.toLocaleString('zh-CN');
      }
    } catch (e) {
      // å¦‚果不是有效日期,返回原值
    }
  }
  return String(value);
};
// å¤„理编辑按钮点击
const handleEdit = () => {
  emit('edit', props.formData);
};
// å¤„理关闭
const handleClose = () => {
  descriptionsVisible.value = false;
  emit('close');
};
</script>
<style scoped>
.margin-top {
  margin-top: 20px;
}
.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
}
.cell-item {
  display: flex;
  align-items: center;
}
:deep(.el-descriptions__label) {
  font-weight: 600;
}
:deep(.el-descriptions__content) {
  word-break: break-word;
}
</style>
src/views/basicInformation/index.vue
@@ -2,7 +2,11 @@
  <div class="app-container">
    <el-form :inline="true" :model="queryParams" class="search-form">
      <el-form-item v-if="shouldShowSearch" label="搜索">
        <el-input v-model="queryParams.searchAll" :placeholder="searchPlaceholder" clearable/>
        <el-input
          v-model="queryParams.searchAll"
          :placeholder="searchPlaceholder"
          clearable
        />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="search">查询</el-button>
@@ -11,63 +15,167 @@
    </el-form>
    <el-card>
      <!-- æ ‡ç­¾é¡µ -->
      <el-tabs v-model="activeTab" class="info-tabs" @tab-click="handleTabClick">
        <el-tab-pane v-for="tab in tabs" :key="tab.name" :label="tab.label" :name="tab.name"/>
      <el-tabs
        v-model="activeTab"
        class="info-tabs"
        @tab-click="handleTabClick"
      >
        <el-tab-pane
          v-for="tab in tabs"
          :key="tab.name"
          :label="tab.label"
          :name="tab.name"
        />
      </el-tabs>
      <!-- æ“ä½œæŒ‰é’®åŒº -->
      <el-row :gutter="24" class="table-toolbar">
        <el-button :icon="Plus" type="primary" @click="handleAdd">新建</el-button>
        <el-button :icon="Delete" type="danger" @click="handleDelete">删除</el-button>
        <el-button @click="jump">admins</el-button>
        <el-button v-show="canExport" :icon="Download" type="info" @click="handleExport">导出</el-button>
      </el-row> <!-- è¡¨æ ¼ç»„ä»¶ -->
        <el-button :icon="Plus" type="primary" @click="handleAdd"
          >新建</el-button
        >
        <el-button :icon="Delete" type="danger" @click="handleDelete"
          >删除</el-button
        >
        <el-button
          v-show="canExport"
          :icon="Download"
          type="info"
          @click="handleExport"
          >导出</el-button
        >
      </el-row>
      <!-- è¡¨æ ¼ç»„ä»¶ -->
      <div>
        <data-table :border="true" :columns="columns" :loading="loading" style="width: 100%;height: calc(100vh - 29em)"
                    :show-selection="true" :table-data="tableData" @edit="handleEdit" @selection-change="handleSelectionChange">
        <data-table
          :border="true"
          :columns="columns"
          :loading="loading"
          style="width: 100%; height: calc(100vh - 29em)"
          :show-selection="true"
          :table-data="tableData"
          @edit="handleEdit"
          @viewRow="handleView"
          @selection-change="handleSelectionChange"
          :showOperations="true"
          :showIndex="true"
          :showPagination="false"
          :operations="['edit', 'viewRow']"
          :operationsWidth="200"
        >
          <!-- å­—段名称列的自定义插槽 - æ˜¾ç¤ºä¸ºæ ‡ç­¾ -->
          <template v-if="tabName === 'coalQualityMaintenance'" #fieldIds="{ row }">
            <template v-if="typeof row.fieldIds === 'string' && row.fieldIds.includes(',')">
              <el-tag v-for="(field, index) in row.fieldIds.split(',')" :key="index" size="small" style="margin-right: 4px; margin-bottom: 2px;"
                      type="primary">
          <template
            v-if="tabName === 'coalQualityMaintenance'"
            #fieldIds="{ row }"
          >
            <template
              v-if="
                typeof row.fieldIds === 'string' && row.fieldIds.includes(',')
              "
            >
              <el-tag
                v-for="(field, index) in row.fieldIds.split(',')"
                :key="index"
                size="small"
                style="margin-right: 4px; margin-bottom: 2px"
                type="primary"
              >
                {{ getFieldDisplayName(field.trim()) }}
              </el-tag>
            </template>
            <template v-else>
              <el-tag size="small" type="primary">
                {{ getFieldDisplayName(row.fieldIds) || '--' }}
                {{ getFieldDisplayName(row.fieldIds) || "--" }}
              </el-tag>
            </template>
          </template>
        </data-table>
      </div>
      <pagination v-if="total > 0" :layout="'total, prev, pager, next, jumper'" :limit="pageSizes" :page="pageNum" :total="total"
                  @pagination="handPagination"/>
      <Supplier v-if="tabName === 'supplier'" v-model:copyForm="copyForm"
                v-model:supplierDialogFormVisible="dialogFormVisible" :addOrEdit="addOrEdit" :form="form" :title="title"
                @beforeClose="handleBeforeClose" @submit="handleSubmit"
                @update:dialogFormVisible="handleDialogFormVisible"/>
      <Customer v-if="tabName === 'customer'" v-model:copyForm="copyForm"
                v-model:customerDialogFormVisible="dialogFormVisible" :addOrEdit="addOrEdit" :form="form" :title="title"
                @beforeClose="handleBeforeClose" @submit="handleSubmit"/>
      <Coal v-if="tabName === 'coal'" v-model:coalDialogFormVisible="dialogFormVisible" v-model:copyForm="copyForm"
            :addOrEdit="addOrEdit" :form="form" :title="title" @submit="handleSubmit"/>
      <coalQualityMaintenance v-if="tabName === 'coalQualityMaintenance'" v-model:coalQualityMaintenanceDialogFormVisible="dialogFormVisible"
                              v-model:copyForm="copyForm" :addOrEdit="addOrEdit"
                              :form="form"
                              :title="title" @submit="handleSubmit"/>
      <coalMeiZhiZiDuanWeiHu v-if="tabName === 'coalMeiZhiZiDuanWeiHu'" v-model:coalMaintenanceFieldDialogVisible="dialogFormVisible"
                             v-model:copyForm="copyForm" :addOrEdit="addOrEdit" :form="form"
                             :title="title"
                             @submit="handleSubmit"/>
      <pagination
        v-if="total > 0"
        :layout="'total, prev, pager, next, jumper'"
        :limit="pageSizes"
        :page="pageNum"
        :total="total"
        @pagination="handPagination"
      />
      <Supplier
        v-if="tabName === 'supplier'"
        v-model:copyForm="copyForm"
        v-model:supplierDialogFormVisible="dialogFormVisible"
        :addOrEdit="addOrEdit"
        :form="form"
        :title="title"
        @beforeClose="handleBeforeClose"
        @submit="handleSubmit"
        @update:dialogFormVisible="handleDialogFormVisible"
      />
      <Customer
        v-if="tabName === 'customer'"
        v-model:copyForm="copyForm"
        v-model:customerDialogFormVisible="dialogFormVisible"
        :addOrEdit="addOrEdit"
        :form="form"
        :title="title"
        @beforeClose="handleBeforeClose"
        @submit="handleSubmit"
      />
      <Coal
        v-if="tabName === 'coal'"
        v-model:coalDialogFormVisible="dialogFormVisible"
        v-model:copyForm="copyForm"
        :addOrEdit="addOrEdit"
        :form="form"
        :title="title"
        @submit="handleSubmit"
      />
      <coalQualityMaintenance
        v-if="tabName === 'coalQualityMaintenance'"
        v-model:coalQualityMaintenanceDialogFormVisible="dialogFormVisible"
        v-model:copyForm="copyForm"
        :addOrEdit="addOrEdit"
        :form="form"
        :title="title"
        @submit="handleSubmit"
      />
      <coalMeiZhiZiDuanWeiHu
        v-if="tabName === 'coalMeiZhiZiDuanWeiHu'"
        v-model:coalMaintenanceFieldDialogVisible="dialogFormVisible"
        v-model:copyForm="copyForm"
        :addOrEdit="addOrEdit"
        :form="form"
        :title="title"
        @submit="handleSubmit"
      />
      <Descriptions
        v-model:descriptionsVisible="showDialog"
        title="供应商详情"
        :formData="supplierData"
        :fieldLabels="supplierFieldLabels"
        :column="2"
        :isViewOnly="false"
        :border="true"
        :showOperations="true"
        descriptionsTitle="基本信息"
        :fieldConfig="fieldConfig"
        :excludeFields="excludeFields"
        @edit="descriptionsHandleEdit"
        @close="handleClose"
      />
    </el-card>
  </div>
</template>
<script setup>
import {computed, getCurrentInstance, onMounted, reactive, ref, nextTick} from "vue";
import {ElMessage, ElMessageBox} from "element-plus";
import {Delete, Download, Plus} from "@element-plus/icons-vue";
import {
  computed,
  getCurrentInstance,
  onMounted,
  reactive,
  ref,
  nextTick,
} from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { Delete, Download, Plus } from "@element-plus/icons-vue";
// ===== ç»„件导入 =====
import DataTable from "@/components/Table/ETable.vue";
@@ -77,28 +185,95 @@
import Coal from "./mould/coal.vue";
import coalQualityMaintenance from "./mould/coalQualityMaintenance.vue";
import coalMeiZhiZiDuanWeiHu from "./mould/coalMeiZhiZiDuanWeiHu.vue";
import Descriptions from "@/components/dialog/Descriptions.vue";
// ===== API æœåС坼入 =====
import {delSupply, getSupply} from "@/api/basicInformation/supplier.js";
import {delCoalInfo, getCoalInfo} from "@/api/basicInformation/coal.js";
import {testUserList} from "@/api/tool/publicInterface.js";
import {getAreaOptions} from "@/api/system/area.js";
import {delCustomer, getCustomerList} from "@/api/basicInformation/customer.js";
import {coalField, deleteCoalField} from "@/api/basicInformation/coalFieldMaintenance.js";
import {getCoalFieldList, getCoalPlanList} from "@/api/basicInformation/coalQualityMaintenance";
import { delSupply, getSupply } from "@/api/basicInformation/supplier.js";
import { delCoalInfo, getCoalInfo } from "@/api/basicInformation/coal.js";
import { testUserList } from "@/api/tool/publicInterface.js";
import { getAreaOptions } from "@/api/system/area.js";
import {
  delCustomer,
  getCustomerList,
} from "@/api/basicInformation/customer.js";
import {
  coalField,
  deleteCoalField,
} from "@/api/basicInformation/coalFieldMaintenance.js";
import {
  getCoalFieldList,
  getCoalPlanList,
} from "@/api/basicInformation/coalQualityMaintenance";
const {proxy} = getCurrentInstance();
const { proxy } = getCurrentInstance();
import router from "@/router";
// ===== å“åº”式状态管理 =====
const jump = () => {
};
// å¼¹çª—控制状态
const showDialog = ref(false)
const supplierFieldLabels = {
  supplierName: '供应商名称',
  taxpayerId: '统一社会信用代码',
}
// æ•°æ®å¯¹è±¡
const supplierData = ref({
  supplierName: "测试供应商",
  taxpayerId: "91320000MA1N2P3Q4R",
  contactPerson: "张三",
  contactPhone: "13800138000",
  bankAccount: "6222024200019999999",
  bankName: "中国工商银行",
  businessAddress: "江苏省苏州市工业园区星湖街328号",
  contactAddress: "江苏省苏州市姑苏区观前街100号",
  createTime: "2024-01-15T10:30:00",
  updateTime: "2024-06-25T14:20:00",
  id: 123,
})
// å­—段配置
const fieldConfig = ref({
  supplierName: {
    label: '供应商名称',
    span: 2  // è·¨2列显示
  },
  taxpayerId: {
    label: '统一社会信用代码'
  },
  contactPhone: {
    label: '联系电话',
    formatter: (value) => value || '暂无联系方式'
  },
  createTime: {
    label: '创建时间',
    formatter: (value) => new Date(value).toLocaleDateString('zh-CN')
  },
  businessAddress: {
    label: '详细经营地址',
    span: 2
  },
  contactAddress: {
    label: '详细联系地址',
    span: 2
  }
})
// æŽ’除不显示的字段
const excludeFields = ref(["id", "updateTime", "deleted"]);
// äº‹ä»¶å¤„理
const descriptionsHandleEdit = (data) => {
  console.log("编辑数据:", data);
  // è·³è½¬åˆ°ç¼–辑页面或打开编辑弹窗
};
const handleClose = () => {
  console.log("弹窗关闭");
};
const dialogFormVisible = ref(false);
const form = ref({});
const title = ref("");
const copyForm = ref({});
const addOrEdit = ref("add");
const descriptionsVisible = ref(false);
// æ•°æ®ç¼“存映射
const userList = ref([]);
@@ -131,11 +306,11 @@
// æ ‡ç­¾é¡µé…ç½®
const tabs = reactive([
  {name: "supplier", label: "供应商信息"},
  {name: "customer", label: "客户信息"},
  {name: "coal", label: "煤种信息"},
  {name: "coalQualityMaintenance", label: "煤质方案"},
  {name: "coalMeiZhiZiDuanWeiHu", label: "煤质字段"}
  { name: "supplier", label: "供应商信息" },
  { name: "customer", label: "客户信息" },
  { name: "coal", label: "煤种信息" },
  { name: "coalQualityMaintenance", label: "煤质方案" },
  { name: "coalMeiZhiZiDuanWeiHu", label: "煤质字段" },
]);
// ===== å·¥å…·å‡½æ•° =====
@@ -153,7 +328,7 @@
      buildAddressMap(res.data);
    }
  } catch (error) {
    console.error('获取地址选项失败:', error);
    console.error("获取地址选项失败:", error);
  }
};
@@ -164,11 +339,11 @@
 */
const buildAddressMap = (areaData) => {
  const buildMap = (list, pathList = []) => {
    list.forEach(item => {
    list.forEach((item) => {
      const currentPath = [...pathList, item.label];
      addressMap.value[item.id] = {
        name: item.label,
        fullPath: currentPath.join(' / ')
        fullPath: currentPath.join(" / "),
      };
      if (item.children && item.children.length > 0) {
        buildMap(item.children, currentPath);
@@ -185,19 +360,26 @@
 * @description å°†åœ°å€ID数组转换为可读的地址字符串
 */
const formatAddressArray = (addressIds) => {
  if (!addressMap.value || Object.keys(addressMap.value).length === 0 ||
      !addressIds || !Array.isArray(addressIds) || addressIds.length === 0 ||
      addressIds.every(id => !id)) {
    return '--';
  if (
    !addressMap.value ||
    Object.keys(addressMap.value).length === 0 ||
    !addressIds ||
    !Array.isArray(addressIds) ||
    addressIds.length === 0 ||
    addressIds.every((id) => !id)
  ) {
    return "--";
  }
  const addressNames = addressIds.map(id => addressMap.value[id]?.name || '--');
  const addressNames = addressIds.map(
    (id) => addressMap.value[id]?.name || "--"
  );
  if (addressNames.every(name => name === '--')) {
    return '--';
  if (addressNames.every((name) => name === "--")) {
    return "--";
  }
  return addressNames.filter(name => name !== '--').join(' / ');
  return addressNames.filter((name) => name !== "--").join(" / ");
};
/**
@@ -209,12 +391,12 @@
    const res = await testUserList();
    if (res && res.data) {
      userList.value = res.data;
      userList.value.forEach(user => {
      userList.value.forEach((user) => {
        userMap.value[user.userId] = user.username;
      });
    }
  } catch (error) {
    console.error('获取用户列表失败:', error);
    console.error("获取用户列表失败:", error);
  }
};
@@ -224,12 +406,12 @@
 */
const coalFieldData = async () => {
  try {
    const {data, code} = await getCoalFieldList();
    const { data, code } = await getCoalFieldList();
    if (code === 200) {
      coalFieldList.value = data;
    }
  } catch (error) {
    console.error('获取煤质字段数据失败:', error);
    console.error("获取煤质字段数据失败:", error);
  }
};
@@ -240,10 +422,10 @@
 * @description é€šè¿‡å­—段ID匹配对应的字段名称
 */
const getFieldDisplayName = (fieldId) => {
  if (!fieldId) return '--';
  if (!fieldId) return "--";
  const numId = parseInt(fieldId);
  const matchedField = coalFieldList.value.find(item => item.id === numId);
  const matchedField = coalFieldList.value.find((item) => item.id === numId);
  return matchedField ? matchedField.fieldName : numId;
};
@@ -254,7 +436,7 @@
 * å½“前标签页是否支持导出功能
 */
const canExport = computed(() => {
  return ['supplier', 'customer'].includes(tabName.value);
  return ["supplier", "customer"].includes(tabName.value);
});
/**
@@ -266,7 +448,7 @@
    customer: "供应商/识别码/详细地址",
    coal: "请输入搜索信息",
    coalQualityMaintenance: "请输入搜索信息",
    coalMeiZhiZiDuanWeiHu: "请输入搜索信息"
    coalMeiZhiZiDuanWeiHu: "请输入搜索信息",
  };
  return placeholderMap[tabName.value] || "请输入搜索信息";
});
@@ -275,7 +457,13 @@
 * æ˜¯å¦æ˜¾ç¤ºæœç´¢æ¡†
 */
const shouldShowSearch = computed(() => {
  return ['supplier', 'customer', 'coal', 'coalQualityMaintenance', 'coalMeiZhiZiDuanWeiHu'].includes(tabName.value);
  return [
    "supplier",
    "customer",
    "coal",
    "coalQualityMaintenance",
    "coalMeiZhiZiDuanWeiHu",
  ].includes(tabName.value);
});
/**
@@ -294,8 +482,8 @@
 * ä¾›åº”商表格列配置
 */
const supplierColumns = ref([
  {prop: "supplierName", label: "供应商名称", minWidth: 100},
  {prop: "taxpayerId", label: "统一人识别号", minWidth: 170},
  { prop: "supplierName", label: "供应商名称", minWidth: 100 },
  { prop: "taxpayerId", label: "统一人识别号", minWidth: 170 },
  {
    prop: "bids",
    label: "经营地址",
@@ -304,12 +492,11 @@
    formatter: (row) => {
      const addressIds = [row.bprovinceId, row.bcityId, row.bdistrictId];
      return formatAddressArray(addressIds);
    }
    },
  },
  {prop: "businessAddress", label: "经营详细地址", minWidth: 150},
  {prop: "bankAccount", label: "开户行", minWidth: 120},
  {prop: "bankName", label: "银行账号", minWidth: 150},
  {prop: "contactPerson", label: "联系人", minWidth: 100},
  { prop: "businessAddress", label: "经营详细地址", minWidth: 150 },
  { prop: "bankAccount", label: "开户行", minWidth: 120 },
  { prop: "contactPerson", label: "联系人", minWidth: 100 },
  {
    prop: "cids",
    label: "联系人地址",
@@ -318,33 +505,36 @@
    formatter: (row) => {
      const addressIds = [row.cprovinceId, row.ccityId, row.cdistrictId];
      return formatAddressArray(addressIds);
    }
    },
  },
  {prop: "contactAddress", label: "联系人详细地址", minWidth: 120},
  {prop: "updateTime", label: "维护日期", minWidth: 120},
  { prop: "contactAddress", label: "联系人详细地址", minWidth: 120 },
]);
/**
 * å®¢æˆ·è¡¨æ ¼åˆ—配置
 */
const customerColumns = ref([
  {prop: "customerName", label: "客户名称", minWidth: 100},
  {prop: "taxpayerId", label: "统一人识别号", minWidth: 120},
  { prop: "customerName", label: "客户名称", minWidth: 100 },
  { prop: "taxpayerId", label: "统一人识别号", minWidth: 120 },
  {
    prop: "bids",
    label: "经营地址",
    minWidth: 150,
    showOverflowTooltip: true,
    formatter: (row) => {
      const addressIds = [row.businessProvinceId, row.businessCityId, row.businessDistrictId];
      const addressIds = [
        row.businessProvinceId,
        row.businessCityId,
        row.businessDistrictId,
      ];
      return formatAddressArray(addressIds);
    }
    },
  },
  {prop: "businessAddress", label: "详细地址", minWidth: 150},
  {prop: "bankName", label: "开户行", minWidth: 120},
  {prop: "bankAccount", label: "银行账号", minWidth: 150},
  {prop: "contactPerson", label: "联系人", minWidth: 100},
  {prop: "contactPhone", label: "联系人电话", minWidth: 100},
  { prop: "businessAddress", label: "详细地址", minWidth: 150 },
  { prop: "bankName", label: "开户行", minWidth: 120 },
  { prop: "bankAccount", label: "银行账号", minWidth: 150 },
  { prop: "contactPerson", label: "联系人", minWidth: 100 },
  { prop: "contactPhone", label: "联系人电话", minWidth: 100 },
  {
    prop: "cids",
    label: "联系人地址",
@@ -353,39 +543,39 @@
    formatter: (row) => {
      const addressIds = [row.provinceId, row.cityId, row.districtId];
      return formatAddressArray(addressIds);
    }
    },
  },
  {prop: "contactAddress", label: "联系人详细地址", minWidth: 150},
  {prop: "updateTime", label: "维护日期", minWidth: 100},
  { prop: "contactAddress", label: "联系人详细地址", minWidth: 150 },
  { prop: "updateTime", label: "维护日期", minWidth: 100 },
]);
/**
 * ç…¤ç§è¡¨æ ¼åˆ—配置
 */
const coalColumns = ref([
  {prop: "coal", label: "煤种名称", minWidth: 200},
  { prop: "coal", label: "煤种名称", minWidth: 200 },
  {
    prop: "maintainerId",
    label: "维护人",
    minWidth: 120,
    formatter: (row, column, cellValue) => {
      if (!userMap.value || Object.keys(userMap.value).length === 0) {
        return '--';
        return "--";
      }
      if (cellValue === null || cellValue === undefined || cellValue === '') {
        return '--';
      if (cellValue === null || cellValue === undefined || cellValue === "") {
        return "--";
      }
      return userMap.value[cellValue] || '--';
    }
      return userMap.value[cellValue] || "--";
    },
  },
  {prop: "maintenanceDate", label: "维护日期", minWidth: 150},
  { prop: "maintenanceDate", label: "维护日期", minWidth: 150 },
]);
/**
 * ç…¤è´¨æ–¹æ¡ˆè¡¨æ ¼åˆ—配置
 */
const coalQualityMaintenanceColumns = ref([
  {prop: "plan", label: "方案名称", minWidth: 100},
  { prop: "plan", label: "方案名称", minWidth: 100 },
  {
    prop: "fieldIds",
    label: "字段名称",
@@ -394,20 +584,20 @@
    slot: true,
    formatter: (row, column, cellValue) => {
      if (Array.isArray(cellValue)) {
        return cellValue.map(item => item);
        return cellValue.map((item) => item);
      }
      return cellValue || '--';
    }
      return cellValue || "--";
    },
  },
  {prop: "schemeDesc", label: "字段描述", minWidth: 100},
  { prop: "schemeDesc", label: "字段描述", minWidth: 100 },
]);
/**
 * ç…¤è´¨å­—段表格列配置
 */
const coalMeiZhiZiDuanWeiHuColumns = ref([
  {prop: "fieldName", label: "字段名称", minWidth: 200},
  {prop: "fieldDescription", label: "字段描述", minWidth: 200},
  { prop: "fieldName", label: "字段名称", minWidth: 200 },
  { prop: "fieldDescription", label: "字段描述", minWidth: 200 },
]);
// ===== äº‹ä»¶å¤„理函数 =====
@@ -449,7 +639,7 @@
    coalMeiZhiZiDuanWeiHu: () => {
      columns.value = coalMeiZhiZiDuanWeiHuColumns.value;
      getList();
    }
    },
  };
  // æ‰§è¡Œå¯¹åº”的配置函数
@@ -495,17 +685,22 @@
 * @description æ ¹æ®æ ‡ç­¾é¡µç±»åž‹è®¾ç½®å¼¹çª—标题并打开弹窗
 */
const handleAddEdit = (currentTabName) => {
  const actionText = addOrEdit.value === "add" ? "新增" : "编辑";
  const actionText =
    addOrEdit.value === "add"
      ? "新增"
      : addOrEdit.value === "edit"
      ? "编辑"
      : "查看";
  const tabTitleMap = {
    supplier: "供应商信息",
    customer: "客户信息",
    coal: "煤种信息",
    coalQualityMaintenance: "煤质方案维护",
    coalMeiZhiZiDuanWeiHu: "煤质字段维护"
    coalMeiZhiZiDuanWeiHu: "煤质字段维护",
  };
  title.value = `${actionText}${tabTitleMap[currentTabName] || ''}`;
  title.value = `${actionText}${tabTitleMap[currentTabName] || ""}`;
  openDialog();
};
@@ -514,7 +709,7 @@
 * @description æ ¹æ®ç¼–辑状态决定是否复制表单数据
 */
const openDialog = () => {
  if (addOrEdit.value === "edit") {
  if (addOrEdit.value === "edit" || addOrEdit.value === "viewRow") {
    copyForm.value = JSON.parse(JSON.stringify(form.value));
  } else {
    form.value = {};
@@ -580,8 +775,16 @@
  }
  // æž„建客户业务地址数组
  if (form.value.businessCityId && form.value.businessDistrictId && form.value.businessProvinceId) {
    form.value.bids = [row.businessProvinceId, row.businessCityId, row.businessDistrictId];
  if (
    form.value.businessCityId &&
    form.value.businessDistrictId &&
    form.value.businessProvinceId
  ) {
    form.value.bids = [
      row.businessProvinceId,
      row.businessCityId,
      row.businessDistrictId,
    ];
  }
  // æž„建客户联系地址数组
@@ -594,6 +797,49 @@
};
/**
 * æŸ¥çœ‹æŒ‰é’®ç‚¹å‡»å¤„理
 * @param {Object} row - è¡Œæ•°æ®
 * @description å¤„理查看操作,构建地址数组并打开查看弹窗
 */
const handleView = (row) => {
  console.log("查看行数据:", row);
  // æ‹¿åˆ°æ‰€æœ‰çš„keys
  const keys = Object.keys(row);
  console.log("所有keys:", keys);
  showDialog.value = true;
  // form.value = JSON.parse(JSON.stringify(row));
  // console.log("查看行数据:", form.value);
  // // æž„建供应商业务地址数组
  // if (form.value.bprovinceId && form.value.bdistrictId && form.value.bcityId) {
  //   form.value.bids = [row.bprovinceId, row.bcityId, row.bdistrictId];
  // }
  // // æž„建供应商联系地址数组
  // if (form.value.cprovinceId && form.value.cdistrictId && form.value.ccityId) {
  //   form.value.cids = [row.cprovinceId, row.ccityId, row.cdistrictId];
  // }
  // // æž„建客户业务地址数组
  // if (
  //   form.value.businessCityId &&
  //   form.value.businessDistrictId &&
  //   form.value.businessProvinceId
  // ) {
  //   form.value.bids = [
  //     row.businessProvinceId,
  //     row.businessCityId,
  //     row.businessDistrictId,
  //   ];
  // }
  // // æž„建客户联系地址数组
  // if (form.value.cityId && form.value.districtId && form.value.provinceId) {
  //   form.value.cids = [row.provinceId, row.cityId, row.districtId];
  // }
  // addOrEdit.value = "viewRow";
  // handleAddEdit(tabName.value);
};
/**
 * æ‰¹é‡åˆ é™¤å¤„理
 * @description æ‰¹é‡åˆ é™¤é€‰ä¸­çš„记录
 */
@@ -603,7 +849,7 @@
    return;
  }
  const deleteIds = selectedRows.value.map(item => item.id);
  const deleteIds = selectedRows.value.map((item) => item.id);
  try {
    await ElMessageBox.confirm("确定删除选中的数据吗?", "提示", {
@@ -616,10 +862,10 @@
      supplier: delSupply,
      coal: delCoalInfo,
      coalQualityMaintenance: () => {
        throw new Error('delCoalQuality API not imported');
        throw new Error("delCoalQuality API not imported");
      },
      customer: delCustomer,
      coalMeiZhiZiDuanWeiHu: deleteCoalField
      coalMeiZhiZiDuanWeiHu: deleteCoalField,
    };
    const deleteApi = deleteApiMap[tabName.value];
@@ -627,7 +873,7 @@
      ElMessage.error("删除接口未配置");
      return;
    }
    console.log(deleteIds)
    console.log(deleteIds);
    const res = await deleteApi(deleteIds);
    if (res.code !== 200 && res.msg !== "操作成功") {
@@ -638,8 +884,8 @@
    ElMessage.success("删除成功");
    await getList();
  } catch (error) {
    if (error.message !== 'cancel') {
      console.error('删除操作失败:', error);
    if (error.message !== "cancel") {
      console.error("删除操作失败:", error);
      ElMessage.error("删除失败,请稍后再试");
    } else {
      ElMessage.info("已取消删除操作");
@@ -662,10 +908,10 @@
 */
const handleExport = () => {
  const exportConfig = {
    supplier: {api: "/supply/export", name: "供应商信息"},
    customer: {api: "/customer/export", name: "客户信息"},
    coal: {api: "/supply/export", name: "煤种信息"},
    coalQualityMaintenance: {api: "/supply/export", name: "煤质维护信息"}
    supplier: { api: "/supply/export", name: "供应商信息" },
    customer: { api: "/customer/export", name: "客户信息" },
    coal: { api: "/supply/export", name: "煤种信息" },
    coalQualityMaintenance: { api: "/supply/export", name: "煤质维护信息" },
  };
  const config = exportConfig[tabName.value];
@@ -680,7 +926,11 @@
 * @param {string} name - å¯¼å‡ºæ–‡ä»¶åå‰ç¼€
 */
const exportData = (api, name) => {
  proxy.download(api, {...queryParams}, `${name}${new Date().getTime()}.xlsx`);
  proxy.download(
    api,
    { ...queryParams },
    `${name}${new Date().getTime()}.xlsx`
  );
  ElMessage.success("导出数据:" + name);
};
// ===== æ•°æ®èŽ·å–å‡½æ•° =====
@@ -702,11 +952,13 @@
    customer: () => getCustomerList(apiParams),
    coal: () => getCoalInfo(apiParams),
    coalQualityMaintenance: () => getCoalPlanList(apiParams),
    coalMeiZhiZiDuanWeiHu: () => coalField(apiParams)
    coalMeiZhiZiDuanWeiHu: () => coalField(apiParams),
  };
  const apiFunction = apiMap[tabName.value];
  return apiFunction ? apiFunction() : Promise.reject(new Error('未找到对应的API接口'));
  return apiFunction
    ? apiFunction()
    : Promise.reject(new Error("未找到对应的API接口"));
};
/**
@@ -716,17 +968,17 @@
const getList = async () => {
  try {
    loading.value = true;
    const {data, code} = await selectInterface();
    const { data, code } = await selectInterface();
    if (code !== 200) {
      ElMessage.error("获取数据失败:" + (data?.msg || '未知错误'));
      ElMessage.error("获取数据失败:" + (data?.msg || "未知错误"));
      return;
    }
    tableData.value = data.records || [];
    total.value = data.total || 0;
  } catch (error) {
    console.error('获取列表数据失败:', error);
    console.error("获取列表数据失败:", error);
    ElMessage.error("获取数据失败,请稍后再试");
  } finally {
    loading.value = false;
@@ -742,12 +994,12 @@
  try {
    // å¹¶è¡Œæ‰§è¡Œåˆå§‹åŒ–操作
    await Promise.all([
      handleTabClick({props: {name: "supplier"}}),
      handleTabClick({ props: { name: "supplier" } }),
      fetchAreaOptions(),
      getUserList()
      getUserList(),
    ]);
  } catch (error) {
    console.error('组件初始化失败:', error);
    console.error("组件初始化失败:", error);
    ElMessage.error("页面初始化失败,请刷新重试");
  }
});
@@ -802,4 +1054,4 @@
.main-container {
  background: red !important;
}
</style>
</style>
src/views/basicInformation/mould/supplier.vue
@@ -1,48 +1,135 @@
<template>
  <div>
    <el-dialog v-model="dialogVisible" :title="title" width="600" :close-on-click-modal="false"
               :before-close="handleClose">
      <el-form ref="formRef" style="max-width: 400px; margin: 0 auto" :model="formData" :rules="rules"
               label-width="auto">
        <el-form-item label="供应商名称" prop="supplierName">
          <el-input v-model="formData.supplierName" placeholder="请输入供货商名称"/>
    <el-dialog
      v-model="dialogVisible"
      :title="title"
      width="600"
      :close-on-click-modal="false"
      :before-close="handleClose"
    >
      <el-form
        ref="formRef"
        style="max-width: 400px; margin: 0 auto"
        :model="formData"
        :rules="rules"
        label-width="auto"
      >        <el-form-item
          label="供应商名称"
          prop="supplierName"
        >
          <el-input
            v-model="formData.supplierName"
            placeholder="请输入供货商名称"
            :disabled="isViewMode"
          />
        </el-form-item>
        <el-form-item label="纳税人识别号" prop="taxpayerId">
          <el-input v-model="formData.taxpayerId" placeholder="请输入纳税人识别号"/>
        <el-form-item
          label="纳税人识别号"
          prop="taxpayerId"
        >
          <el-input
            v-model="formData.taxpayerId"
            placeholder="请输入纳税人识别号"
            :disabled="isViewMode"
          />
        </el-form-item>
        <el-form-item label="经营地址" prop="bids">
          <el-cascader placeholder="请选择经营地址" size="default" :options="addressSelectOptions"
                       v-model="formData.bids"
                       :props="cascaderProps" @change="handleChange">
        <el-form-item
          label="经营地址"
          prop="bids"
        >
          <el-cascader
            placeholder="请选择经营地址"
            size="default"
            :options="addressSelectOptions"
            v-model="formData.bids"
            :props="cascaderProps"
            @change="handleChange"
            :disabled="isViewMode"
          >
          </el-cascader>
        </el-form-item>
        <el-form-item label="详细地址" prop="businessAddress">
          <el-input v-model="formData.businessAddress" placeholder="请输入客户详细地址"/>
        <el-form-item
          label="详细地址"
          prop="businessAddress"
        >
          <el-input
            v-model="formData.businessAddress"
            placeholder="请输入客户详细地址"
            :disabled="isViewMode"
          />
        </el-form-item>
        <el-form-item label="开户行" prop="bankAccount">
          <el-input v-model="formData.bankAccount" placeholder="请输入开户行"/>
        <el-form-item
          label="开户行"
          prop="bankAccount"
        >
          <el-input
            v-model="formData.bankAccount"
            placeholder="请输入开户行"
            :disabled="isViewMode"
          />
        </el-form-item>
        <el-form-item label="银行账户" prop="bankName">
          <el-input v-model="formData.bankName" placeholder="请输入银行账户"/>
        <el-form-item
          label="银行账户"
          prop="bankName"
        >
          <el-input
            v-model="formData.bankName"
            placeholder="请输入银行账户"
            :disabled="isViewMode"
          />
        </el-form-item>
        <el-form-item label="联系人" prop="contactPerson">
          <el-input v-model="formData.contactPerson" placeholder="请输入联系人"/>
        <el-form-item
          label="联系人"
          prop="contactPerson"
        >
          <el-input
            v-model="formData.contactPerson"
            placeholder="请输入联系人"
            :disabled="isViewMode"
          />
        </el-form-item>
        <el-form-item label="联系人电话" prop="contactPhone">
          <el-input v-model="formData.contactPhone" placeholder="请输入联系人电话"/>
        <el-form-item
          label="联系人电话"
          prop="contactPhone"
        >
          <el-input
            v-model="formData.contactPhone"
            placeholder="请输入联系人电话"
            :disabled="isViewMode"
          />
        </el-form-item>
        <el-form-item label="联系人地址" prop="cids">
          <el-cascader placeholder="请选择联系人地址" size="default" :options="addressSelectOptions"
                       v-model="formData.cids"
                       :props="cascaderProps" @change="handleChange">
        <el-form-item
          label="联系人地址"
          prop="cids"
        >
          <el-cascader
            placeholder="请选择联系人地址"
            size="default"
            :options="addressSelectOptions"
            v-model="formData.cids"
            :props="cascaderProps"
            @change="handleChange"
            :disabled="isViewMode"
          >
          </el-cascader>
        </el-form-item>
        <el-form-item label="联系人详细地址" prop="contactAddress">
          <el-input v-model="formData.contactAddress" placeholder="请输入联系人地址"/>
        <el-form-item
          label="联系人详细地址"
          prop="contactAddress"
        >
          <el-input
            v-model="formData.contactAddress"
            placeholder="请输入联系人地址"
            :disabled="isViewMode"
          />
        </el-form-item>
        <el-form-item class="dialog-footer">
          <el-button v-if="addOrEdit === 'edit'" @click="resetForm">重置</el-button>
          <el-button v-if="addOrEdit === 'add'" @click="cancelForm">取消</el-button>
          <el-button v-if="addOrEdit === 'edit'" @click="resetForm"
            >重置</el-button
          >
          <el-button v-if="addOrEdit !== 'edit'" @click="cancelForm"
            >取消</el-button
          >
          <el-button type="primary" @click="submitForm"> ç¡®å®š</el-button>
        </el-form-item>
      </el-form>
@@ -51,15 +138,14 @@
</template>
<script setup>
import {ref, watch, defineProps, onMounted} from "vue";
import {addOrEditSupply} from "@/api/basicInformation/supplier";
import {getAreaOptions} from "@/api/system/area.js";
import { ref, watch, defineProps, onMounted, computed, reactive } from "vue";
import { addOrEditSupply } from "@/api/basicInformation/supplier";
import { getAreaOptions } from "@/api/system/area.js";
const props = defineProps({
  beforeClose: {
    type: Function,
    default: () => {
    },
    default: () => {},
  },
  form: {
    type: Object,
@@ -75,21 +161,24 @@
  },
});
// è®¡ç®—属性:统一控制是否禁用
const isViewMode = computed(() => props.addOrEdit === 'viewRow');
const emit = defineEmits(["submit", "handleBeforeClose"]);
const copyForm = defineModel("copyForm", {
  required: true,
  type: Object,
});
onMounted(() => {
  fetchAreaOptions()
})
  fetchAreaOptions();
});
// ä¿®æ”¹æ ‘形选择的映射
const cascaderProps = ref({
  value: 'id', // æŒ‡å®švalue字段为id
  label: 'label', // æŒ‡å®šlabel字段
  children: 'children' // æŒ‡å®šå­èŠ‚ç‚¹å­—æ®µ
})
  value: "id", // æŒ‡å®švalue字段为id
  label: "label", // æŒ‡å®šlabel字段
  children: "children", // æŒ‡å®šå­èŠ‚ç‚¹å­—æ®µ
});
// åœ°å€é€‰æ‹©æ•°æ®
const addressSelectOptions = ref([]);
@@ -100,21 +189,21 @@
  if (res.code === 200) {
    addressSelectOptions.value = res.data;
  }
}
};
// å¤„理地址数据转换
function mapAddress(list) {
  return list.map(item => ({
  return list.map((item) => ({
    value: item.id,
    label: item.name,
    children: item.children ? mapAddress(item.children) : undefined
    children: item.children ? mapAddress(item.children) : undefined,
  }));
}
// è¡¨å•引用
const formRef = ref(null);
// è¡¨å•数据
const formData = ref({...props.form});
const formData = ref({ ...props.form });
// å¼¹çª—可见性
const dialogVisible = defineModel("supplierDialogFormVisible", {
  required: true,
@@ -122,19 +211,19 @@
});
// ç›‘听外部传入的表单数据变化
watch(
    () => props.form,
    (newVal) => {
      formData.value = {...newVal};
    },
    {deep: true}
  () => props.form,
  (newVal) => {
    formData.value = { ...newVal };
  },
  { deep: true }
);
// ç›‘听内部弹窗状态变化
watch(
    () => dialogVisible.value,
    (newVal) => {
      emit("update:supplierDialogFormVisible", newVal);
    }
  () => dialogVisible.value,
  (newVal) => {
    emit("update:supplierDialogFormVisible", newVal);
  }
);
// å¤„理地址选择变化
const handleChange = (value) => {
@@ -146,23 +235,23 @@
  await formRef.value.validate(async (valid, fields) => {
    if (valid) {
      const obj = ref({});
      if (props.title.includes('新增')) {
      if (props.title.includes("新增")) {
        let result = await addOrEditSupply({
          ...formData.value,
        })
        });
        obj.value = {
          title: "新增",
          ...formData.value,
          result
          result,
        };
      } else {
        let result = await addOrEditSupply({
          ...formData.value,
        })
        });
        obj.value = {
          title: "编辑",
          ...formData.value,
          result
          result,
        };
      }
      emit("submit", obj.value);
@@ -187,11 +276,11 @@
};
const rules = reactive({
  supplierName: [
    {required: true, message: "请输入供货商名称", trigger: "blur"},
    { required: true, message: "请输入供货商名称", trigger: "blur" },
  ],
  taxpayerId: [
    {required: true, message: "请正确输入纳税人识别号", trigger: "blur"},
    {min: 17, max: 20, message: "请输入17-20位纳税人识别号", trigger: "blur"},
    { required: true, message: "请正确输入纳税人识别号", trigger: "blur" },
    { min: 17, max: 20, message: "请输入17-20位纳税人识别号", trigger: "blur" },
  ],
  // bids: [
  //   {
@@ -200,12 +289,12 @@
  //     trigger: "change",
  //   },
  // ],
  bankName: [{required: true, message: "请输入银行账户", trigger: "blur"}],
  bankAccount: [{required: true, message: "请输入开户行", trigger: "blur"}],
  contactPerson: [{required: true, message: "联系人", trigger: "blur"}],
  bankName: [{ required: true, message: "请输入银行账户", trigger: "blur" }],
  bankAccount: [{ required: true, message: "请输入开户行", trigger: "blur" }],
  contactPerson: [{ required: true, message: "联系人", trigger: "blur" }],
  contactPhone: [
    {required: true, message: "请输入联系人", trigger: "blur"},
    {min: 11, max: 11, message: "请输入11位联系人电话", trigger: "blur"},
    { required: true, message: "请输入联系人", trigger: "blur" },
    { min: 11, max: 11, message: "请输入11位联系人电话", trigger: "blur" },
  ],
});
</script>
@@ -216,4 +305,4 @@
  margin-top: 20px;
  flex-direction: column;
}
</style>
</style>
src/views/production/index.vue
@@ -81,10 +81,15 @@
import {useTableData} from "./components/useTableData.js";
import {useDialog} from "./components/useDialog.js";
import {useCoalData} from "./components/useCoalData.js";
import {getCoalInfoList} from "@/api/production";
// è¡¨æ ¼åˆ—配置
const columns = [
  {prop: "coal", label: "煤种", minWidth: 150, slot: 'coal'},
  {prop: "coalId", label: "煤种", minWidth: 150,
    formatter: (row) => {
      return coalInfoList.value.find(item => item.id == row.coalId)?.coal || '--';
    }
  },
  {prop: "productionQuantity", label: "生产数量", minWidth: 120},
  {prop: "laborCost", label: "人工成本", minWidth: 150},
  {prop: "energyConsumptionCost", label: "能耗成本", minWidth: 120},
@@ -134,10 +139,13 @@
    ElMessage.success("操作成功");
  });
};
const coalInfoList = ref([]);
// ç»„件挂载时加载数据
onMounted(async () => {
  await getCoalData(); // é¢„加载煤种数据
  getList();
  let res = await getCoalInfoList()
  coalInfoList.value = res.data;
});
</script>