gaoluyang
2026-08-03 af4074fecfc1188e68f695cd490dc9ccb157a94c
src/views/erp/sale/order/index.vue
@@ -2,30 +2,43 @@
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { ErpSaleOrderApi } from '#/api/erp/sale/order';
import { ref } from 'vue';
import { onMounted, ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { Page, useVbenModal } from '../../../../packages/effects/common-ui/src';
import { downloadFileFromBlobPart, isEmpty } from '../../../../packages/utils/src';
import { Page, useVbenModal } from '@vben/common-ui';
import { downloadFileFromBlobPart, isEmpty } from '@vben/utils';
import { message } from 'ant-design-vue';
import { message, Tag, Tooltip } from 'ant-design-vue';
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
import {
  cancelSaleOrder,
  deleteSaleOrder,
  enableSaleOrder,
  exportSaleOrder,
  getSaleOrderPage,
  updateSaleOrderStatus,
} from '#/api/erp/sale/order';
import { generateFromSaleOrder } from '#/api/mes/wm/salesnotice';
import { $t } from '#/locales';
import { useGridColumns, useGridFormSchema } from './data';
import Form from './modules/form.vue';
import SalesNoticeForm from '#/views/wls/salesnotice/modules/form.vue';
/** ERP 销售订单列表 */
defineOptions({ name: 'ErpSaleOrder' });
const router = useRouter();
const route = useRoute();
const [FormModal, formModalApi] = useVbenModal({
  connectedComponent: Form,
  destroyOnClose: true,
});
const [SalesNoticeFormModal, salesNoticeFormModalApi] = useVbenModal({
  connectedComponent: SalesNoticeForm,
  destroyOnClose: true,
});
@@ -83,6 +96,36 @@
  }
}
/** 作废销售订单 */
async function handleCancel(row: ErpSaleOrderApi.SaleOrder) {
  const hideLoading = message.loading({
    content: '正在作废该订单...',
    duration: 0,
  });
  try {
    await cancelSaleOrder(row.id!);
    message.success('作废成功');
    handleRefresh();
  } finally {
    hideLoading();
  }
}
/** 启用销售订单(恢复已作废订单) */
async function handleEnable(row: ErpSaleOrderApi.SaleOrder) {
  const hideLoading = message.loading({
    content: '正在启用该订单...',
    duration: 0,
  });
  try {
    await enableSaleOrder(row.id!);
    message.success('启用成功');
    handleRefresh();
  } finally {
    hideLoading();
  }
}
const checkedIds = ref<number[]>([]);
function handleRowCheckboxChange({
  records,
@@ -97,6 +140,30 @@
  formModalApi.setData({ formType: 'detail', id: row.id }).open();
}
/** 查看关联合同 */
function handleViewContract(row: ErpSaleOrderApi.SaleOrder) {
  if (row.contractId) {
    router.push({
      path: `/crm/contract/detail/${row.contractId}`,
    });
  }
}
/** 生成发货通知单 */
async function handleGenerateNotice(row: ErpSaleOrderApi.SaleOrder) {
  try {
    const noticeId = await generateFromSaleOrder(row.id!);
    message.success('生成发货通知单成功');
    handleRefresh();
    // 直接打开发货通知单详情弹框
    salesNoticeFormModalApi
      .setData({ formType: 'detail', id: noticeId })
      .open();
  } catch (e) {
    console.error(e);
  }
}
const [Grid, gridApi] = useVbenVxeGrid({
  formOptions: {
    schema: useGridFormSchema(),
@@ -108,10 +175,19 @@
    proxyConfig: {
      ajax: {
        query: async ({ page }, formValues) => {
          // 生产状态搜索参数转换:-1(无需生产) → needProduction=0
          const { productionStatus, ...rest } = formValues;
          const params: Record<string, any> = { ...rest };
          if (productionStatus === -1) {
            params.needProduction = 0;
          } else if (productionStatus != null) {
            params.productionStatus = productionStatus;
            params.needProduction = 1;
          }
          return await getSaleOrderPage({
            pageNo: page.currentPage,
            pageSize: page.pageSize,
            ...formValues,
            ...params,
          });
        },
      },
@@ -130,10 +206,20 @@
    checkboxChange: handleRowCheckboxChange,
  },
});
/** 处理从合同跳转过来的查询参数 */
onMounted(() => {
  const orderId = route.query.id;
  if (orderId) {
    formModalApi.setData({ formType: 'detail', id: Number(orderId) }).open();
  }
});
</script>
<template>
  <Page auto-content-height><FormModal @success="handleRefresh" />
  <Page auto-content-height>
    <FormModal @success="handleRefresh" />
    <SalesNoticeFormModal />
    <Grid table-title="销售订单列表">
      <template #toolbar-tools>
        <TableAction
@@ -167,6 +253,46 @@
          ]"
        />
      </template>
      <template #no="{ row }">
        <Tooltip v-if="row.status === 30" title="该订单已作废,订单已失效">
          <span class="text-red-500 cursor-pointer" @click="handleDetail(row)">
            {{ row.no }}
          </span>
        </Tooltip>
        <a v-else class="text-primary cursor-pointer" @click="handleDetail(row)">
          {{ row.no }}
        </a>
      </template>
      <template #contractNo="{ row }">
        <a v-if="row.contractId" class="text-primary cursor-pointer" @click="handleViewContract(row)">
          {{ row.contractNo }}
        </a>
        <span v-else>-</span>
      </template>
      <template #status="{ row }">
        <Tag v-if="row.status === 10" color="warning">未审核</Tag>
        <Tag v-if="row.status === 20" color="success">已审核</Tag>
        <Tag v-if="row.status === 30" color="error">已作废</Tag>
      </template>
      <template #needProduction="{ row }">
        <Tag v-if="row.needProduction === 1" color="success">是</Tag>
        <Tag v-else color="default">否</Tag>
      </template>
      <template #outStatus="{ row }">
        <Tag v-if="row.outStatus === 0" color="default">未出库</Tag>
        <Tag v-else-if="row.outStatus === 1" color="processing">已预留</Tag>
        <Tag v-else-if="row.outStatus === 2" color="warning">部分出库</Tag>
        <Tag v-else-if="row.outStatus === 3" color="success">全部出库</Tag>
      </template>
      <template #productionStatus="{ row }">
        <template v-if="row.needProduction !== 1">
          <Tag color="default">无需生产</Tag>
        </template>
        <template v-else>
          <Tag v-if="row.productionStatus === 0" color="warning">未完成</Tag>
          <Tag v-else-if="row.productionStatus === 1" color="success">已完成</Tag>
        </template>
      </template>
      <template #actions="{ row }">
        <TableAction
          :actions="[
@@ -182,22 +308,60 @@
              type: 'link',
              icon: ACTION_ICON.EDIT,
              auth: ['erp:sale-order:update'],
              ifShow: () => row.status !== 20,
              ifShow: () => row.status === 10,
              onClick: handleEdit.bind(null, row),
            },
            {
              label: row.status === 10 ? '审批' : '反审批',
              label: '审批',
              type: 'link',
              icon: ACTION_ICON.AUDIT,
              auth: ['erp:sale-order:update-status'],
              ifShow: () => row.status === 10,
              popConfirm: {
                title: `确认${row.status === 10 ? '审批' : '反审批'}${row.no}吗?`,
                confirm: handleUpdateStatus.bind(
                  null,
                  row,
                  row.status === 10 ? 20 : 10,
                ),
                title: `确认审批${row.no}吗?`,
                confirm: handleUpdateStatus.bind(null, row, 20),
              },
            },
            {
              label: '反审批',
              type: 'link',
              icon: ACTION_ICON.AUDIT,
              auth: ['erp:sale-order:update-status'],
              ifShow: () => row.status === 20,
              popConfirm: {
                title: `确认反审批${row.no}吗?`,
                confirm: handleUpdateStatus.bind(null, row, 10),
              },
            },
            {
              label: '作废',
              type: 'link',
              icon: 'ant-design:stop-outlined',
              auth: ['erp:sale-order:cancel'],
              ifShow: () => row.status === 20,
              popConfirm: {
                title: `确认作废${row.no}吗?作废后不可恢复!`,
                confirm: handleCancel.bind(null, row),
              },
            },
            {
              label: '启用',
              type: 'link',
              icon: 'ant-design:check-circle-outlined',
              auth: ['erp:sale-order:enable'],
              ifShow: () => row.status === 30,
              popConfirm: {
                title: `确认启用${row.no}吗?`,
                confirm: handleEnable.bind(null, row),
              },
            },
            {
              label: '生成发货通知单',
              type: 'link',
              icon: 'ant-design:file-protect-outlined',
              auth: ['mes:wm-sales-notice:create'],
              ifShow: () => row.status === 20 && row.canCreateSalesNotice,
              onClick: handleGenerateNotice.bind(null, row),
            },
            {
              label: $t('common.delete'),
@@ -205,6 +369,7 @@
              danger: true,
              icon: ACTION_ICON.DELETE,
              auth: ['erp:sale-order:delete'],
              ifShow: () => row.status === 10,
              popConfirm: {
                title: $t('ui.actionMessage.deleteConfirm', [row.no]),
                confirm: handleDelete.bind(null, [row.id!]),