张诺
2 天以前 e85670cc7beaa7616453a30823fd08c149ab442b
基础信息模块and采购登记
已修改1个文件
已添加10个文件
2409 ■■■■■ 文件已修改
index.html 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Table/ETable.vue 156 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/useFormData.js 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/usePaginationApi.jsx 145 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicInformation/index.vue 528 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicInformation/indexs.vue 541 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicInformation/mould/coal.vue 140 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicInformation/mould/customer.vue 140 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicInformation/mould/supplier.vue 154 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procureMent/index.vue 308 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/production/index.vue 278 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
index.html
@@ -197,6 +197,7 @@
      color: #FFF;
      opacity: 0.5;
    }
  </style>
</head>
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>
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 };
}
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: "正在加载第一页...",
    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 = `正在加载第${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
  };
}
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省XX市XX区XXè·¯",
        maintainer: "李雪芹",
        maintainDate: "2022-09-26",
        contactsPhone: "19345678901",
      },
      {
        supplierName: "中国冶金科工股份有限公司",
        identifyNumber: "123412123123123111",
        address: "山西省",
        bank: "交通银行",
        bankAccount: "901234567890123456",
        contacts: "李雪芹",
        contactAddress: "XX省XX市XX区XXè·¯",
        maintainer: "李雪芹",
        maintainDate: "2022-09-26",
        contactsPhone: "19345678901",
      },
      {
        supplierName: "中国冶金科工股份有限公司",
        identifyNumber: "123412123123123111",
        address: "山西省",
        bank: "交通银行",
        bankAccount: "901234567890123456",
        contacts: "李雪芹",
        contactAddress: "XX省XX市XX区XXè·¯",
        maintainer: "李雪芹",
        maintainDate: "2022-09-26",
        contactsPhone: "19345678901",
      },
      {
        supplierName: "交通银行股份有限公司",
        identifyNumber: "042-26881314",
        address: "江西省",
        bank: "平安银行",
        bankAccount: "123456789012345678",
        contacts: "周白玉",
        contactAddress: "XX省XX市XX区XXè·¯",
        maintainer: "周白玉",
        maintainDate: "2022-08-29",
      },
      {
        supplierName: "中国冶金科工股份有限公司",
        identifyNumber: "019-65851198",
        address: "山西省",
        bank: "交通银行",
        bankAccount: "901234567890123456",
        contacts: "李雪芹",
        contactAddress: "XX省XX市XX区XXè·¯",
        maintainer: "李雪芹",
        maintainDate: "2022-09-26",
      },
      {
        supplierName: "交通银行股份有限公司",
        identifyNumber: "042-26881314",
        address: "江西省",
        bank: "平安银行",
        bankAccount: "123456789012345678",
        contacts: "周白玉",
        contactAddress: "XX省XX市XX区XXè·¯",
        maintainer: "周白玉",
        maintainDate: "2022-08-29",
      },
      {
        supplierName: "中国冶金科工股份有限公司",
        identifyNumber: "019-65851198",
        address: "山西省",
        bank: "交通银行",
        bankAccount: "901234567890123456",
        contacts: "李雪芹",
        contactAddress: "XX省XX市XX区XXè·¯",
        maintainer: "李雪芹",
        maintainDate: "2022-09-26",
      },
      {
        supplierName: "交通银行股份有限公司",
        identifyNumber: "042-26881314",
        address: "江西省",
        bank: "平安银行",
        bankAccount: "123456789012345678",
        contacts: "周白玉",
        contactAddress: "XX省XX市XX区XXè·¯",
        maintainer: "周白玉",
        maintainDate: "2022-08-29",
      },
      {
        supplierName: "中国冶金科工股份有限公司",
        identifyNumber: "019-65851198",
        address: "山西省",
        bank: "交通银行",
        bankAccount: "901234567890123456",
        contacts: "李雪芹",
        contactAddress: "XX省XX市XX区XXè·¯",
        maintainer: "李雪芹",
        maintainDate: "2022-09-26",
      },
      {
        supplierName: "交通银行股份有限公司",
        identifyNumber: "042-26881314",
        address: "江西省",
        bank: "平安银行",
        bankAccount: "123456789012345678",
        contacts: "周白玉",
        contactAddress: "XX省XX市XX区XXè·¯",
        maintainer: "周白玉",
        maintainDate: "2022-08-29",
      },
      {
        supplierName: "中国冶金科工股份有限公司",
        identifyNumber: "019-65851198",
        address: "山西省",
        bank: "交通银行",
        bankAccount: "901234567890123456",
        contacts: "李雪芹",
        contactAddress: "XX省XX市XX区XXè·¯",
        maintainer: "李雪芹",
        maintainDate: "2022-09-26",
      },
      {
        supplierName: "交通银行股份有限公司",
        identifyNumber: "042-26881314",
        address: "江西省",
        bank: "平安银行",
        bankAccount: "123456789012345678",
        contacts: "周白玉",
        contactAddress: "XX省XX市XX区XXè·¯",
        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>
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省XX市XX区XXè·¯",
        maintainer: "李雪芹",
        maintainDate: "2022-09-26",
        contactsPhone: "19345678901",
      },
      {
        supplierName: "中国冶金科工股份有限公司",
        identifyNumber: "123412123123123111",
        address: "山西省",
        bank: "交通银行",
        bankAccount: "901234567890123456",
        contacts: "李雪芹",
        contactAddress: "XX省XX市XX区XXè·¯",
        maintainer: "李雪芹",
        maintainDate: "2022-09-26",
        contactsPhone: "19345678901",
      },
      {
        supplierName: "中国冶金科工股份有限公司",
        identifyNumber: "123412123123123111",
        address: "山西省",
        bank: "交通银行",
        bankAccount: "901234567890123456",
        contacts: "李雪芹",
        contactAddress: "XX省XX市XX区XXè·¯",
        maintainer: "李雪芹",
        maintainDate: "2022-09-26",
        contactsPhone: "19345678901",
      },
      {
        supplierName: "交通银行股份有限公司",
        identifyNumber: "042-26881314",
        address: "江西省",
        bank: "平安银行",
        bankAccount: "123456789012345678",
        contacts: "周白玉",
        contactAddress: "XX省XX市XX区XXè·¯",
        maintainer: "周白玉",
        maintainDate: "2022-08-29",
      },
      {
        supplierName: "中国冶金科工股份有限公司",
        identifyNumber: "019-65851198",
        address: "山西省",
        bank: "交通银行",
        bankAccount: "901234567890123456",
        contacts: "李雪芹",
        contactAddress: "XX省XX市XX区XXè·¯",
        maintainer: "李雪芹",
        maintainDate: "2022-09-26",
      },
      {
        supplierName: "交通银行股份有限公司",
        identifyNumber: "042-26881314",
        address: "江西省",
        bank: "平安银行",
        bankAccount: "123456789012345678",
        contacts: "周白玉",
        contactAddress: "XX省XX市XX区XXè·¯",
        maintainer: "周白玉",
        maintainDate: "2022-08-29",
      },
      {
        supplierName: "中国冶金科工股份有限公司",
        identifyNumber: "019-65851198",
        address: "山西省",
        bank: "交通银行",
        bankAccount: "901234567890123456",
        contacts: "李雪芹",
        contactAddress: "XX省XX市XX区XXè·¯",
        maintainer: "李雪芹",
        maintainDate: "2022-09-26",
      },
      {
        supplierName: "交通银行股份有限公司",
        identifyNumber: "042-26881314",
        address: "江西省",
        bank: "平安银行",
        bankAccount: "123456789012345678",
        contacts: "周白玉",
        contactAddress: "XX省XX市XX区XXè·¯",
        maintainer: "周白玉",
        maintainDate: "2022-08-29",
      },
      {
        supplierName: "中国冶金科工股份有限公司",
        identifyNumber: "019-65851198",
        address: "山西省",
        bank: "交通银行",
        bankAccount: "901234567890123456",
        contacts: "李雪芹",
        contactAddress: "XX省XX市XX区XXè·¯",
        maintainer: "李雪芹",
        maintainDate: "2022-09-26",
      },
      {
        supplierName: "交通银行股份有限公司",
        identifyNumber: "042-26881314",
        address: "江西省",
        bank: "平安银行",
        bankAccount: "123456789012345678",
        contacts: "周白玉",
        contactAddress: "XX省XX市XX区XXè·¯",
        maintainer: "周白玉",
        maintainDate: "2022-08-29",
      },
      {
        supplierName: "中国冶金科工股份有限公司",
        identifyNumber: "019-65851198",
        address: "山西省",
        bank: "交通银行",
        bankAccount: "901234567890123456",
        contacts: "李雪芹",
        contactAddress: "XX省XX市XX区XXè·¯",
        maintainer: "李雪芹",
        maintainDate: "2022-09-26",
      },
      {
        supplierName: "交通银行股份有限公司",
        identifyNumber: "042-26881314",
        address: "江西省",
        bank: "平安银行",
        bankAccount: "123456789012345678",
        contacts: "周白玉",
        contactAddress: "XX省XX市XX区XXè·¯",
        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>
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>
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>
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>
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>
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>