银川
1.销售订单页面展示字段修改
2.客户选择弹框复用调整
3.未使用菜单整理
4.发货通知、销售退货展示字段和操作权限判断修改
已修改12个文件
234 ■■■■ 文件已修改
src/api/erp/sale/order/index.ts 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mes/wm/salesnotice/index.ts 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicData/mdm/index.vue 36 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/sale/order/data.ts 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/sale/order/index.vue 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/wls/productsales/data.ts 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/wls/returnsales/data.ts 30 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/wls/salesnotice/components/select-dialog.vue 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/wls/salesnotice/components/select.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/wls/salesnotice/data.ts 52 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/wls/salesnotice/index.vue 35 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/wls/salesnotice/modules/form.vue 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/erp/sale/order/index.ts
@@ -16,6 +16,7 @@
    status: number; // 状态
    remark: string; // 备注
    outCount: number; // 销售出库数量
    outStatus?: number; // 出库状态:0-未出库,1-部分出库,2-全部出库
    fileUrl?: string; // 附件地址
    inCount?: number; // 采购入库数量
    returnCount: number; // 销售退货数量
@@ -27,6 +28,7 @@
    contractNo?: string; // CRM 合同单号
    needProduction?: number; // 是否需要生产:0-不需要,1-需要
    hasSalesNotice?: boolean; // 是否已生成发货通知单
    canCreateSalesNotice?: boolean; // 是否可以生成发货通知单
    items?: SaleOrderItem[]; // 销售订单产品明细列表
  }
src/api/mes/wm/salesnotice/index.ts
@@ -9,7 +9,7 @@
    code?: string; // 通知单编号
    name?: string; // 通知单名称
    saleOrderId?: number; // 销售订单编号
    salesOrderCode?: string; // 销售订单编号
    saleOrderCode?: string; // 销售订单编号
    clientId?: number; // 客户编号
    clientCode?: string; // 客户编码
    clientName?: string; // 客户名称
