From e85670cc7beaa7616453a30823fd08c149ab442b Mon Sep 17 00:00:00 2001
From: 张诺 <zhang_12370@163.com>
Date: 星期四, 29 五月 2025 16:18:20 +0800
Subject: [PATCH] 基础信息模块and采购登记

---
 src/hooks/useFormData.js                      |   18 
 src/views/basicInformation/index.vue          |  528 ++++++++++++
 src/views/procureMent/index.vue               |  308 +++++++
 index.html                                    |    1 
 src/views/basicInformation/mould/coal.vue     |  140 +++
 src/hooks/usePaginationApi.jsx                |  145 +++
 src/views/production/index.vue                |  278 ++++++
 src/views/basicInformation/mould/supplier.vue |  154 +++
 src/components/Table/ETable.vue               |  156 +++
 src/views/basicInformation/indexs.vue         |  541 +++++++++++++
 src/views/basicInformation/mould/customer.vue |  140 +++
 11 files changed, 2,409 insertions(+), 0 deletions(-)

diff --git a/index.html b/index.html
index d20d02e..b9105d6 100644
--- a/index.html
+++ b/index.html
@@ -197,6 +197,7 @@
       color: #FFF;
       opacity: 0.5;
     }
+    
   </style>
 </head>
 
diff --git a/src/components/Table/ETable.vue b/src/components/Table/ETable.vue
new file mode 100644
index 0000000..f835e2d
--- /dev/null
+++ b/src/components/Table/ETable.vue
@@ -0,0 +1,156 @@
+<template>
+    <el-table
+      v-loading="loading"
+      :data="tableData"
+      style="width: 100%"
+      :border="border"
+      :show-selection="showSelection"
+      :max-height="maxHeight"
+      @selection-change="handleSelectionChange"
+    >
+      <el-table-column v-if="showSelection" type="selection" width="55" align="center" />
+      <el-table-column v-if="showIndex" label="搴忓彿" type="index" width="60" align="center" />
+      <template v-for="col in columns" :key="col.prop">
+        <el-table-column
+          v-bind="col"
+          :show-overflow-tooltip="col.showOverflowTooltip !== false"
+        >
+          <template v-if="col.slot" #default>
+            <slot></slot>
+          </template>
+        </el-table-column>
+      </template>
+      <!-- 鎿嶄綔鍒� -->
+      <el-table-column v-if="showOperations" :label="operationsLabel" :width="operationsWidth" fixed="right">
+        <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('delete')"
+              link
+              type="danger"
+              size="small"
+              @click="handleDelete(scope.row)"
+            >鍒犻櫎</el-button>
+          </slot>
+        </template>
+      </el-table-column>
+    </el-table>
+  </template>
+  
+  <script setup>
+  import { defineEmits } from 'vue'
+  import { ElMessage, ElMessageBox } from 'element-plus'
+
+  const props = defineProps({
+    // 楂樺害
+    maxHeight: {
+      type: [String, Number],
+      default: 'auto'
+    },
+    // 鍔犺浇鐘舵��
+    loading: {
+      type: Boolean,
+      default: false
+    },
+    //   border
+    border: {
+      type: Boolean,
+      default: false
+    },
+    // 琛ㄦ牸鏁版嵁
+    tableData: {
+      type: Array,
+      default: () => []
+    },
+    // 鏄惁鏄剧ず閫夋嫨鍒�
+    showSelection: {
+      type: Boolean,
+      default: true
+    },
+    // 鏄惁鏄剧ず搴忓彿鍒�
+    showIndex: {
+      type: Boolean,
+      default: true
+    },
+    // 鍒楅厤缃�
+    columns: {
+      type: Array,
+      default: () => []
+    },
+    // 鏄惁鏄剧ず鎿嶄綔鍒�
+    showOperations: {
+      type: Boolean,
+      default: true
+    },
+    // 鎿嶄綔鍒楁爣绛�
+    operationsLabel: {
+      type: String,
+      default: '鎿嶄綔'
+    },
+    // 鎿嶄綔鍒楀搴�
+    operationsWidth: {
+      type: [String, Number],
+      default: 160
+    },
+    // 鏄剧ず鍝簺鎿嶄綔鎸夐挳
+    operations: {
+      type: Array,
+      default: () => ['edit', 'delete', 'export']
+    },
+    // 鍒犻櫎纭淇℃伅
+    deleteConfirmText: {
+      type: String,
+      default: '纭鍒犻櫎璇ヨ褰曪紵'
+    }
+  })
+  const emit = defineEmits(['selection-change', 'edit', 'delete', 'export'])
+  const handleSelectionChange = (selection) => {
+    emit('selection-change', selection)
+  }
+  const handleEdit = (row) => {
+    emit('edit', row)
+  }
+  const handleDelete = (row) => {
+    ElMessageBox.confirm(
+      props.deleteConfirmText,
+      '璀﹀憡',
+      {
+        confirmButtonText: '纭畾',
+        cancelButtonText: '鍙栨秷',
+        type: 'warning'
+      }
+    ).then(() => {
+      emit('delete', row)
+    }).catch(() => {})
+  }
+  
+  const handleExport = (row) => {
+    emit('export', row)
+  }
+  </script>
+  
+  <style scoped>
+  :deep(.el-table) {
+    margin-bottom: 20px;
+    overflow-x: auto;
+  }
+  
+  :deep(.el-table th) {
+    background-color: #f5f7fa;
+  }
+  
+  /* 鍝嶅簲寮忔牱寮� */
+  @media screen and (max-width: 768px) {
+    :deep(.el-table) {
+      width: 100%;
+      overflow-x: auto;
+    }
+  }
+  </style> 
\ No newline at end of file
diff --git a/src/hooks/useFormData.js b/src/hooks/useFormData.js
new file mode 100644
index 0000000..7363aa8
--- /dev/null
+++ b/src/hooks/useFormData.js
@@ -0,0 +1,18 @@
+import { reactive } from "vue";
+import { clone } from "lodash";
+
+
+export default function useFormData(initData) {
+  const form = reactive(clone(initData, true));
+
+  function resetForm() {
+    const initData2 = JSON.parse(JSON.stringify(initData));
+    Object.keys(initData).forEach(key => {
+      form[key] = initData2[key];
+    });
+  }
+
+  return { form, resetForm };
+}
+
+
diff --git a/src/hooks/usePaginationApi.jsx b/src/hooks/usePaginationApi.jsx
new file mode 100644
index 0000000..aa995b0
--- /dev/null
+++ b/src/hooks/usePaginationApi.jsx
@@ -0,0 +1,145 @@
+import { ref, reactive, watchEffect, unref } from "vue";
+import useFormData from "./useFormData.js";
+// import { message } from "@/utils/message";
+
+import { clone, isEqual } from "lodash";
+/**
+ * 鍒嗛〉api
+ * @param api 鎺ュ彛
+ * @param initalFilters 鍒濆鍖栫瓫閫夋潯浠�
+ * @param sorters
+ * @param filterTransformer
+ */
+export function usePaginationApi(
+  api,
+  initalFilters,
+  columns,
+  sorters,
+  filterTransformer,
+  cb
+) {
+  const dataList = ref([]);
+  const { form: filters, resetForm } = useFormData(initalFilters);
+  let lastFilters = clone(initalFilters);
+  const sorter = reactive(sorters || {});
+  const others = ref({});
+  const loading = ref(true);
+  const paginationAlign = ref("right");
+
+  /** 鍒嗛〉閰嶇疆 */
+  const pagination = reactive({
+    pageSize: 10,
+    currentPage: 1,
+    pageSizes: [10, 15, 20],
+    total: 0,
+    align: "right",
+    background: true
+  });
+
+  /** 鍔犺浇鍔ㄧ敾閰嶇疆 */
+  const loadingConfig = reactive({
+    text: "姝e湪鍔犺浇绗竴椤�...",
+    viewBox: "-10, -10, 50, 50",
+    spinner: `
+        <path class="path" d="
+          M 30 15
+          L 28 17
+          M 25.61 25.61
+          A 15 15, 0, 0, 1, 15 30
+          A 15 15, 0, 1, 1, 27.99 7.5
+          L 15 15
+        " style="stroke-width: 4px; fill: rgba(0, 0, 0, 0)"/>
+      `
+    // svg: "",
+    // background: rgba()
+  });
+
+  function getFinalParams() {
+    const finalFilters = {};
+    const beforeParams = unref(filters);
+    if (filterTransformer) {
+      Object.keys(beforeParams).forEach(key => {
+        if (filterTransformer[key]) {
+          Object.assign(
+            finalFilters,
+            filterTransformer[key](beforeParams[key], beforeParams)
+          );
+        } else {
+          finalFilters[key] = beforeParams[key];
+        }
+      });
+    }
+
+    return filterTransformer
+      ? { ...finalFilters, ...sorter }
+      : { ...beforeParams, ...sorter };
+  }
+
+  async function getTableData() {
+    // 濡傛灉杩欐鍜屼笂娆$殑filter涓嶅悓锛岄偅涔堝氨閲嶇疆椤电爜
+    if (!isEqual(unref(filters), lastFilters)) {
+      pagination.currentPage = 1;
+      lastFilters = clone(unref(filters));
+    }
+    loading.value = true;
+    api({
+      ...getFinalParams(),
+      current: pagination.currentPage,
+      size: pagination.pageSize
+    }).then(({ code, data, ...rest }) => {
+      if (code == 200) {
+        // pagination.currentPage = meta.current_page;
+        // pagination.pageSize = meta.per_page;
+        pagination.total = data.total;
+        others.value = rest;
+        dataList.value = data.records;
+        cb && cb(data);
+        loading.value = false;
+      } else {
+        loading.value = false;
+        // message(data.msg, { type: "error" });
+      }
+    });
+  }
+
+  function onSizeChange(val) {
+    pagination.pageSize = val;
+    pagination.currentPage = 1;
+    getTableData();
+  }
+
+  function onCurrentChange(val) {
+    loadingConfig.text = `姝e湪鍔犺浇绗�${val}椤�...`;
+    loading.value = true;
+    getTableData();
+  }
+  function resetFilters() {
+    resetForm();
+    pagination.currentPage = 1;
+    getTableData();
+  }
+
+  watchEffect(() => {
+    pagination.align = paginationAlign.value;
+  });
+
+  // onMounted(() => {
+  //   getTableData();
+  // });
+
+  return {
+    loading,
+    columns,
+    dataList,
+    pagination,
+    loadingConfig,
+    paginationAlign,
+    filters,
+    sorter,
+    others,
+    onSizeChange,
+    onCurrentChange,
+    getTableData,
+    resetFilters
+  };
+}
diff --git a/src/views/basicInformation/index.vue b/src/views/basicInformation/index.vue
new file mode 100644
index 0000000..62ceb31
--- /dev/null
+++ b/src/views/basicInformation/index.vue
@@ -0,0 +1,528 @@
+<template>
+  <div class="app-container">
+      <el-form :inline="true" :model="queryParams" class="search-form">
+        <el-form-item label="鎼滅储">
+          <el-input
+            v-model="queryParams.searchText"
+            placeholder="璇疯緭鍏ュ叧閿瘝"
+            clearable
+            :style="{ width: '100%' }"
+          />
+        </el-form-item>
+        <el-form-item label="渚涘簲鍟嗗悕绉�">
+          <el-input
+            v-model="queryParams.supplierName"
+            placeholder="璇疯緭鍏�"
+            clearable
+            :style="{ width: '100%' }"
+          />
+        </el-form-item>
+        <el-form-item label="缁熶竴浜鸿瘑鍒彿">
+          <el-input
+            v-model="queryParams.identifyNumber"
+            placeholder="璇疯緭鍏�"
+            clearable
+            :style="{ width: '100%' }"
+          />
+        </el-form-item>
+        <el-form-item label="缁忚惀鍦板潃">
+          <el-input
+            v-model="queryParams.address"
+            placeholder="璇疯緭鍏�"
+            clearable
+            :style="{ width: '100%' }"
+          />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="handleQuery">鏌ヨ</el-button>
+          <el-button @click="resetQuery">閲嶇疆</el-button>
+        </el-form-item>
+      </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>
+
+      <!-- 鎿嶄綔鎸夐挳鍖� -->
+      <el-row :gutter="24" class="table-toolbar">
+        <el-button type="primary" :icon="Plus" @click="handleAdd"
+          >鏂板缓</el-button
+        >
+        <el-button type="danger" :icon="Delete" @click="handleDelete">鍒犻櫎</el-button>
+        <el-button type="info" :icon="Download" @click="handleExport">瀵煎嚭</el-button>
+      </el-row> 
+      <!-- 琛ㄦ牸缁勪欢 -->
+      <div>
+        <data-table
+          :loading="loading"
+          :table-data="tableData"
+          :columns="columns"
+          @selection-change="handleSelectionChange"
+          @edit="handleEdit"
+          @delete="handleDeleteSuccess"
+          :show-selection="true"
+          :border="true"
+          :maxHeight="440"
+        />
+      </div>
+      <pagination
+        v-if="total>0"
+        :page-num="pageNum"
+        :page-size="pageSize"
+        :total="total"
+        @pagination="handleQuery"
+        :layout="'total, prev, pager, next, jumper'"
+      />
+      <Supplier
+        v-if="tabName === 'supplier'"
+        v-model:supplierDialogFormVisible="dialogFormVisible"
+        :form="form"
+        :title="title"
+        @submit="handleSubmit"
+        @beforeClose="handleBeforeClose"
+        @update:dialogFormVisible="handleDialogFormVisible"
+        :addOrEdit="addOrEdit"
+      />
+      <Customer
+        v-if="tabName === 'customer'"
+        v-model:customerDialogFormVisible="dialogFormVisible"
+        :form="form"
+        :title="title"
+        @submit="handleSubmit"
+        @beforeClose="handleBeforeClose"
+      />
+      <Coal
+        v-if="tabName === 'coal'"
+        v-model:coalDialogFormVisible="dialogFormVisible"
+        :form="form"
+        :title="title"
+        @submit="handleSubmit"
+      />
+    </el-card>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted } from "vue";
+import { ElMessage, ElMessageBox } from "element-plus";
+import { Plus, Edit, Delete, Download } from "@element-plus/icons-vue";
+import DataTable from "@/components/Table/ETable.vue";
+import Pagination from "@/components/Pagination";
+import Supplier from "./mould/supplier.vue";
+import Customer from "./mould/customer.vue";
+import Coal from "./mould/coal.vue";
+const { proxy } = getCurrentInstance()
+// 寮圭獥
+const customerDialogFormVisible = ref(false);
+const coalDialogFormVisible = ref(false);
+const supplierDialogFormVisible = ref(false);
+const dialogFormVisible = ref(false);
+const form = ref({});
+const title = ref("");
+const copyForm = ref({});
+// 褰撳墠鏍囩
+const tabName = ref("supplier");
+// 鐘舵�佸彉閲�
+const loading = ref(false);
+const total = ref(200);
+const pageNum = ref(1);
+const pageSize = ref(10);
+const activeTab = ref("supplier");
+const selectedRows = ref([]);
+// 鏌ヨ鍙傛暟
+const queryParams = reactive({
+  searchText: "",
+  supplierName: "",
+  identifyNumber: "",
+  address: "",
+});
+onMounted(() => {
+  handleTabClick({ props: { name: "supplier" } });
+});
+const columns = ref();
+// 鏍囩椤垫暟鎹�
+const tabs = reactive([
+  { name: "supplier", label: "渚涘簲鍟嗕俊鎭�" },
+  { name: "customer", label: "瀹㈡埛淇℃伅" },
+  { name: "coal", label: "鐓ょ淇℃伅" },
+]);
+// 鏄惁缂栬緫
+const addOrEdit = ref("add");
+// 琛ㄦ牸鏁版嵁
+const tableData = ref([]);
+// 鏂规硶瀹氫箟
+const handleQuery = () => {
+  loading.value = true;
+  setTimeout(() => {
+    loading.value = false;
+  }, 500);
+};
+// supplier 渚涘簲鍟嗘暟鎹�
+const supplierColumns = reactive([
+  { prop: "supplierName", label: "渚涘簲鍟嗗悕绉�", minWidth: 200 },
+  { prop: "identifyNumber", label: "缁熶竴浜鸿瘑鍒彿", minWidth: 120 },
+  { prop: "address", label: "缁忚惀鍦板潃", minWidth: 150 },
+  { prop: "bank", label: "寮�鎴疯", minWidth: 120 },
+  { prop: "bankAccount", label: "閾惰璐﹀彿", minWidth: 150 },
+  { prop: "contacts", label: "鑱旂郴浜�", minWidth: 100 },
+  { prop: "contactAddress", label: "鑱旂郴鍦板潃", minWidth: 150 },
+  { prop: "maintainer", label: "缁存姢浜�", minWidth: 100 },
+  { prop: "maintainDate", label: "缁存姢鏃ユ湡", minWidth: 100 },
+]);
+// customer 瀹㈡埛鏁版嵁
+const customerColumns = reactive([
+  { prop: "customerName", label: "瀹㈡埛鍚嶇О", minWidth: 200 },
+  { prop: "identifyNumber", label: "缁熶竴浜鸿瘑鍒彿", minWidth: 120 },
+  { prop: "address", label: "缁忚惀鍦板潃", minWidth: 150 },
+  { prop: "bank", label: "寮�鎴疯", minWidth: 120 },
+  { prop: "bankAccount", label: "閾惰璐﹀彿", minWidth: 150 },
+  { prop: "contacts", label: "鑱旂郴浜�", minWidth: 100 },
+  { prop: "contactAddress", label: "鑱旂郴鍦板潃", minWidth: 150 },
+  { prop: "maintainer", label: "缁存姢浜�", minWidth: 100 },
+  { prop: "maintainDate", label: "缁存姢鏃ユ湡", minWidth: 100 },
+]);
+// coal 鐓ょ鏁版嵁
+const coalColumns = reactive([
+  { prop: "coalName", label: "鐓ょ鍚嶇О", minWidth: 200 },
+  { prop: "maintainer", label: "缁存姢浜�", minWidth: 120 },
+  { prop: "maintenanceDate", label: "缁存姢鏃ユ湡", minWidth: 150 },
+]);
+// 鏍囩椤电偣鍑�
+const handleTabClick = (tab) => {
+  form.value = {};
+  getList();
+  addOrEdit.value = "add";
+  loading.value = true;
+  tabName.value = tab.props.name;
+  tableData.value = [];
+  getList();
+  switch (tabName.value) {
+    case "supplier":
+      columns.value = supplierColumns;
+      dialogFormVisible.value = supplierDialogFormVisible.value;
+      break;
+    case "customer":
+      columns.value = customerColumns;
+      dialogFormVisible.value = customerDialogFormVisible.value;
+      break;
+    case "coal":
+      columns.value = coalColumns;
+      dialogFormVisible.value = coalDialogFormVisible.value;
+      break;
+  }
+  setTimeout(() => {
+    loading.value = false;
+  }, 500);
+};
+// 閲嶇疆鏌ヨ
+const resetQuery = () => {
+  Object.keys(queryParams).forEach((key) => {
+    if (key !== "pageNum" && key !== "pageSize") {
+      queryParams[key] = "";
+    }
+  });
+  handleQuery();
+};
+// 鏂板
+const handleAdd = () => {
+  addOrEdit.value = "add";
+  handleAddEdit(tabName.value);
+};
+// 鏂板缂栬緫
+const handleAddEdit = (tabName) => {
+  addOrEdit.value == "add" ? (title.value = "鏂板") : (title.value = "缂栬緫");
+  if (tabName === "supplier") {
+    dialogFormVisible.value = true;
+    title.value = title.value + "渚涘簲鍟嗕俊鎭�";
+    openDialog();
+  } else if (tabName === "customer") {
+    dialogFormVisible.value = true;
+    title.value = title.value + "瀹㈡埛淇℃伅";
+    openDialog();
+  } else if (tabName === "coal") {
+    dialogFormVisible.value = true;
+    title.value = title.value + "鐓ょ淇℃伅";
+    openDialog();
+  }
+};
+// 鎵撳紑寮圭獥
+const openDialog = () => {
+  if (addOrEdit.value === "edit") {
+    copyForm.value = JSON.parse(JSON.stringify(form.value));
+    dialogFormVisible.value = true;
+    return;
+  }
+  form.value = {};
+  dialogFormVisible.value = true;
+};
+// 鎻愪氦琛ㄥ崟
+const handleSubmit = (val) => {
+  // 鎷垮埌鎻愪氦鏁版嵁
+  dialogFormVisible.value = false;
+  getList();
+};
+const handleDialogFormVisible = (value) => {
+  dialogFormVisible.value = value;
+};
+// 閫夋嫨琛�
+const handleSelectionChange = (selection) => {
+  selectedRows.value = selection;
+};
+// 缂栬緫
+const handleEdit = (row) => {
+    form.value = JSON.parse(JSON.stringify(row));
+    addOrEdit.value = "edit";
+    handleAddEdit(tabName.value);
+};
+// 鎵归噺鍒犻櫎
+const handleDelete = () => {
+  if (selectedRows.value.length === 0) {
+    ElMessage.warning("璇烽�夋嫨瑕佸垹闄ょ殑鏁版嵁");
+    return;
+  }
+  ElMessageBox.confirm("纭畾鍒犻櫎閫変腑鐨勬暟鎹悧锛�", "鎻愮ず", {
+    confirmButtonText: "纭畾",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  })
+    .then(() => {
+      ElMessage.success("鍒犻櫎鎴愬姛锛屽叡鍒犻櫎" + selectedRows.value.length + "鏉℃暟鎹�");
+      selectedRows.value.forEach((row) => {
+        tableData.value = tableData.value.filter(
+          (item) => item !== row
+        );
+      });
+      total.value = tableData.value.length;
+      // 娓呯┖閫変腑琛�
+      selectedRows.value = [];
+  }).catch(() => {
+    ElMessage.info("宸插彇娑堝垹闄ゆ搷浣�");
+  });
+}
+// 琛ㄦ牸鍒犻櫎
+const handleDeleteSuccess = (row) => {
+  ElMessage.success("鍒犻櫎鎴愬姛锛�" + row.supplierName);
+};
+// 鍏抽棴寮圭獥
+const handleBeforeClose = () => {
+  dialogFormVisible.value = false;
+  form.value = {};
+};
+const handleExport = (row) => {
+  proxy.download("system/post/export", {
+    ...queryParams.value
+  }, `post_${new Date().getTime()}.xlsx`)
+  ElMessage.success("瀵煎嚭鏁版嵁锛�" + row.supplierName);
+};
+const getList = () => {
+  loading.value = true;
+  setTimeout(() => {
+    // 鏆傛椂寮曞叆娴嬭瘯鏁版嵁
+    tableData.value = [
+      {
+        supplierName: "涓浗鍐堕噾绉戝伐鑲′唤鏈夐檺鍏徃",
+        identifyNumber: "123412123123123111",
+        address: "灞辫タ鐪�",
+        bank: "浜ら�氶摱琛�",
+        bankAccount: "901234567890123456",
+        contacts: "鏉庨洩鑺�",
+        contactAddress: "XX鐪乆X甯俋X鍖篨X璺�",
+        maintainer: "鏉庨洩鑺�",
+        maintainDate: "2022-09-26",
+        contactsPhone: "19345678901",
+      },
+      {
+        supplierName: "涓浗鍐堕噾绉戝伐鑲′唤鏈夐檺鍏徃",
+        identifyNumber: "123412123123123111",
+        address: "灞辫タ鐪�",
+        bank: "浜ら�氶摱琛�",
+        bankAccount: "901234567890123456",
+        contacts: "鏉庨洩鑺�",
+        contactAddress: "XX鐪乆X甯俋X鍖篨X璺�",
+        maintainer: "鏉庨洩鑺�",
+        maintainDate: "2022-09-26",
+        contactsPhone: "19345678901",
+      },
+      {
+        supplierName: "涓浗鍐堕噾绉戝伐鑲′唤鏈夐檺鍏徃",
+        identifyNumber: "123412123123123111",
+        address: "灞辫タ鐪�",
+        bank: "浜ら�氶摱琛�",
+        bankAccount: "901234567890123456",
+        contacts: "鏉庨洩鑺�",
+        contactAddress: "XX鐪乆X甯俋X鍖篨X璺�",
+        maintainer: "鏉庨洩鑺�",
+        maintainDate: "2022-09-26",
+        contactsPhone: "19345678901",
+      },
+      {
+        supplierName: "浜ら�氶摱琛岃偂浠芥湁闄愬叕鍙�",
+        identifyNumber: "042-26881314",
+        address: "姹熻タ鐪�",
+        bank: "骞冲畨閾惰",
+        bankAccount: "123456789012345678",
+        contacts: "鍛ㄧ櫧鐜�",
+        contactAddress: "XX鐪乆X甯俋X鍖篨X璺�",
+        maintainer: "鍛ㄧ櫧鐜�",
+        maintainDate: "2022-08-29",
+      },
+      {
+        supplierName: "涓浗鍐堕噾绉戝伐鑲′唤鏈夐檺鍏徃",
+        identifyNumber: "019-65851198",
+        address: "灞辫タ鐪�",
+        bank: "浜ら�氶摱琛�",
+        bankAccount: "901234567890123456",
+        contacts: "鏉庨洩鑺�",
+        contactAddress: "XX鐪乆X甯俋X鍖篨X璺�",
+        maintainer: "鏉庨洩鑺�",
+        maintainDate: "2022-09-26",
+      },
+      {
+        supplierName: "浜ら�氶摱琛岃偂浠芥湁闄愬叕鍙�",
+        identifyNumber: "042-26881314",
+        address: "姹熻タ鐪�",
+        bank: "骞冲畨閾惰",
+        bankAccount: "123456789012345678",
+        contacts: "鍛ㄧ櫧鐜�",
+        contactAddress: "XX鐪乆X甯俋X鍖篨X璺�",
+        maintainer: "鍛ㄧ櫧鐜�",
+        maintainDate: "2022-08-29",
+      },
+      {
+        supplierName: "涓浗鍐堕噾绉戝伐鑲′唤鏈夐檺鍏徃",
+        identifyNumber: "019-65851198",
+        address: "灞辫タ鐪�",
+        bank: "浜ら�氶摱琛�",
+        bankAccount: "901234567890123456",
+        contacts: "鏉庨洩鑺�",
+        contactAddress: "XX鐪乆X甯俋X鍖篨X璺�",
+        maintainer: "鏉庨洩鑺�",
+        maintainDate: "2022-09-26",
+      },
+      {
+        supplierName: "浜ら�氶摱琛岃偂浠芥湁闄愬叕鍙�",
+        identifyNumber: "042-26881314",
+        address: "姹熻タ鐪�",
+        bank: "骞冲畨閾惰",
+        bankAccount: "123456789012345678",
+        contacts: "鍛ㄧ櫧鐜�",
+        contactAddress: "XX鐪乆X甯俋X鍖篨X璺�",
+        maintainer: "鍛ㄧ櫧鐜�",
+        maintainDate: "2022-08-29",
+      },
+      {
+        supplierName: "涓浗鍐堕噾绉戝伐鑲′唤鏈夐檺鍏徃",
+        identifyNumber: "019-65851198",
+        address: "灞辫タ鐪�",
+        bank: "浜ら�氶摱琛�",
+        bankAccount: "901234567890123456",
+        contacts: "鏉庨洩鑺�",
+        contactAddress: "XX鐪乆X甯俋X鍖篨X璺�",
+        maintainer: "鏉庨洩鑺�",
+        maintainDate: "2022-09-26",
+      },
+      {
+        supplierName: "浜ら�氶摱琛岃偂浠芥湁闄愬叕鍙�",
+        identifyNumber: "042-26881314",
+        address: "姹熻タ鐪�",
+        bank: "骞冲畨閾惰",
+        bankAccount: "123456789012345678",
+        contacts: "鍛ㄧ櫧鐜�",
+        contactAddress: "XX鐪乆X甯俋X鍖篨X璺�",
+        maintainer: "鍛ㄧ櫧鐜�",
+        maintainDate: "2022-08-29",
+      },
+      {
+        supplierName: "涓浗鍐堕噾绉戝伐鑲′唤鏈夐檺鍏徃",
+        identifyNumber: "019-65851198",
+        address: "灞辫タ鐪�",
+        bank: "浜ら�氶摱琛�",
+        bankAccount: "901234567890123456",
+        contacts: "鏉庨洩鑺�",
+        contactAddress: "XX鐪乆X甯俋X鍖篨X璺�",
+        maintainer: "鏉庨洩鑺�",
+        maintainDate: "2022-09-26",
+      },
+      {
+        supplierName: "浜ら�氶摱琛岃偂浠芥湁闄愬叕鍙�",
+        identifyNumber: "042-26881314",
+        address: "姹熻タ鐪�",
+        bank: "骞冲畨閾惰",
+        bankAccount: "123456789012345678",
+        contacts: "鍛ㄧ櫧鐜�",
+        contactAddress: "XX鐪乆X甯俋X鍖篨X璺�",
+        maintainer: "鍛ㄧ櫧鐜�",
+        maintainDate: "2022-08-29",
+      },
+    ];
+    total.value = tableData.value.length;
+    loading.value = false;
+  }, 500);
+};
+getList();
+</script>
+
+<style scoped>
+.app-container{
+  box-sizing: border-box;
+}
+.search-form {
+  background-color: #fff;
+  padding: 20px 20px 0 20px;
+  margin-bottom: 20px;
+  border-radius: 4px;
+  box-shadow: var(--el-box-shadow-light);
+}
+.search-form :deep(.el-form-item) {
+  margin-bottom: 16px;
+  width: 100%;
+}
+
+/* 鍝嶅簲寮忓竷灞� */
+@media screen and (min-width: 768px) {
+  .search-form :deep(.el-form-item) {
+    width: 50%;
+  }
+}
+@media screen and (min-width: 1200px) {
+  .search-form :deep(.el-form-item) {
+    width: 18%;
+  }
+}
+.info-tabs {
+  margin-bottom: 20px;
+}
+.table-toolbar {
+  margin-bottom: 20px;
+  display: flex;
+  flex-wrap: wrap;
+  gap: 10px;
+}
+
+/* 鍝嶅簲寮忚〃鏍� */
+@media screen and (max-width: 768px) {
+  .table-toolbar {
+    flex-direction: column;
+  }
+  .table-toolbar .el-button {
+    width: 100%;
+  }
+}
+/* 琛ㄦ牸宸ュ叿鏍� */
+.table-toolbar, .table-toolbar > * {
+  margin: 0 0 0 0 !important;
+}
+.table-toolbar{
+  margin-bottom: 20px !important;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/basicInformation/indexs.vue b/src/views/basicInformation/indexs.vue
new file mode 100644
index 0000000..7a9559d
--- /dev/null
+++ b/src/views/basicInformation/indexs.vue
@@ -0,0 +1,541 @@
+<template>
+  <div class="app-container">
+      <el-form :inline="true" :model="queryParams" class="search-form">
+        <el-form-item label="鎼滅储">
+          <el-input
+            v-model="queryParams.searchText"
+            placeholder="璇疯緭鍏ュ叧閿瘝"
+            clearable
+            :style="{ width: '100%' }"
+          />
+        </el-form-item>
+        <el-form-item label="渚涘簲鍟嗗悕绉�">
+          <el-input
+            v-model="queryParams.supplierName"
+            placeholder="璇疯緭鍏�"
+            clearable
+            :style="{ width: '100%' }"
+          />
+        </el-form-item>
+        <el-form-item label="缁熶竴浜鸿瘑鍒彿">
+          <el-input
+            v-model="queryParams.identifyNumber"
+            placeholder="璇疯緭鍏�"
+            clearable
+            :style="{ width: '100%' }"
+          />
+        </el-form-item>
+        <el-form-item label="缁忚惀鍦板潃">
+          <el-input
+            v-model="queryParams.address"
+            placeholder="璇疯緭鍏�"
+            clearable
+            :style="{ width: '100%' }"
+          />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="handleQuery">鏌ヨ</el-button>
+          <el-button @click="resetQuery">閲嶇疆</el-button>
+        </el-form-item>
+      </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>
+
+      <!-- 鎿嶄綔鎸夐挳鍖� -->
+      <el-row :gutter="24" class="table-toolbar">
+        <el-button type="primary" :icon="Plus" @click="handleAdd"
+          >鏂板缓</el-button
+        >
+        <el-button type="danger" :icon="Delete">鍒犻櫎</el-button>
+        <el-button type="info" :icon="Download" @click="handleExport">瀵煎嚭</el-button>
+      </el-row> 
+      <!-- 琛ㄦ牸缁勪欢 -->
+      <div>
+        <data-table
+          :loading="loading"
+          :table-data="tableData"
+          :columns="columns"
+          @selection-change="handleSelectionChange"
+          @edit="handleEdit"
+          @delete="handleDeleteSuccess"
+          :show-selection="true"
+          :border="true"
+          :maxHeight="440"
+        />
+      </div>
+      <pagination
+        v-if="total>0"
+        :page-num="queryParams.pageNum"
+        :page-size="queryParams.pageSize"
+        :total="total"
+        @pagination="handleQuery"
+        :layout="'total, prev, pager, next, jumper'"
+      />
+      <Supplier
+        v-if="tabName === 'supplier'"
+        v-model:supplierDialogFormVisible="dialogFormVisible"
+        :form="form"
+        :title="title"
+        @submit="handleSubmit"
+        @beforeClose="handleBeforeClose"
+        @update:dialogFormVisible="handleDialogFormVisible"
+        :addOrEdit="addOrEdit"
+      />
+      <Customer
+        v-if="tabName === 'customer'"
+        v-model:customerDialogFormVisible="dialogFormVisible"
+        :form="form"
+        :title="title"
+        @submit="handleSubmit"
+        @beforeClose="handleBeforeClose"
+      />
+      <Coal
+        v-if="tabName === 'coal'"
+        v-model:coalDialogFormVisible="dialogFormVisible"
+        :form="form"
+        :title="title"
+        @submit="handleSubmit"
+      />
+    </el-card>
+  </div>
+</template>
+
+<script setup>
+import { usePaginationApi } from "../../../hooks/usePaginationApi";
+import { ref, reactive, onMounted } from "vue";
+import { ElMessage } from "element-plus";
+import { Plus, Edit, Delete, Download } from "@element-plus/icons-vue";
+import DataTable from "@/components/Table/ETable.vue";
+import Pagination from "@/components/Pagination";
+import Supplier from "./mould/supplier.vue";
+import Customer from "./mould/customer.vue";
+import Coal from "./mould/coal.vue";
+const { proxy } = getCurrentInstance()
+
+const {
+  columns
+} = usePaginationApi(()=> {
+  // 鍒嗛〉閫昏緫鍙互鍦ㄨ繖閲屽鐞�
+},{
+  searchText: "",
+  supplierName: "",
+  identifyNumber: "",
+  address: "",
+  pageNum: 1,
+  pageSize: 10,
+},[
+  { prop: "supplierName", label: "渚涘簲鍟嗗悕绉�", minWidth: 200 },
+  { prop: "identifyNumber", label: "缁熶竴浜鸿瘑鍒彿", minWidth: 120 },
+  { prop: "address", label: "缁忚惀鍦板潃", minWidth: 150 },
+  { prop: "bank", label: "寮�鎴疯", minWidth: 120 },
+  { prop: "bankAccount", label: "閾惰璐﹀彿", minWidth: 150 },
+  { prop: "contacts", label: "鑱旂郴浜�", minWidth: 100 },
+  { prop: "contactAddress", label: "鑱旂郴鍦板潃", minWidth: 150 },
+  { prop: "maintainer", label: "缁存姢浜�", minWidth: 100 },
+  { prop: "maintainDate", label: "缁存姢鏃ユ湡", minWidth: 100 },
+]);
+
+
+
+
+
+// 寮圭獥
+const customerDialogFormVisible = ref(false);
+const coalDialogFormVisible = ref(false);
+const supplierDialogFormVisible = ref(false);
+const dialogFormVisible = ref(false);
+const form = ref({});
+const title = ref("");
+const copyForm = ref({});
+// 褰撳墠鏍囩
+const tabName = ref("supplier");
+// 鐘舵�佸彉閲�
+const loading = ref(false);
+const total = ref(200);
+const activeTab = ref("supplier");
+const selectedRows = ref([]);
+// 鏌ヨ鍙傛暟
+const queryParams = reactive({
+  searchText: "",
+  supplierName: "",
+  identifyNumber: "",
+  address: "",
+  pageNum: 1,
+  pageSize: 10,
+});
+onMounted(() => {
+  handleTabClick({ props: { name: "supplier" } });
+});
+// 鏍囩椤垫暟鎹�
+const tabs = reactive([
+  { name: "supplier", label: "渚涘簲鍟嗕俊鎭�" },
+  { name: "customer", label: "瀹㈡埛淇℃伅" },
+  { name: "coal", label: "鐓ょ淇℃伅" },
+]);
+// 鏄惁缂栬緫
+const addOrEdit = ref("add");
+// 琛ㄦ牸鏁版嵁
+const tableData = ref([]);
+// 鏂规硶瀹氫箟
+const handleQuery = () => {
+  loading.value = true;
+  // 杩欓噷娣诲姞瀹為檯鐨勬煡璇㈤�昏緫
+  setTimeout(() => {
+    loading.value = false;
+  }, 500);
+};
+
+/* // supplier 渚涘簲鍟嗘暟鎹�
+const supplierColumns = reactive([
+  { prop: "supplierName", label: "渚涘簲鍟嗗悕绉�", minWidth: 200 },
+  { prop: "identifyNumber", label: "缁熶竴浜鸿瘑鍒彿", minWidth: 120 },
+  { prop: "address", label: "缁忚惀鍦板潃", minWidth: 150 },
+  { prop: "bank", label: "寮�鎴疯", minWidth: 120 },
+  { prop: "bankAccount", label: "閾惰璐﹀彿", minWidth: 150 },
+  { prop: "contacts", label: "鑱旂郴浜�", minWidth: 100 },
+  { prop: "contactAddress", label: "鑱旂郴鍦板潃", minWidth: 150 },
+  { prop: "maintainer", label: "缁存姢浜�", minWidth: 100 },
+  { prop: "maintainDate", label: "缁存姢鏃ユ湡", minWidth: 100 },
+]);
+// customer 瀹㈡埛鏁版嵁
+const customerColumns = reactive([
+  { prop: "customerName", label: "瀹㈡埛鍚嶇О", minWidth: 200 },
+  { prop: "identifyNumber", label: "缁熶竴浜鸿瘑鍒彿", minWidth: 120 },
+  { prop: "address", label: "缁忚惀鍦板潃", minWidth: 150 },
+  { prop: "bank", label: "寮�鎴疯", minWidth: 120 },
+  { prop: "bankAccount", label: "閾惰璐﹀彿", minWidth: 150 },
+  { prop: "contacts", label: "鑱旂郴浜�", minWidth: 100 },
+  { prop: "contactAddress", label: "鑱旂郴鍦板潃", minWidth: 150 },
+  { prop: "maintainer", label: "缁存姢浜�", minWidth: 100 },
+  { prop: "maintainDate", label: "缁存姢鏃ユ湡", minWidth: 100 },
+]);
+// coal 鐓ょ鏁版嵁
+const coalColumns = reactive([
+  { prop: "coalName", label: "鐓ょ鍚嶇О", minWidth: 200 },
+  { prop: "maintainer", label: "缁存姢浜�", minWidth: 120 },
+  { prop: "maintenanceDate", label: "缁存姢鏃ユ湡", minWidth: 150 },
+]); */
+
+// 鏍囩椤电偣鍑�
+const handleTabClick = (tab) => {
+  loading.value = true;
+  tabName.value = tab.props.name;
+  tableData.value = [];
+  getList();
+  switch (tabName.value) {
+    case "supplier":
+      dialogFormVisible.value = supplierDialogFormVisible.value;
+      break;
+    case "customer":
+      columns.value = customerColumns;
+      dialogFormVisible.value = customerDialogFormVisible.value;
+      break;
+    case "coal":
+      columns.value = coalColumns;
+      dialogFormVisible.value = coalDialogFormVisible.value;
+      break;
+  }
+  setTimeout(() => {
+    loading.value = false;
+  }, 500);
+};
+// 閲嶇疆鏌ヨ
+const resetQuery = () => {
+  Object.keys(queryParams).forEach((key) => {
+    if (key !== "pageNum" && key !== "pageSize") {
+      queryParams[key] = "";
+    }
+  });
+  handleQuery();
+};
+// 鏂板
+const handleAdd = () => {
+  addOrEdit.value = "add";
+  handleAddEdit(tabName.value);
+};
+// 鏂板缂栬緫
+const handleAddEdit = (tabName) => {
+  addOrEdit.value == "add" ? (title.value = "鏂板") : (title.value = "缂栬緫");
+  if (tabName === "supplier") {
+    dialogFormVisible.value = true;
+    title.value = title.value + "渚涘簲鍟嗕俊鎭�";
+    openDialog();
+  } else if (tabName === "customer") {
+    dialogFormVisible.value = true;
+    title.value = title.value + "瀹㈡埛淇℃伅";
+    openDialog();
+  } else if (tabName === "coal") {
+    dialogFormVisible.value = true;
+    title.value = title.value + "鐓ょ淇℃伅";
+    openDialog();
+  }
+};
+// 鎵撳紑寮圭獥
+const openDialog = () => {
+  if (addOrEdit.value === "edit") {
+    copyForm.value = JSON.parse(JSON.stringify(form.value));
+    dialogFormVisible.value = true;
+    return;
+  }
+  form.value = {};
+  dialogFormVisible.value = true;
+};
+
+// 鎻愪氦琛ㄥ崟
+const handleSubmit = (val) => {
+  // 鎷垮埌鎻愪氦鏁版嵁
+  dialogFormVisible.value = false;
+  getList();
+};
+const handleDialogFormVisible = (value) => {
+  dialogFormVisible.value = value;
+};
+// 閫夋嫨琛�
+const handleSelectionChange = (selection) => {
+  selectedRows.value = selection;
+};
+// 缂栬緫
+const handleEdit = (row) => {
+  if (row.supplierName) {
+    form.value = JSON.parse(JSON.stringify(row));
+    addOrEdit.value = "edit";
+    handleAddEdit(tabName.value);
+    return;
+  }
+  if (selectedRows.value.length === 1) {
+    form.value = JSON.parse(JSON.stringify(selectedRows.value[0]));
+    addOrEdit.value = "edit";
+    handleAddEdit(tabName.value);
+    return;
+  } else {
+    ElMessage.warning("璇烽�夋嫨涓�鏉℃暟鎹慨鏀�");
+  }
+};
+
+const handleDeleteSuccess = (row) => {
+  ElMessage.success("鍒犻櫎鎴愬姛锛�" + row.supplierName);
+};
+// 鍏抽棴寮圭獥
+const handleBeforeClose = () => {
+  dialogFormVisible.value = false;
+  form.value = {};
+};
+const handleExport = (row) => {
+  proxy.download("system/post/export", {
+    ...queryParams.value
+  }, `post_${new Date().getTime()}.xlsx`)
+  ElMessage.success("瀵煎嚭鏁版嵁锛�" + row.supplierName);
+};
+const getList = () => {
+  loading.value = true;
+  setTimeout(() => {
+    tableData.value = [
+      {
+        supplierName: "涓浗鍐堕噾绉戝伐鑲′唤鏈夐檺鍏徃",
+        identifyNumber: "123412123123123111",
+        address: "灞辫タ鐪�",
+        bank: "浜ら�氶摱琛�",
+        bankAccount: "901234567890123456",
+        contacts: "鏉庨洩鑺�",
+        contactAddress: "XX鐪乆X甯俋X鍖篨X璺�",
+        maintainer: "鏉庨洩鑺�",
+        maintainDate: "2022-09-26",
+        contactsPhone: "19345678901",
+      },
+      {
+        supplierName: "涓浗鍐堕噾绉戝伐鑲′唤鏈夐檺鍏徃",
+        identifyNumber: "123412123123123111",
+        address: "灞辫タ鐪�",
+        bank: "浜ら�氶摱琛�",
+        bankAccount: "901234567890123456",
+        contacts: "鏉庨洩鑺�",
+        contactAddress: "XX鐪乆X甯俋X鍖篨X璺�",
+        maintainer: "鏉庨洩鑺�",
+        maintainDate: "2022-09-26",
+        contactsPhone: "19345678901",
+      },
+      {
+        supplierName: "涓浗鍐堕噾绉戝伐鑲′唤鏈夐檺鍏徃",
+        identifyNumber: "123412123123123111",
+        address: "灞辫タ鐪�",
+        bank: "浜ら�氶摱琛�",
+        bankAccount: "901234567890123456",
+        contacts: "鏉庨洩鑺�",
+        contactAddress: "XX鐪乆X甯俋X鍖篨X璺�",
+        maintainer: "鏉庨洩鑺�",
+        maintainDate: "2022-09-26",
+        contactsPhone: "19345678901",
+      },
+      {
+        supplierName: "浜ら�氶摱琛岃偂浠芥湁闄愬叕鍙�",
+        identifyNumber: "042-26881314",
+        address: "姹熻タ鐪�",
+        bank: "骞冲畨閾惰",
+        bankAccount: "123456789012345678",
+        contacts: "鍛ㄧ櫧鐜�",
+        contactAddress: "XX鐪乆X甯俋X鍖篨X璺�",
+        maintainer: "鍛ㄧ櫧鐜�",
+        maintainDate: "2022-08-29",
+      },
+      {
+        supplierName: "涓浗鍐堕噾绉戝伐鑲′唤鏈夐檺鍏徃",
+        identifyNumber: "019-65851198",
+        address: "灞辫タ鐪�",
+        bank: "浜ら�氶摱琛�",
+        bankAccount: "901234567890123456",
+        contacts: "鏉庨洩鑺�",
+        contactAddress: "XX鐪乆X甯俋X鍖篨X璺�",
+        maintainer: "鏉庨洩鑺�",
+        maintainDate: "2022-09-26",
+      },
+      {
+        supplierName: "浜ら�氶摱琛岃偂浠芥湁闄愬叕鍙�",
+        identifyNumber: "042-26881314",
+        address: "姹熻タ鐪�",
+        bank: "骞冲畨閾惰",
+        bankAccount: "123456789012345678",
+        contacts: "鍛ㄧ櫧鐜�",
+        contactAddress: "XX鐪乆X甯俋X鍖篨X璺�",
+        maintainer: "鍛ㄧ櫧鐜�",
+        maintainDate: "2022-08-29",
+      },
+      {
+        supplierName: "涓浗鍐堕噾绉戝伐鑲′唤鏈夐檺鍏徃",
+        identifyNumber: "019-65851198",
+        address: "灞辫タ鐪�",
+        bank: "浜ら�氶摱琛�",
+        bankAccount: "901234567890123456",
+        contacts: "鏉庨洩鑺�",
+        contactAddress: "XX鐪乆X甯俋X鍖篨X璺�",
+        maintainer: "鏉庨洩鑺�",
+        maintainDate: "2022-09-26",
+      },
+      {
+        supplierName: "浜ら�氶摱琛岃偂浠芥湁闄愬叕鍙�",
+        identifyNumber: "042-26881314",
+        address: "姹熻タ鐪�",
+        bank: "骞冲畨閾惰",
+        bankAccount: "123456789012345678",
+        contacts: "鍛ㄧ櫧鐜�",
+        contactAddress: "XX鐪乆X甯俋X鍖篨X璺�",
+        maintainer: "鍛ㄧ櫧鐜�",
+        maintainDate: "2022-08-29",
+      },
+      {
+        supplierName: "涓浗鍐堕噾绉戝伐鑲′唤鏈夐檺鍏徃",
+        identifyNumber: "019-65851198",
+        address: "灞辫タ鐪�",
+        bank: "浜ら�氶摱琛�",
+        bankAccount: "901234567890123456",
+        contacts: "鏉庨洩鑺�",
+        contactAddress: "XX鐪乆X甯俋X鍖篨X璺�",
+        maintainer: "鏉庨洩鑺�",
+        maintainDate: "2022-09-26",
+      },
+      {
+        supplierName: "浜ら�氶摱琛岃偂浠芥湁闄愬叕鍙�",
+        identifyNumber: "042-26881314",
+        address: "姹熻タ鐪�",
+        bank: "骞冲畨閾惰",
+        bankAccount: "123456789012345678",
+        contacts: "鍛ㄧ櫧鐜�",
+        contactAddress: "XX鐪乆X甯俋X鍖篨X璺�",
+        maintainer: "鍛ㄧ櫧鐜�",
+        maintainDate: "2022-08-29",
+      },
+      {
+        supplierName: "涓浗鍐堕噾绉戝伐鑲′唤鏈夐檺鍏徃",
+        identifyNumber: "019-65851198",
+        address: "灞辫タ鐪�",
+        bank: "浜ら�氶摱琛�",
+        bankAccount: "901234567890123456",
+        contacts: "鏉庨洩鑺�",
+        contactAddress: "XX鐪乆X甯俋X鍖篨X璺�",
+        maintainer: "鏉庨洩鑺�",
+        maintainDate: "2022-09-26",
+      },
+      {
+        supplierName: "浜ら�氶摱琛岃偂浠芥湁闄愬叕鍙�",
+        identifyNumber: "042-26881314",
+        address: "姹熻タ鐪�",
+        bank: "骞冲畨閾惰",
+        bankAccount: "123456789012345678",
+        contacts: "鍛ㄧ櫧鐜�",
+        contactAddress: "XX鐪乆X甯俋X鍖篨X璺�",
+        maintainer: "鍛ㄧ櫧鐜�",
+        maintainDate: "2022-08-29",
+      },
+    ];
+    total.value = tableData.value.length;
+    loading.value = false;
+  }, 500);
+};
+getList();
+</script>
+
+<style scoped>
+.app-container{
+  box-sizing: border-box;
+}
+.search-form {
+  background-color: #fff;
+  padding: 20px 20px 0 20px;
+  margin-bottom: 20px;
+  border-radius: 4px;
+  box-shadow: var(--el-box-shadow-light);
+}
+.search-form :deep(.el-form-item) {
+  margin-bottom: 16px;
+  width: 100%;
+}
+
+/* 鍝嶅簲寮忓竷灞� */
+@media screen and (min-width: 768px) {
+  .search-form :deep(.el-form-item) {
+    width: 50%;
+  }
+}
+@media screen and (min-width: 1200px) {
+  .search-form :deep(.el-form-item) {
+    width: 18%;
+  }
+}
+.info-tabs {
+  margin-bottom: 20px;
+}
+.table-toolbar {
+  margin-bottom: 20px;
+  display: flex;
+  flex-wrap: wrap;
+  gap: 10px;
+}
+
+/* 鍝嶅簲寮忚〃鏍� */
+@media screen and (max-width: 768px) {
+  .table-toolbar {
+    flex-direction: column;
+  }
+  .table-toolbar .el-button {
+    width: 100%;
+  }
+}
+/* 琛ㄦ牸宸ュ叿鏍� */
+.table-toolbar, .table-toolbar > * {
+  margin: 0 0 0 0 !important;
+}
+.table-toolbar{
+  margin-bottom: 20px !important;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/basicInformation/mould/coal.vue b/src/views/basicInformation/mould/coal.vue
new file mode 100644
index 0000000..59dd4d5
--- /dev/null
+++ b/src/views/basicInformation/mould/coal.vue
@@ -0,0 +1,140 @@
+<template>
+    <div>
+        <el-dialog
+            v-model="dialogVisible"
+            :title="title"
+            width="800"
+            :close-on-click-modal="false"
+            :before-close="handleClose"
+        >
+            <el-form
+                ref="formRef"
+                style="max-width: 600px; margin: 0 auto"
+                :model="formData"
+                :rules="rules"
+                label-width="auto"
+            >
+                <el-form-item label="鍗¤儭" prop="supplierName">
+                    <el-input
+                        v-model="formData.supplierName"
+                        placeholder="璇疯緭鍏ヤ緵璐у晢鍚嶇О"
+                    />
+                </el-form-item>
+                <el-form-item label="绾崇◣浜鸿瘑鍒彿" prop="identifyNumber">
+                    <el-input
+                        v-model="formData.identifyNumber"
+                        placeholder="璇疯緭鍏ョ撼绋庝汉璇嗗埆鍙�"
+                    />
+                </el-form-item>
+                <el-form-item label="缁忚惀鍦板潃" prop="address">
+                    <el-select v-model="formData.address" placeholder="璇烽�夋嫨缁忚惀鍦板潃">
+                        <el-option label="Zone one" value="shanghai" />
+                        <el-option label="Zone two" value="beijing" />
+                    </el-select>
+                </el-form-item>
+                <el-form-item label="閾惰璐︽埛" prop="bankAccount">
+                    <el-input v-model="formData.bankAccount" placeholder="璇疯緭鍏ラ摱琛岃处鎴�" />
+                </el-form-item>
+                <el-form-item>
+                    <el-button type="primary" @click="submitForm">
+                        纭畾
+                    </el-button>
+                </el-form-item>
+            </el-form>
+        </el-dialog>
+    </div>
+</template>
+
+<script setup>
+import { ref, watch ,defineProps } from 'vue'
+
+const props = defineProps({
+    beforeClose: {
+        type: Function,
+        default: () => {}
+    },
+    form: {
+        type: Object,
+        default: () => ({})
+    },
+    addOrEdit: {
+        type: String,
+        default: 'add'
+    },
+    title: {
+        type: String,
+        default: ''
+    },
+})
+
+const emit = defineEmits(['submit', 'handleBeforeClose','update:coalDialogFormVisible'])
+
+// 琛ㄥ崟寮曠敤
+const formRef = ref(null)
+// 琛ㄥ崟鏁版嵁
+const formData = ref({ ...props.form })
+// 寮圭獥鍙鎬�
+const dialogVisible = defineModel("coalDialogFormVisible",{required:true,type:Boolean})
+
+// 鐩戝惉澶栭儴浼犲叆鐨勮〃鍗曟暟鎹彉鍖�
+watch(() => props.form, (newVal) => {
+    formData.value = { ...newVal }
+}, { deep: true })
+
+// 鐩戝惉鍐呴儴寮圭獥鐘舵�佸彉鍖�
+watch(() => dialogVisible.value, (newVal) => {
+    emit('update:coalDialogFormVisible', newVal)
+})
+
+// 鎻愪氦琛ㄥ崟
+const submitForm = async () => {
+    if (!formRef.value) return
+    await formRef.value.validate((valid, fields) => {
+        if (valid) {
+            emit('submit', formData.value)
+        }
+    })
+}
+// 鍙栨秷琛ㄥ崟
+const cancelForm = () => {
+    emit('update:coalDialogFormVisible', false)
+    formData.value = {}
+}
+// 閲嶇疆琛ㄥ崟
+const resetForm = () => {
+    if (!formRef.value) return
+    formRef.value.resetFields()
+}
+// 鍏抽棴寮圭獥
+const handleClose = () => {
+    // 瑙﹀彂鐖剁粍浠剁殑鍏抽棴鍑芥暟
+    emit("handleBeforeClose")
+    emit('update:coalDialogFormVisible', false)
+}
+const rules = reactive({
+  supplierName: [
+    { required: true, message: "璇疯緭鍏ヤ緵璐у晢鍚嶇О", trigger: "blur" },
+  ],
+  identifyNumber: [
+    { required: true, message: "璇锋纭緭鍏ョ撼绋庝汉璇嗗埆鍙�", trigger: "blur" },
+    { min: 17, max: 20, message: "璇疯緭鍏�17-20浣嶇撼绋庝汉璇嗗埆鍙�", trigger: "blur" },
+  ],
+  address: [
+    {
+      required: true,
+      message: "璇烽�夋嫨缁忚惀鍦板潃",
+      trigger: "change",
+    },
+  ],
+  bankAccount: [{ required: true, message: "璇疯緭鍏ラ摱琛岃处鎴�", trigger: "blur" }],
+  bank: [{ required: true, message: "璇疯緭鍏ュ紑鎴疯", trigger: "blur" }],
+  contacts: [{ required: true, message: "璇疯緭鍏ュ紑鎴疯", trigger: "blur" }],
+  contactsPhone: [
+    { required: true, message: "璇疯緭鍏ヨ仈绯讳汉", trigger: "blur" },
+    { min: 11, max: 11, message: "璇疯緭鍏�11浣嶈仈绯讳汉鐢佃瘽", trigger: "blur" },
+  ],
+});
+</script>
+
+<style lang="sass" scoped>
+</style>
\ No newline at end of file
diff --git a/src/views/basicInformation/mould/customer.vue b/src/views/basicInformation/mould/customer.vue
new file mode 100644
index 0000000..b35a6d5
--- /dev/null
+++ b/src/views/basicInformation/mould/customer.vue
@@ -0,0 +1,140 @@
+<template>
+    <div>
+        <el-dialog
+            v-model="dialogVisible"
+            :title="title"
+            width="800"
+            :close-on-click-modal="false"
+            :before-close="handleClose"
+        >
+            <el-form
+                ref="formRef"
+                style="max-width: 600px; margin: 0 auto"
+                :model="formData"
+                :rules="rules"
+                label-width="auto"
+            >
+                <el-form-item label="鍗¤儭" prop="supplierName">
+                    <el-input
+                        v-model="formData.supplierName"
+                        placeholder="璇疯緭鍏ヤ緵璐у晢鍚嶇О"
+                    />
+                </el-form-item>
+                <el-form-item label="绾崇◣浜鸿瘑鍒彿" prop="identifyNumber">
+                    <el-input
+                        v-model="formData.identifyNumber"
+                        placeholder="璇疯緭鍏ョ撼绋庝汉璇嗗埆鍙�"
+                    />
+                </el-form-item>
+                <el-form-item label="缁忚惀鍦板潃" prop="address">
+                    <el-select v-model="formData.address" placeholder="璇烽�夋嫨缁忚惀鍦板潃">
+                        <el-option label="Zone one" value="shanghai" />
+                        <el-option label="Zone two" value="beijing" />
+                    </el-select>
+                </el-form-item>
+                <el-form-item label="閾惰璐︽埛" prop="bankAccount">
+                    <el-input v-model="formData.bankAccount" placeholder="璇疯緭鍏ラ摱琛岃处鎴�" />
+                </el-form-item>
+                <el-form-item>
+                    <el-button type="primary" @click="submitForm">
+                        纭畾
+                    </el-button>
+                </el-form-item>
+            </el-form>
+        </el-dialog>
+    </div>
+</template>
+
+<script setup>
+import { ref, watch ,defineProps } from 'vue'
+
+const props = defineProps({
+    beforeClose: {
+        type: Function,
+        default: () => {}
+    },
+    form: {
+        type: Object,
+        default: () => ({})
+    },
+    addOrEdit: {
+        type: String,
+        default: 'add'
+    },
+    title: {
+        type: String,
+        default: ''
+    },
+})
+
+const emit = defineEmits(['submit', 'handleBeforeClose','update:customerDialogFormVisible'])
+
+// 琛ㄥ崟寮曠敤
+const formRef = ref(null)
+// 琛ㄥ崟鏁版嵁
+const formData = ref({ ...props.form })
+// 寮圭獥鍙鎬�
+const dialogVisible = defineModel("customerDialogFormVisible",{required:true,type:Boolean})
+
+// 鐩戝惉澶栭儴浼犲叆鐨勮〃鍗曟暟鎹彉鍖�
+watch(() => props.form, (newVal) => {
+    formData.value = { ...newVal }
+}, { deep: true })
+
+// 鐩戝惉鍐呴儴寮圭獥鐘舵�佸彉鍖�
+watch(() => dialogVisible.value, (newVal) => {
+    emit('update:customerDialogFormVisible', newVal)
+})
+
+// 鎻愪氦琛ㄥ崟
+const submitForm = async () => {
+    if (!formRef.value) return
+    await formRef.value.validate((valid, fields) => {
+        if (valid) {
+            emit('submit', formData.value)
+        }
+    })
+}
+// 鍙栨秷琛ㄥ崟
+const cancelForm = () => {
+    emit('update:customerDialogFormVisible', false)
+    formData.value = {}
+}
+// 閲嶇疆琛ㄥ崟
+const resetForm = () => {
+    if (!formRef.value) return
+    formRef.value.resetFields()
+}
+// 鍏抽棴寮圭獥
+const handleClose = () => {
+    // 瑙﹀彂鐖剁粍浠剁殑鍏抽棴鍑芥暟
+    emit("handleBeforeClose")
+    emit('update:customerDialogFormVisible', false)
+}
+const rules = reactive({
+  supplierName: [
+    { required: true, message: "璇疯緭鍏ヤ緵璐у晢鍚嶇О", trigger: "blur" },
+  ],
+  identifyNumber: [
+    { required: true, message: "璇锋纭緭鍏ョ撼绋庝汉璇嗗埆鍙�", trigger: "blur" },
+    { min: 17, max: 20, message: "璇疯緭鍏�17-20浣嶇撼绋庝汉璇嗗埆鍙�", trigger: "blur" },
+  ],
+  address: [
+    {
+      required: true,
+      message: "璇烽�夋嫨缁忚惀鍦板潃",
+      trigger: "change",
+    },
+  ],
+  bankAccount: [{ required: true, message: "璇疯緭鍏ラ摱琛岃处鎴�", trigger: "blur" }],
+  bank: [{ required: true, message: "璇疯緭鍏ュ紑鎴疯", trigger: "blur" }],
+  contacts: [{ required: true, message: "璇疯緭鍏ュ紑鎴疯", trigger: "blur" }],
+  contactsPhone: [
+    { required: true, message: "璇疯緭鍏ヨ仈绯讳汉", trigger: "blur" },
+    { min: 11, max: 11, message: "璇疯緭鍏�11浣嶈仈绯讳汉鐢佃瘽", trigger: "blur" },
+  ],
+});
+</script>
+
+<style lang="sass" scoped>
+</style>
\ No newline at end of file
diff --git a/src/views/basicInformation/mould/supplier.vue b/src/views/basicInformation/mould/supplier.vue
new file mode 100644
index 0000000..0b1d5ec
--- /dev/null
+++ b/src/views/basicInformation/mould/supplier.vue
@@ -0,0 +1,154 @@
+<template>
+    <div>
+        <el-dialog
+            v-model="dialogVisible"
+            :title="title"
+            width="800"
+            :close-on-click-modal="false"
+            :before-close="handleClose"
+        >
+            <el-form
+                ref="formRef"
+                style="max-width: 600px; margin: 0 auto"
+                :model="formData"
+                :rules="rules"
+                label-width="auto"
+            >
+                <el-form-item label="瀹㈡埛鍚嶇О" prop="supplierName">
+                    <el-input
+                        v-model="formData.supplierName"
+                        placeholder="璇疯緭鍏ヤ緵璐у晢鍚嶇О"
+                    />
+                </el-form-item>
+                <el-form-item label="绾崇◣浜鸿瘑鍒彿" prop="identifyNumber">
+                    <el-input
+                        v-model="formData.identifyNumber"
+                        placeholder="璇疯緭鍏ョ撼绋庝汉璇嗗埆鍙�"
+                    />
+                </el-form-item>
+                <el-form-item label="缁忚惀鍦板潃" prop="address">
+                    <el-select v-model="formData.address" placeholder="璇烽�夋嫨缁忚惀鍦板潃">
+                        <el-option label="Zone one" value="shanghai" />
+                        <el-option label="Zone two" value="beijing" />
+                    </el-select>
+                </el-form-item>
+                <el-form-item label="閾惰璐︽埛" prop="bankAccount">
+                    <el-input v-model="formData.bankAccount" placeholder="璇疯緭鍏ラ摱琛岃处鎴�" />
+                </el-form-item>
+                <el-form-item label="寮�鎴疯" prop="bank">
+                    <el-input v-model="formData.bank" placeholder="璇疯緭鍏ュ紑鎴疯" />
+                </el-form-item>
+                <el-form-item label="鑱旂郴浜�" prop="contacts">
+                    <el-input v-model="formData.contacts" placeholder="璇疯緭鍏ヨ仈绯讳汉" />
+                </el-form-item>
+                <el-form-item label="鑱旂郴浜虹數璇�" prop="contactsPhone">
+                    <el-input
+                        v-model="formData.contactsPhone"
+                        placeholder="璇疯緭鍏ヨ仈绯讳汉鐢佃瘽"
+                    />
+                </el-form-item>
+                <el-form-item>
+                    <el-button type="primary" @click="submitForm">
+                        纭畾
+                    </el-button>
+                    <el-button v-if="addOrEdit === 'edit'" @click="resetForm">閲嶇疆</el-button>
+                    <el-button v-if="addOrEdit === 'add'" @click="cancelForm">鍙栨秷</el-button>
+                </el-form-item>
+            </el-form>
+        </el-dialog>
+    </div>
+</template>
+
+<script setup>
+import { ref, watch, defineProps } from 'vue'
+
+const props = defineProps({
+    beforeClose: {
+        type: Function,
+        default: () => {}
+    },
+    form: {
+        type: Object,
+        default: () => ({})
+    },
+    addOrEdit: {
+        type: String,
+        default: 'add'
+    },
+    title: {
+        type: String,
+        default: ''
+    },
+})
+
+const emit = defineEmits(['submit', 'handleBeforeClose'])
+
+// 琛ㄥ崟寮曠敤
+const formRef = ref(null)
+// 琛ㄥ崟鏁版嵁
+const formData = ref({ ...props.form })
+// 寮圭獥鍙鎬�
+const dialogVisible = defineModel("supplierDialogFormVisible",{required:true,type:Boolean})
+
+// 鐩戝惉澶栭儴浼犲叆鐨勮〃鍗曟暟鎹彉鍖�
+watch(() => props.form, (newVal) => {
+    formData.value = { ...newVal }
+}, { deep: true })
+
+// 鐩戝惉鍐呴儴寮圭獥鐘舵�佸彉鍖�
+watch(() => dialogVisible.value, (newVal) => {
+    emit('update:supplierDialogFormVisible', newVal)
+})
+
+// 鎻愪氦琛ㄥ崟
+const submitForm = async () => {
+    if (!formRef.value) return
+    await formRef.value.validate((valid, fields) => {
+        if (valid) {
+            emit('submit', formData.value)
+        }
+    })
+}
+// 鍙栨秷琛ㄥ崟
+const cancelForm = () => {
+    emit('update:supplierDialogFormVisible', false)
+    formData.value = {}
+}
+// 閲嶇疆琛ㄥ崟
+const resetForm = () => {
+    if (!formRef.value) return
+    formRef.value.resetFields()
+}
+// 鍏抽棴寮圭獥
+const handleClose = () => {
+    // 瑙﹀彂鐖剁粍浠剁殑鍏抽棴鍑芥暟
+    emit("handleBeforeClose")
+    emit('update:supplierDialogFormVisible', false)
+}
+const rules = reactive({
+  supplierName: [
+    { required: true, message: "璇疯緭鍏ヤ緵璐у晢鍚嶇О", trigger: "blur" },
+  ],
+  identifyNumber: [
+    { required: true, message: "璇锋纭緭鍏ョ撼绋庝汉璇嗗埆鍙�", trigger: "blur" },
+    { min: 17, max: 20, message: "璇疯緭鍏�17-20浣嶇撼绋庝汉璇嗗埆鍙�", trigger: "blur" },
+  ],
+  address: [
+    {
+      required: true,
+      message: "璇烽�夋嫨缁忚惀鍦板潃",
+      trigger: "change",
+    },
+  ],
+  bankAccount: [{ required: true, message: "璇疯緭鍏ラ摱琛岃处鎴�", trigger: "blur" }],
+  bank: [{ required: true, message: "璇疯緭鍏ュ紑鎴疯", trigger: "blur" }],
+  contacts: [{ required: true, message: "璇疯緭鍏ュ紑鎴疯", trigger: "blur" }],
+  contactsPhone: [
+    { required: true, message: "璇疯緭鍏ヨ仈绯讳汉", trigger: "blur" },
+    { min: 11, max: 11, message: "璇疯緭鍏�11浣嶈仈绯讳汉鐢佃瘽", trigger: "blur" },
+  ],
+});
+</script>
+
+<style lang="sass" scoped>
+</style>
\ No newline at end of file
diff --git a/src/views/procureMent/index.vue b/src/views/procureMent/index.vue
new file mode 100644
index 0000000..790146a
--- /dev/null
+++ b/src/views/procureMent/index.vue
@@ -0,0 +1,308 @@
+<template>
+  <div class="app-container">
+      <el-form :inline="true" :model="queryParams" class="search-form">
+        <el-form-item label="鎼滅储">
+          <el-input
+            v-model="queryParams.searchText"
+            placeholder="璇疯緭鍏ュ叧閿瘝"
+            clearable
+            :style="{ width: '100%' }"
+          />
+        </el-form-item>
+        <el-form-item label="渚涘簲鍟嗗悕绉�">
+          <el-input
+            v-model="queryParams.supplierName"
+            placeholder="璇疯緭鍏�"
+            clearable
+            :style="{ width: '100%' }"
+          />
+        </el-form-item>
+        <el-form-item label="缁熶竴浜鸿瘑鍒彿">
+          <el-input
+            v-model="queryParams.identifyNumber"
+            placeholder="璇疯緭鍏�"
+            clearable
+            :style="{ width: '100%' }"
+          />
+        </el-form-item>
+        <el-form-item label="缁忚惀鍦板潃">
+          <el-input
+            v-model="queryParams.address"
+            placeholder="璇疯緭鍏�"
+            clearable
+            :style="{ width: '100%' }"
+          />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="handleQuery">鏌ヨ</el-button>
+          <el-button @click="resetQuery">閲嶇疆</el-button>
+        </el-form-item>
+      </el-form>
+    <el-card>
+      <!-- 鎿嶄綔鎸夐挳鍖� -->
+      <el-row :gutter="24" class="table-toolbar">
+        <el-button type="primary" :icon="Plus" @click="handleAdd"
+          >鏂板缓</el-button
+        >
+        <el-button type="danger" :icon="Delete" @click="handleDelete">鍒犻櫎</el-button>
+        <el-button type="info" :icon="Download" @click="handleExport">瀵煎嚭</el-button>
+      </el-row> 
+      <!-- 琛ㄦ牸缁勪欢 -->
+        <data-table
+          :loading="loading"
+          :table-data="tableData"
+          :columns="columns"
+          @selection-change="handleSelectionChange"
+          @edit="handleEdit"
+          @delete="handleDeleteSuccess"
+          :show-selection="true"
+          :border="true"
+          :maxHeight="440"
+        />
+      <pagination
+        v-if="total>0"
+        :page-num="pageNum"
+        :page-size="pageSize"
+        :total="total"
+        @pagination="handleQuery"
+        :layout="'total, prev, pager, next, jumper'"
+      />
+    </el-card>
+    <ProductionDialog
+        v-if="total>0"
+        v-model:dialogFormVisible="dialogFormVisible"
+        :form="form"
+        :title="title"
+        @submit="handleSubmit"
+        @success="handleSuccess"
+      />
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted } from "vue";
+import { ElMessage, ElMessageBox } from "element-plus";
+import { Plus, Edit, Delete, Download } from "@element-plus/icons-vue";
+import DataTable from "@/components/Table/ETable.vue";
+import Pagination from "@/components/Pagination";
+import ProductionDialog from "./components/ProductionDialog.vue";
+const { proxy } = getCurrentInstance()
+
+const dialogFormVisible = ref(false);
+const form = ref({});
+const title = ref("");
+// 鐘舵�佸彉閲�
+const loading = ref(false);
+const total = ref(0);
+const pageNum = ref(1)
+const pageSize = ref(10);
+const selectedRows = ref([]);
+// 鏌ヨ鍙傛暟
+const queryParams = reactive({
+  searchText: "",
+  supplierName: "",
+  identifyNumber: "",
+  address: "",
+  
+});
+// 鏄惁缂栬緫
+const addOrEdit = ref("add");
+// 琛ㄦ牸鏁版嵁
+const tableData = ref([]);
+// 鏂规硶瀹氫箟
+const handleQuery = () => {
+  loading.value = true;
+  // 杩欓噷娣诲姞瀹為檯鐨勬煡璇㈤�昏緫
+  setTimeout(() => {
+    loading.value = false;
+  }, 500);
+};
+
+// supplier 渚涘簲鍟嗘暟鎹�
+const columns = ref([
+  { prop: "supplierName", label: "渚涘簲鍟嗗悕绉�", minWidth: 200 },
+  { prop: "category", label: "鐓ょ", minWidth: 120 },
+  { prop: "unit", label: "鍗曚綅", minWidth: 150 },
+  { prop: "purchaseAmount", label: "閲囪喘鏁伴噺", minWidth: 120 },
+  { prop: "priceBeforeTax", label: "鍗曚环(绋庡墠)", minWidth: 150 },
+  { prop: "totalBeforeTax", label: "鎬讳环(绋庡墠)", minWidth: 100 },
+  { prop: "calorificValue", label: "鐑��", minWidth: 150 },
+  { prop: "registrant", label: "鐧昏浜�", minWidth: 100 },
+  { prop: "registrationDate", label: "鐧昏鏃ユ湡", minWidth: 100 },
+]);
+
+// 閲嶇疆鏌ヨ
+const resetQuery = () => {
+  Object.keys(queryParams).forEach((key) => {
+    if (key !== "pageNum" && key !== "pageSize") {
+      queryParams[key] = "";
+    }
+  });
+  handleQuery();
+};
+// 鏂板
+const handleAdd = () => {
+  addOrEdit.value = "add";
+  handleAddEdit();
+};
+// 鏂板缂栬緫
+const handleAddEdit = () => {
+  addOrEdit.value == "add" ? (title.value = "鏂板") : (title.value = "缂栬緫");
+    title.value = title.value + "閲囪喘淇℃伅";
+    openDialog();
+};
+// 鎵撳紑寮圭獥
+const openDialog = () => {
+  if (addOrEdit.value === "edit") {
+    dialogFormVisible.value = true;
+    return;
+  }
+  form.value = {};
+  dialogFormVisible.value = true;
+};
+
+// 鎻愪氦琛ㄥ崟
+const handleSubmit = () => {
+  // 鎷垮埌鎻愪氦鏁版嵁
+  dialogFormVisible.value = false;
+  getList();
+};
+// 閫夋嫨琛�
+const handleSelectionChange = (selection) => {
+  selectedRows.value = selection;
+};
+// 琛ㄦ牸缂栬緫鏂规硶
+const handleEdit = (row) => {
+    form.value = JSON.parse(JSON.stringify(row));
+    addOrEdit.value = "edit";
+    handleAddEdit()
+};
+const handleDelete = () => {
+  if (selectedRows.value.length === 0) {
+    ElMessage.warning("璇烽�夋嫨瑕佸垹闄ょ殑鏁版嵁");
+    return;
+  }
+  ElMessageBox.confirm(
+    `纭鍒犻櫎閫変腑鐨� ${selectedRows.value.length} 鏉℃暟鎹悧锛焋,
+    "鎻愮ず",
+    {
+      confirmButtonText: "纭畾",
+      cancelButtonText: "鍙栨秷",
+      type: "warning"
+    }
+  )
+    .then(() => {
+      // 妯℃嫙鍒犻櫎鎿嶄綔
+      tableData.value = tableData.value.filter(
+        (item) => !selectedRows.value.includes(item)
+      );
+      total.value = tableData.value.length;
+      ElMessage.success("鍒犻櫎鎴愬姛");
+    })
+    .catch(() => {
+      ElMessage.info("宸插彇娑堝垹闄�");
+    });
+}
+const handleDeleteSuccess = (row) => {
+  ElMessage.success("鍒犻櫎鎴愬姛锛�" + row.supplierName);
+};
+// 瀵煎嚭
+const handleExport = (row) => {
+  proxy.download("system/post/export", {
+    ...queryParams.value
+  }, `post_${new Date().getTime()}.xlsx`)
+  ElMessage.success("瀵煎嚭鏁版嵁锛�" + row.supplierName);
+};
+// 鎴愬姛
+const handleSuccess = (val) => {
+  console.log(val);
+  tableData.value.push(val);
+  // getList();
+  total.value = tableData.value.length;
+  ElMessage.success("鎿嶄綔鎴愬姛");
+};
+const getList = () => {
+  loading.value = true;
+  setTimeout(() => {
+    tableData.value = [
+      {
+        supplierName: "涓浗鐭虫补鍖栧伐鑲′唤鏈夐檺鍏徃",
+        category: "鐓�",
+        unit: "鍚�",
+        purchaseAmount: "1000",
+        priceBeforeTax: "100",
+        totalBeforeTax: "100000",
+        calorificValue: "5000",
+        registrant: "寮犱笁",
+        registrationDate: "2025-01-01",
+      },
+      {
+        supplierName: "涓浗涓煶鍖�",
+        category: "绮惧搧鐓�",
+        unit: "鍗冨厠",
+        purchaseAmount: "1000",
+        priceBeforeTax: "100",
+        totalBeforeTax: "100000",
+        calorificValue: "5000",
+        registrant: "鏉庡洓",
+        registrationDate: "2025-01-01",
+      }
+    ]
+    total.value = tableData.value.length;
+    loading.value = false;
+  }, 500);
+};
+getList();
+</script>
+
+<style scoped>
+.app-container{
+  box-sizing: border-box;
+}
+.search-form {
+  background-color: #fff;
+  padding: 20px 20px 0 20px;
+  margin-bottom: 20px;
+  border-radius: 4px;
+  box-shadow: var(--el-box-shadow-light);
+}
+.search-form :deep(.el-form-item) {
+  margin-bottom: 16px;
+  width: 100%;
+}
+
+/* 鍝嶅簲寮忓竷灞� */
+@media screen and (min-width: 768px) {
+  .search-form :deep(.el-form-item) {
+    width: 50%;
+  }
+}
+@media screen and (min-width: 1200px) {
+  .search-form :deep(.el-form-item) {
+    width: 18%;
+  }
+}
+.table-toolbar {
+  margin-bottom: 20px;
+  display: flex;
+  flex-wrap: wrap;
+  gap: 10px;
+}
+
+/* 鍝嶅簲寮忚〃鏍� */
+@media screen and (max-width: 768px) {
+  .table-toolbar {
+    flex-direction: column;
+  }
+  .table-toolbar .el-button {
+    width: 100%;
+  }
+}
+/* 琛ㄦ牸宸ュ叿鏍� */
+.table-toolbar, .table-toolbar > * {
+  margin: 0 0 0 0 !important;
+}
+.table-toolbar{
+  margin-bottom: 20px !important;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/production/index.vue b/src/views/production/index.vue
new file mode 100644
index 0000000..dbad178
--- /dev/null
+++ b/src/views/production/index.vue
@@ -0,0 +1,278 @@
+<template>
+  <div class="production-container">
+    <div class="search-bar">
+      <el-input v-model="searchForm.keyword" placeholder="璇疯緭鍏ュ叧閿瘝" clearable />
+      <el-input v-model="searchForm.addUser" placeholder="璇疯緭鍏ヤ汉" clearable />
+      <el-button type="primary" @click="handleSearch">鏌ヨ</el-button>
+      <el-button @click="handleReset">閲嶇疆</el-button>
+    </div>
+
+    <div class="operation-bar">
+      <el-button type="primary" @click="handleAdd">鏂板閰嶉」</el-button>
+      <el-button type="success" @click="handleAddBatch">鏂板鍔犲伐</el-button>
+      <el-button type="warning">淇敼</el-button>
+      <el-button type="danger">鍒犻櫎</el-button>
+      <el-button type="info">瀵煎嚭</el-button>
+    </div>
+
+    <el-table :data="tableData" border style="width: 100%" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" />
+      <el-table-column prop="sequence" label="搴忓彿" width="80" />
+      <el-table-column prop="category" label="鐓ょ" width="120" />
+      <el-table-column prop="unit" label="鍗曚綅" width="100" />
+      <el-table-column prop="productionVolume" label="鐢熶骇鏁伴噺" width="120" />
+      <el-table-column prop="laborCost" label="浜哄伐鎴愭湰" width="120" />
+      <el-table-column prop="materialCost" label="鍘熸枡鎴愭湰" width="120" />
+      <el-table-column prop="equipmentCost" label="璁惧璐圭敤" width="120" />
+      <el-table-column prop="totalCost" label="鎬绘垚鏈�" width="120" />
+      <el-table-column prop="totalPrice" label="鎬绘垚鏈�" width="120" />
+      <el-table-column prop="profit" label="鍒╂鼎" width="100" />
+      <el-table-column prop="reviewer" label="澶嶈浜�" width="120" />
+      <el-table-column prop="date" label="鏃ユ湡" width="120" />
+      <el-table-column label="鎿嶄綔" fixed="right" width="220">
+        <template #default="scope">
+          <el-button type="primary" link @click="handleEdit(scope.row)">鐧昏</el-button>
+          <el-button type="success" link @click="handleEdit(scope.row)">缂栬緫</el-button>
+          <el-button type="danger" link @click="handleDelete(scope.row)">鍒犻櫎</el-button>
+          <el-button type="warning" link @click="handleExport(scope.row)">瀵煎嚭</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <div class="pagination">
+      <el-pagination
+        v-model:current-page="pagination.currentPage"
+        v-model:page-size="pagination.pageSize"
+        :page-sizes="[10, 20, 30, 50]"
+        :total="pagination.total"
+        layout="total, sizes, prev, pager, next, jumper"
+        @size-change="handleSizeChange"
+        @current-change="handleCurrentChange"
+      />
+    </div>
+
+    <!-- 寮圭獥缁勪欢 -->
+    <ProductionDialog-dialog
+      v-model:visible="dialogVisible"
+      :type="dialogType"
+      :row-data="currentRow"
+      @success="handleDialogSuccess"
+    />
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { getProductionList, addProduction, updateProduction, deleteProduction, exportProduction } from '@/api/production'
+import ProductionDialog from './components/ProductionDialog.vue'
+
+// 鎼滅储琛ㄥ崟鏁版嵁
+const searchForm = reactive({
+  keyword: '',
+  addUser: ''
+})
+
+// 琛ㄦ牸鏁版嵁
+const tableData = ref([])
+const loading = ref(false)
+
+// 鍒嗛〉鏁版嵁
+const pagination = reactive({
+  currentPage: 1,
+  pageSize: 10,
+  total: 0
+})
+
+// 閫変腑鐨勮鏁版嵁
+const selectedRows = ref([])
+
+// 寮圭獥鐩稿叧
+const dialogVisible = ref(false)
+const dialogType = ref('add')
+const currentRow = ref(null)
+
+// 鑾峰彇琛ㄦ牸鏁版嵁
+const getList = async () => {
+  loading.value = true
+  try {
+    const params = {
+      ...searchForm,
+      pageNum: pagination.currentPage,
+      pageSize: pagination.pageSize
+    }
+    // const res = await getProductionList(params)
+    // 鍋囨暟鎹�
+    const res = {
+      data: {
+        list: [{
+          sequence: 1,
+          category: '鐓ょ',
+          unit: '鍗曚綅',
+          productionVolume: '鐢熶骇鏁伴噺',
+          laborCost: '浜哄伐鎴愭湰',
+          materialCost: '鍘熸枡鎴愭湰',
+          equipmentCost: '璁惧璐圭敤',
+          totalCost: '鎬绘垚鏈�',
+          totalPrice: '鎬绘垚鏈�',
+          profit: '鍒╂鼎',
+          reviewer: '澶嶈浜�',
+          date: '鏃ユ湡'
+        }],
+        total: 0
+      }
+    }
+    
+
+    tableData.value = res.data.list
+    pagination.total = res.data.total
+  } catch (error) {
+    console.error('鑾峰彇鏁版嵁澶辫触:', error)
+    ElMessage.error('鑾峰彇鏁版嵁澶辫触')
+  } finally {
+    loading.value = false
+  }
+}
+
+// 澶勭悊琛ㄦ牸閫夋嫨鍙樺寲
+const handleSelectionChange = (selection) => {
+  selectedRows.value = selection
+}
+
+// 鎼滅储鏂规硶
+const handleSearch = () => {
+  pagination.currentPage = 1
+  getList()
+}
+
+// 閲嶇疆鎼滅储
+const handleReset = () => {
+  searchForm.keyword = ''
+  searchForm.addUser = ''
+  handleSearch()
+}
+
+// 鏂板閰嶉」
+const handleAdd = () => {
+  dialogType.value = 'add'
+  dialogVisible.value = true
+}
+
+// 鏂板鍔犲伐
+const handleAddBatch = () => {
+  dialogType.value = 'add'
+  dialogVisible.value = true
+}
+
+// 缂栬緫
+const handleEdit = (row) => {
+  currentRow.value = row
+  dialogType.value = 'edit'
+  dialogVisible.value = true
+}
+
+// 澶勭悊寮圭獥鎻愪氦
+const handleDialogSuccess = async (formData) => {
+  try {
+    if (dialogType.value === 'add') {
+      await addProduction(formData)
+      ElMessage.success('鏂板鎴愬姛')
+    } else {
+      await updateProduction({
+        ...formData,
+        id: currentRow.value.id
+      })
+      ElMessage.success('鏇存柊鎴愬姛')
+    }
+    getList()
+  } catch (error) {
+    console.error(dialogType.value === 'add' ? '鏂板澶辫触:' : '鏇存柊澶辫触:', error)
+    ElMessage.error(dialogType.value === 'add' ? '鏂板澶辫触' : '鏇存柊澶辫触')
+  }
+}
+
+// 鍒犻櫎
+const handleDelete = (row) => {
+  ElMessageBox.confirm('纭鍒犻櫎璇ヨ褰曞悧锛�', '鎻愮ず', {
+    confirmButtonText: '纭畾',
+    cancelButtonText: '鍙栨秷',
+    type: 'warning'
+  }).then(async () => {
+    try {
+      await deleteProduction(row.id)
+      ElMessage.success('鍒犻櫎鎴愬姛')
+      getList()
+    } catch (error) {
+      console.error('鍒犻櫎澶辫触:', error)
+      ElMessage.error('鍒犻櫎澶辫触')
+    }
+  }).catch(() => {
+    ElMessage.info('宸插彇娑堝垹闄�')
+  })
+}
+
+// 瀵煎嚭
+const handleExport = async (row) => {
+  try {
+    const res = await exportProduction({ id: row.id })
+    const blob = new Blob([res], { type: 'application/vnd.ms-excel' })
+    const fileName = `鐢熶骇鍔犲伐璁板綍_${new Date().getTime()}.xlsx`
+    if ('download' in document.createElement('a')) {
+      const elink = document.createElement('a')
+      elink.download = fileName
+      elink.style.display = 'none'
+      elink.href = URL.createObjectURL(blob)
+      document.body.appendChild(elink)
+      elink.click()
+      URL.revokeObjectURL(elink.href)
+      document.body.removeChild(elink)
+    } else {
+      navigator.msSaveBlob(blob, fileName)
+    }
+  } catch (error) {
+    console.error('瀵煎嚭澶辫触:', error)
+    ElMessage.error('瀵煎嚭澶辫触')
+  }
+}
+
+// 澶勭悊姣忛〉鏄剧ず鏁伴噺鍙樺寲
+const handleSizeChange = (val) => {
+  pagination.pageSize = val
+  getList()
+}
+
+// 澶勭悊椤电爜鍙樺寲
+const handleCurrentChange = (val) => {
+  pagination.currentPage = val
+  getList()
+}
+
+// 缁勪欢鎸傝浇鏃跺姞杞芥暟鎹�
+onMounted(() => {
+  getList()
+})
+</script>
+
+<style scoped>
+.production-container {
+  padding: 20px;
+}
+
+.search-bar {
+  margin-bottom: 20px;
+  display: flex;
+  gap: 10px;
+}
+
+.operation-bar {
+  margin-bottom: 20px;
+  display: flex;
+  gap: 10px;
+}
+
+.pagination {
+  margin-top: 20px;
+  display: flex;
+  justify-content: flex-end;
+}
+</style> 
\ No newline at end of file

--
Gitblit v1.9.3