huminmin
2026-05-08 1455e8a5dcea2209b4d1baf4d513aa8fbfb2b39b
src/views/financialManagement/revenueManagement/index.vue
@@ -1,24 +1,24 @@
<template>
  <div class="app-container">
    <el-form :model="filters" :inline="true">
      <el-form-item label="录入日期:">
      <el-form-item label="收入日期:">
        <el-date-picker v-model="filters.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange"
                        placeholder="请选择" clearable @change="changeDaterange" />
                        placeholder="请选择" clearable @change="changeDaterange"/>
      </el-form-item>
      <el-form-item label="收款方式:">
        <el-select
                v-model="filters.incomeMethod"
                placeholder="请选择"
                clearable
                style="width: 200px;"
              >
                <el-option
                  v-for="item in payment_methods"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value"
                />
              </el-select>
            v-model="filters.incomeMethodLabel"
            placeholder="请选择"
            clearable
            style="width: 200px;"
        >
          <el-option
              v-for="item in incomeMethodOptions"
              :key="item.value"
              :label="item.label"
              :value="item.value"
          />
        </el-select>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="getTableData">搜索</el-button>
@@ -29,39 +29,51 @@
      <div class="actions">
        <div></div>
        <div>
          <el-button type="primary" @click="add" icon="Plus"> 新增 </el-button>
          <el-button type="primary" @click="add" icon="Plus"> 新增</el-button>
          <el-button @click="handleOut" icon="download">导出</el-button>
          <el-button
            type="danger"
            icon="Delete"
            :disabled="multipleList.length <= 0"
            @click="deleteRow(multipleList.map((item) => item.id))"
              type="danger"
              icon="Delete"
              :disabled="multipleList.length <= 0 || hasBusinessIdInSelection"
              @click="handleBatchDelete"
          >
            批量删除
          </el-button>
        </div>
      </div>
      <PIMTable
        rowKey="id"
        isSelection
        :column="columns"
        :tableData="dataList"
        :page="{
          rowKey="id"
          isSelection
          :column="columns"
          :tableData="dataList"
          :page="{
          current: pagination.currentPage,
          size: pagination.pageSize,
          total: pagination.total,
        }"
        @selection-change="handleSelectionChange"
        @pagination="changePage"
          :isShowSummary="true"
          :summaryMethod="summarizeMainTable"
          @selection-change="handleSelectionChange"
          @pagination="changePage"
      >
        <template #incomeMethodSlot="{ row }">
          <el-tag>
            {{ getIncomeMethodLabel(row) }}
          </el-tag>
        </template>
        <template #operation="{ row }">
          <el-button type="primary" text @click="edit(row.id)" icon="editPen">
          <el-button
              type="primary"
              link
              :disabled="!!row.businessId"
              @click="edit(row.id)"
          >
            编辑
          </el-button>
          <el-button
            type="primary"
            text
            @click="openFilesFormDia(row)"
              type="primary"
              link
              @click="openFilesFormDia(row)"
          >
            附件
          </el-button>
@@ -69,18 +81,16 @@
      </PIMTable>
    </div>
    <Modal ref="modalRef" @success="getTableData"></Modal>
    <files-dia ref="filesDia"></files-dia>
    <FileListDialog v-if="fileListDialogVisible" :record-id="currentRecordId" record-type="account_income" v-model:visible="fileListDialogVisible"/>
  </div>