src/views/basicData/mdm/index.vue
@@ -3,7 +3,7 @@
import type { MdmItemApi } from '#/api/mdm/item';
import type { MesMdItemTypeApi } from '#/api/mes/md/item/type';
import { ref } from 'vue';
import { computed, ref } from 'vue';
import { confirm, Page, useVbenModal } from '#/packages/effects/common-ui/src';
import { downloadFileFromBlobPart, isEmpty } from '#/packages/utils/src';
@@ -33,6 +33,34 @@
// 分类列表缓存
const categoryList = ref<MesMdItemTypeApi.ItemType[]>([]);
const TAG_COLORS = [
  'green',
  'orange',
  'blue',
  'purple',
  'cyan',
  'magenta',
  'geekblue',
  'volcano',
  'gold',
  'lime',
] as const;
/** 分类ID → 颜色映射(基于分类在列表中的索引循环分配) */
const categoryColorMap = computed(() => {
  const map = new Map<number, string>();
  categoryList.value.forEach((item, index) => {
    map.set(item.id!, TAG_COLORS[index % TAG_COLORS.length]!);
  });
  return map;
});
/** 获取分类Tag颜色 */
function getCategoryColor(categoryId?: number): string {
  if (!categoryId) return '';
  return categoryColorMap.value.get(categoryId) || '';
}
/** 获取分类名称 */
function getCategoryName(categoryId?: number) {
@@ -196,11 +224,7 @@
        />
      </template>
      <template #categoryName="{ row }">
        <Tag v-if="row.categoryId === 1" color="green">{{ getCategoryName(row.categoryId) }}</Tag>
        <Tag v-else-if="row.categoryId === 2" color="orange">{{ getCategoryName(row.categoryId) }}</Tag>
        <Tag v-else-if="row.categoryId === 3" color="blue">{{ getCategoryName(row.categoryId) }}</Tag>
        <Tag v-else-if="row.categoryId === 4" color="purple">{{ getCategoryName(row.categoryId) }}</Tag>
        <Tag v-else-if="row.categoryId === 5" color="cyan">{{ getCategoryName(row.categoryId) }}</Tag>
        <Tag v-if="getCategoryColor(row.categoryId)" :color="getCategoryColor(row.categoryId)">{{ getCategoryName(row.categoryId) }}</Tag>
        <span v-else>{{ getCategoryName(row.categoryId) }}</span>
      </template>
      <template #isBatchManaged="{ row }">
src/views/erp/sale/order/data.ts
@@ -371,8 +371,9 @@
      componentProps: {
        options: [
          { label: '未出库', value: 0 },
          { label: '部分出库', value: 1 },
          { label: '全部出库', value: 2 },
          { label: '已预留', value: 1 },
          { label: '部分出库', value: 2 },
          { label: '全部出库', value: 3 },
        ],
        placeholder: '请选择出库状态',
        allowClear: true,
@@ -445,16 +446,10 @@
      minWidth: 120,
    },
    {
      field: 'outCount',
      title: '出库数量',
      formatter: 'formatAmount3',
      minWidth: 120,
    },
    {
      field: 'returnCount',
      title: '退货数量',
      formatter: 'formatAmount3',
      minWidth: 120,
      field: 'outStatus',
      title: '出库状态',
      minWidth: 100,
      slots: { default: 'outStatus' },
    },
    {
      field: 'totalProductPrice',
src/views/erp/sale/order/index.vue
@@ -260,6 +260,12 @@
        <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 #actions="{ row }">
        <TableAction
          :actions="[
@@ -327,7 +333,7 @@
              type: 'link',
              icon: 'ant-design:file-protect-outlined',
              auth: ['mes:wm-sales-notice:create'],
              ifShow: () => row.status === 20 && !row.hasSalesNotice,
              ifShow: () => row.status === 20 && row.canCreateSalesNotice,
              onClick: handleGenerateNotice.bind(null, row),
            },
            {
src/views/wls/productsales/data.ts
@@ -19,9 +19,10 @@
import { Button } from 'ant-design-vue';
import { z } from '#/adapter/form';
import CrmCustomerSelect from '#/components/crm-customer-select.vue';
import { generateAutoCode } from '#/api/mes/md/autocode/record';
import { ErpSaleOrderSelect } from '#/views/erp/sale/order/components';
import { getRangePickerDefaultProps } from '#/utils';
import { MdClientSelect } from '#/views/mes/md/client/components';
import { MdItemSelect } from '#/views/mes/md/item/components';
import { WmMaterialStockSelect } from '#/views/wls/materialstock/components';
import {
@@ -139,12 +140,29 @@
    },
    {
      fieldName: 'salesOrderCode',
      label: '销售订单编号',
      component: 'Input',
      dependencies: {
        triggerFields: [''],
        show: () => false,
      },
    },
    {
      fieldName: 'saleOrderId',
      label: '销售订单编号',
      component: markRaw(ErpSaleOrderSelect),
      componentProps: {
        disabled: isHeaderReadonly(formType),
        placeholder: '请输入销售订单编号',
        placeholder: '请选择销售订单',
        onChange: (item: any) => {
          if (formApi) {
            formApi.setFieldValue('salesOrderCode', item?.no ?? '');
            if (item?.customerId) {
              formApi.setFieldValue('clientId', item.customerId);
            }
          }
        },
      },
      rules: 'selectRequired',
    },
    {
      fieldName: 'salesDate',
@@ -162,7 +180,7 @@
    {
      fieldName: 'clientId',
      label: '客户',
      component: markRaw(MdClientSelect),
      component: markRaw(CrmCustomerSelect),
      componentProps: {
        disabled: isHeaderReadonly(formType),
        placeholder: '请选择客户',
@@ -269,7 +287,7 @@
    {
      fieldName: 'clientId',
      label: '客户',
      component: markRaw(MdClientSelect),
      component: markRaw(CrmCustomerSelect),
      componentProps: {
        placeholder: '请选择客户',
      },
src/views/wls/returnsales/data.ts
@@ -12,8 +12,9 @@
import { Button } from 'ant-design-vue';
import { z } from '#/adapter/form';
import CrmCustomerSelect from '#/components/crm-customer-select.vue';
import { generateAutoCode } from '#/api/mes/md/autocode/record';
import { MdClientSelect } from '#/views/mes/md/client/components';
import { ErpSaleOrderSelect } from '#/views/erp/sale/order/components';
import { MdItemSelect } from '#/views/mes/md/item/components';
import { WmBatchSelect } from '#/views/wls/batch/components';
import {
@@ -88,16 +89,33 @@
    },
    {
      fieldName: 'salesOrderCode',
      label: '销售订单号',
      component: 'Input',
      componentProps: {
        placeholder: '请输入销售订单号',
      dependencies: {
        triggerFields: [''],
        show: () => false,
      },
    },
    {
      fieldName: 'saleOrderId',
      label: '销售订单号',
      component: markRaw(ErpSaleOrderSelect),
      componentProps: {
        placeholder: '请选择销售订单',
        onChange: (item: any) => {
          if (formApi) {
            formApi.setFieldValue('salesOrderCode', item?.no ?? '');
            if (item?.customerId) {
              formApi.setFieldValue('clientId', item.customerId);
            }
          }
        },
      },
      rules: 'selectRequired',
    },
    {
      fieldName: 'clientId',
      label: '客户',
      component: markRaw(MdClientSelect),
      component: markRaw(CrmCustomerSelect),
      componentProps: {
        placeholder: '请选择客户',
      },
@@ -172,7 +190,7 @@
    {
      fieldName: 'clientId',
      label: '客户',
      component: markRaw(MdClientSelect),
      component: markRaw(CrmCustomerSelect),
      componentProps: {
        placeholder: '请选择客户',
      },
src/views/wls/salesnotice/components/select-dialog.vue
@@ -12,7 +12,7 @@
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { getSalesNoticePage } from '#/api/mes/wm/salesnotice';
import { MdClientSelect } from '#/views/mes/md/client/components';
import CrmCustomerSelect from '#/components/crm-customer-select.vue';
const emit = defineEmits<{
  selected: [rows: MesWmSalesNoticeApi.SalesNotice[]];
@@ -46,7 +46,7 @@
      },
    },
    {
      fieldName: 'salesOrderCode',
      fieldName: 'saleOrderCode',
      label: '销售订单编号',
      component: 'Input',
      componentProps: {
@@ -57,7 +57,7 @@
    {
      fieldName: 'clientId',
      label: '客户',
      component: markRaw(MdClientSelect),
      component: markRaw(CrmCustomerSelect),
      componentProps: {
        placeholder: '请选择客户',
      },
@@ -102,7 +102,7 @@
      minWidth: 150,
    },
    {
      field: 'salesOrderCode',
      field: 'saleOrderCode',
      title: '销售订单编号',
      minWidth: 140,
    },
src/views/wls/salesnotice/components/select.vue
@@ -119,7 +119,7 @@
          <div>编号:{{ selectedItem.code || '-' }}</div>
          <div>名称:{{ selectedItem.name || '-' }}</div>
          <div>客户:{{ selectedItem.clientName || '-' }}</div>
          <div>销售订单:{{ selectedItem.salesOrderCode || '-' }}</div>
          <div>销售订单:{{ selectedItem.saleOrderCode || '-' }}</div>
        </div>
      </template>
      <Input
src/views/wls/salesnotice/data.ts
@@ -8,23 +8,22 @@
import {
  DICT_TYPE,
  MesAutoCodeRuleCode,
  MesWmSalesNoticeOutStatusEnum,
} from '@vben/constants';
import { Button, Tag } from 'ant-design-vue';
import { Button } from 'ant-design-vue';
import { z } from '#/adapter/form';
import { generateAutoCode } from '#/api/mes/md/autocode/record';
import CrmCustomerSelect from '#/components/crm-customer-select.vue';
import { ErpSaleOrderSelect } from '#/views/erp/sale/order/components';
import { MdClientSelect } from '#/views/mes/md/client/components';
import { MdItemSelect } from '#/views/mes/md/item/components';
/** 表单类型 */
export type FormType = 'create' | 'detail' | 'finish' | 'update';
export type FormType = 'create' | 'detail' | 'update';
/** 表单头部是否只读(详情、执行出库态) */
/** 表单头部是否只读(详情态) */
function isHeaderReadonly(formType: FormType): boolean {
  return formType === 'detail' || formType === 'finish';
  return formType === 'detail';
}
/** 新增/修改的表单 */
@@ -93,35 +92,17 @@
        onChange: (item: any) => {
          if (item?.customerId && formApi) {
            formApi.setFieldValue('clientId', item.customerId);
            formApi.setFieldValue('clientName', item.customerName);
          }
        },
      },
    },
    {
      fieldName: 'clientName',
      label: '',
      component: 'Input',
      dependencies: {
        triggerFields: [''],
        show: () => false,
      },
    },
    {
      fieldName: 'clientId',
      label: '客户',
      component: markRaw(MdClientSelect),
      component: markRaw(CrmCustomerSelect),
      componentProps: {
        placeholder: '请选择客户',
        disabled: true,
      },
      dependencies: {
        triggerFields: ['clientName'],
        componentProps: (values) => ({
          placeholder: '请选择客户',
          disabled: true,
          clientName: values.clientName as string,
        }),
      },
      rules: 'selectRequired',
    },
@@ -196,7 +177,7 @@
      },
    },
    {
      fieldName: 'salesOrderCode',
      fieldName: 'saleOrderCode',
      label: '销售订单编号',
      component: 'Input',
      componentProps: {
@@ -207,7 +188,7 @@
    {
      fieldName: 'clientId',
      label: '客户',
      component: markRaw(MdClientSelect),
      component: markRaw(CrmCustomerSelect),
      componentProps: {
        placeholder: '请选择客户',
      },
@@ -230,7 +211,7 @@
      minWidth: 150,
    },
    {
      field: 'salesOrderCode',
      field: 'saleOrderCode',
      title: '销售订单编号',
      minWidth: 140,
    },
@@ -273,20 +254,7 @@
      field: 'outStatus',
      title: '出库状态',
      minWidth: 100,
      cellRender: {
        name: 'CellTag',
        props: {
          formatter: ({ row }: { row: MesWmSalesNoticeApi.SalesNotice }) => {
            const statusMap: Record<number, { color: string; label: string }> = {
              [MesWmSalesNoticeOutStatusEnum.NONE]: { color: 'default', label: '未出库' },
              [MesWmSalesNoticeOutStatusEnum.PARTIAL]: { color: 'warning', label: '部分出库' },
              [MesWmSalesNoticeOutStatusEnum.ALL]: { color: 'success', label: '全部出库' },
            };
            const status = statusMap[row.outStatus ?? MesWmSalesNoticeOutStatusEnum.NONE];
            return { color: status?.color, label: status?.label ?? '未出库' };
          },
        },
      },
      slots: { default: 'outStatus' },
    },
    {
      title: '操作',
src/views/wls/salesnotice/index.vue
@@ -3,10 +3,10 @@
import type { MesWmSalesNoticeApi } from '#/api/mes/wm/salesnotice';
import { Page, useVbenModal } from '@vben/common-ui';
import { MesWmSalesNoticeStatusEnum } from '@vben/constants';
import { MesWmSalesNoticeOutStatusEnum, MesWmSalesNoticeStatusEnum } from '@vben/constants';
import { downloadFileFromBlobPart } from '@vben/utils';
import { Button, message } from 'ant-design-vue';
import { Button, message, Tag } from 'ant-design-vue';
import { useRouter } from 'vue-router';
@@ -29,6 +29,17 @@
const router = useRouter();
const outStatusLabelMap: Record<number, string> = {
  [MesWmSalesNoticeOutStatusEnum.NONE]: '未出库',
  [MesWmSalesNoticeOutStatusEnum.PARTIAL]: '部分出库',
  [MesWmSalesNoticeOutStatusEnum.ALL]: '全部出库',
};
const outStatusColorMap: Record<number, string> = {
  [MesWmSalesNoticeOutStatusEnum.NONE]: 'default',
  [MesWmSalesNoticeOutStatusEnum.PARTIAL]: 'warning',
  [MesWmSalesNoticeOutStatusEnum.ALL]: 'success',
};
/** 刷新表格 */
function handleRefresh() {
  gridApi.query();
@@ -49,20 +60,14 @@
  formModalApi.setData({ formType: 'update', id: row.id }).open();
}
/** 执行出库 */
function handleFinish(row: MesWmSalesNoticeApi.SalesNotice) {
  formModalApi.setData({ formType: 'finish', id: row.id }).open();
}
/** 生成销售出库单 */
async function handleGenerateProductSales(row: MesWmSalesNoticeApi.SalesNotice) {
  try {
    const productSalesId = await generateProductSales(row.id!);
    message.success('生成销售出库单成功');
    // 跳转到销售出库单页面
    router.push({
      path: '/wls/product-sales',
      query: { id: productSalesId },
      name: 'MesWmProductSales',
      query: { id: String(productSalesId) },
    });
  } catch (e) {
    console.error(e);
@@ -150,6 +155,9 @@
          {{ row.code }}
        </Button>
      </template>
      <template #outStatus="{ row }">
        <Tag :color="outStatusColorMap[row.outStatus ?? 0]">{{ outStatusLabelMap[row.outStatus ?? 0] }}</Tag>
      </template>
      <template #actions="{ row }">
        <TableAction
          :actions="[
@@ -180,13 +188,6 @@
              auth: ['mes:wm-product-sales:create'],
              ifShow: row.status === MesWmSalesNoticeStatusEnum.APPROVED,
              onClick: handleGenerateProductSales.bind(null, row),
            },
            {
              label: '执行出库',
              type: 'link',
              auth: ['mes:wm-sales-notice:update'],
              ifShow: row.status === MesWmSalesNoticeStatusEnum.APPROVED,
              onClick: handleFinish.bind(null, row),
            },
          ]"
        />
src/views/wls/salesnotice/modules/form.vue
@@ -30,7 +30,6 @@
  // 是否为编辑模式(可保存)
  ['create', 'update'].includes(formType.value),
);
const isFinish = computed(() => formType.value === 'finish'); // 是否为执行出库模式
const canSubmit = computed(
  () =>
    // 是否可提交
@@ -40,9 +39,6 @@
const getTitle = computed(() => {
  if (formType.value === 'detail') {
    return $t('ui.actionTitle.view', ['发货通知单']);
  }
  if (formType.value === 'finish') {
    return '执行出库';
  }
  return formType.value === 'update'
    ? $t('ui.actionTitle.edit', ['发货通知单'])
@@ -85,11 +81,6 @@
  } finally {
    modalApi.unlock();
  }
}
/** 执行出库(后端暂未实现,提示用户) */
function handleFinish() {
  message.info('执行出库功能暂时不支持,敬请期待!');
}
const [Modal, modalApi] = useVbenModal({
@@ -173,9 +164,6 @@
        >
          <Button type="primary">提交</Button>
        </Popconfirm>
        <Button v-if="isFinish" type="primary" @click="handleFinish">
          执行出库
        </Button>
      </div>
    </template>
  </Modal>