</template>
<script setup>
import { usePaginationApi } from "@/hooks/usePaginationApi";
import { listPage, delAccountIncome } from "@/api/financialManagement/revenueManagement";
import { onMounted, getCurrentInstance } from "vue";
import Modal from "./Modal.vue";
import { ElMessageBox, ElMessage } from "element-plus";
import {usePaginationApi} from "@/hooks/usePaginationApi";
import {listPage, delAccountIncome} from "@/api/financialManagement/revenueManagement";
import {onMounted, getCurrentInstance, ref, computed} from "vue";
import {ElMessageBox, ElMessage} from "element-plus";
import dayjs from "dayjs";
import FilesDia from "./filesDia.vue";
defineOptions({
  name: "收入管理",
@@ -88,11 +98,27 @@
// 表格多选框选中项
const multipleList = ref([]);
const { proxy } = getCurrentInstance();
const {proxy} = getCurrentInstance();
const modalRef = ref();
const { payment_methods } = proxy.useDict("payment_methods");
const { income_types } = proxy.useDict("income_types");
const filesDia = ref()
const {payment_methods} = proxy.useDict("payment_methods");
const {receipt_payment_type} = proxy.useDict("receipt_payment_type");
const {income_types} = proxy.useDict("income_types");
const fileListRef = ref(null);
const fileListDialogVisible = ref(false);
const currentRecordId = ref(0);
const incomeMethodOptions = computed(() => {
  const merged = [...(payment_methods.value || []), ...(receipt_payment_type.value || [])];
  const uniqueMap = new Map();
  merged.forEach((item) => {
    const label = item?.label;
    if (!label) return;
    if (!uniqueMap.has(label)) {
      uniqueMap.set(label, {label, value: label});
    }
  });
  return Array.from(uniqueMap.values());
});
const {
  filters,
@@ -103,117 +129,154 @@
  resetFilters,
  onCurrentChange,
} = usePaginationApi(
  listPage,
  {
    incomeMethod: undefined,
  },
  [
    listPage,
    {
      label: "收入日期",
      align: "center",
      prop: "incomeDate",
      incomeMethodLabel: undefined,
      entryDate: undefined,
    },
    {
      label: "收入类型",
      align: "center",
      prop: "incomeType",
      dataType: "tag",
      formatData: (params) => {
        if (income_types.value.find((m) => m.value == params)) {
          return income_types.value.find((m) => m.value == params).label;
        } else {
          return null
        }
    [
      {
        label: "收入日期",
        prop: "incomeDate",
      },
    },
    {
      label: "客户名称",
      align: "center",
      prop: "customerName",
    },
    {
      label: "收入金额",
      align: "center",
      prop: "incomeMoney",
    },
    {
      label: "收入描述",
      align: "center",
      prop: "incomeDescribed",
    },
    {
      label: "收款方式",
      align: "center",
      prop: "incomeMethod",
      dataType: "tag",
      formatData: (params) => {
        if (payment_methods.value.find((m) => m.value == params)) {
          return payment_methods.value.find((m) => m.value == params).label;
        } else {
          return null
        }
      {
        label: "收入类型",
        prop: "incomeType",
        dataType: "tag",
        formatData: (params) => {
          if (income_types.value.find((m) => m.value == params)) {
            return income_types.value.find((m) => m.value == params).label;
          } else {
            return null
          }
        },
      },
    },
    {
      label: "发票号码",
      align: "center",
      prop: "invoiceNumber",
      {
        label: "客户名称",
        prop: "customerName",
        width: '200'
    },
    {
      label: "备注",
      align: "center",
      prop: "note",
      },
      {
        label: "收入金额",
        prop: "incomeMoney",
    },
    {
      label: "录入人",
      align: "center",
      prop: "inputUser",
    },
    {
      label: "录入日期",
      align: "center",
      prop: "inputTime",
      },
      {
        label: "收入描述",
        prop: "incomeDescribed",
    },
      },
      {
        label: "收款方式",
        prop: "incomeMethodLabel",
        align: 'center',
        width: '100',
        dataType: "slot",
        slot: "incomeMethodSlot",
      },
      {
        label: "发票号码",
        prop: "invoiceNumber",
      },
      {
        label: "备注",
        prop: "note",
      },
      {
        label: "录入人",
        prop: "inputUser",
      },
      {
        label: "录入日期",
        prop: "inputTime",
      },
      {
        fixed: "right",
        label: "操作",
        dataType: "slot",
        slot: "operation",
        align: "center",
        width: "160px",
      },
    ],
    undefined,
    {
      fixed: "right",
      label: "操作",
      dataType: "slot",
      slot: "operation",
      align: "center",
      width: "200px",
    },
  ]
      incomeMethodLabel: (value) => ({
        incomeMethodLabel: value || undefined,
      }),
    }
);
// 表格合计:收入金额
const summarizeMainTable = (param) => {
  return proxy.summarizeTable(param, ["incomeMoney"]);
};
const getIncomeMethodLabel = (row) => {
  const methodValue = row?.incomeMethod;
  const dictList = String(row?.businessType) === "1"
      ? receipt_payment_type.value
      : payment_methods.value;
  return dictList.find((item) => item.value == methodValue)?.label || "--";
};
// 多选后做什么
const handleSelectionChange = (selectionList) => {
  multipleList.value = selectionList;
};
// 判断选中的项中是否有 businessId
const hasBusinessIdInSelection = computed(() => {
  return multipleList.value.some(item => item.businessId);
});
const add = () => {
  modalRef.value.openModal();
};
const edit = (id) => {
  // 检查当前行是否有 businessId
  const row = dataList.value.find(item => item.id === id);
  if (row && row.businessId) {
    proxy.$modal.msgWarning("该记录已关联业务,不能编辑");
    return;
  }
  modalRef.value.loadForm(id);
};
const changePage = ({ page, limit }) => {
const changePage = ({page, limit}) => {
  pagination.currentPage = page;
   pagination.pageSize = limit;
  pagination.pageSize = limit;
  onCurrentChange(page);
};
const deleteRow = (id) => {
  // 如果是数组,检查是否有 businessId
  if (Array.isArray(id)) {
    const hasBusinessId = id.some(itemId => {
      const row = dataList.value.find(item => item.id === itemId);
      return row && row.businessId;
    });
    if (hasBusinessId) {
      proxy.$modal.msgWarning("选中的记录中包含已关联业务的记录,不能删除");
      return;
    }
  } else {
    // 单个删除,检查是否有 businessId
    const row = dataList.value.find(item => item.id === id);
    if (row && row.businessId) {
      proxy.$modal.msgWarning("该记录已关联业务,不能删除");
      return;
    }
  }
  ElMessageBox.confirm("此操作将永久删除该数据, 是否继续?", "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  }).then(async () => {
    const { code } = await delAccountIncome(id);
    const {code} = await delAccountIncome(id);
    if (code == 200) {
      ElMessage({
        type: "success",
@@ -224,11 +287,30 @@
  });
};
// 批量删除
const handleBatchDelete = () => {
  if (multipleList.value.length === 0) {
    proxy.$modal.msgWarning("请选择要删除的数据");
    return;
  }
  // 检查是否有 businessId
  if (hasBusinessIdInSelection.value) {
    proxy.$modal.msgWarning("选中的记录中包含已关联业务的记录,不能删除");
    return;
  }
  const ids = multipleList.value.map((item) => item.id);
  deleteRow(ids);
};
const changeDaterange = (value) => {
  if (value) {
    filters.entryDate = value;
    filters.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
    filters.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
  } else {
    filters.entryDate = null;
    filters.entryDateStart = undefined;
    filters.entryDateEnd = undefined;
  }
@@ -241,27 +323,20 @@
    cancelButtonText: "取消",
    type: "warning",
  })
    .then(() => {
      proxy.download(`/account/accountIncome/export`, {}, "收入台账.xlsx");
    })
    .catch(() => {
      proxy.$modal.msg("已取消");
    });
      .then(() => {
        proxy.download(`/account/accountIncome/export`, {}, "收入台账.xlsx");
      })
      .catch(() => {
        proxy.$modal.msg("已取消");
      });
};
// 打开附件弹框
const openFilesFormDia = (row) => {
  nextTick(() => {
    filesDia.value?.openDialog( row,'收入')
  })
const openFilesFormDia = async (row) => {
  currentRecordId.value = row.id;
  fileListDialogVisible.value = true;
};
onMounted(() => {
  filters.entryDate = [
    dayjs().format("YYYY-MM-DD"),
    dayjs().add(1, "day").format("YYYY-MM-DD"),
  ]
  filters.entryDateStart = dayjs().format("YYYY-MM-DD")
  filters.entryDateEnd = dayjs().add(1, "day").format("YYYY-MM-DD")
  getTableData();
});
</script>
@@ -270,6 +345,7 @@
.table_list {
  margin-top: unset;
}
.actions {
  display: flex;
  justify-content: space-between;