gaoluyang
6 天以前 fa95ef8dd4c23d05bf7bee16927f207cc0793412
诚发五金:按需求收敛页面,去掉无入口的工序/库区库位强依赖

- 工单表单移除「工序」页签,不再要求先维护工序主数据
- 工作站表单去掉工序必选与工具页签
- 排产/任务列表按单工序展示,路线与工序可空
- 库区、库位选择改为可手填新建
- 仓库页去掉已无菜单的库位跳转链接
- MPS「查看工单」跳转路径修正为 /mes/pro/work-order
- 物料管理隐藏需求外的智能体导入

Co-Authored-By: Claude Code <noreply@anthropic.com>
已修改10个文件
394 ■■■■■ 文件已修改
src/views/basicData/mdm/index.vue 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mes/md/workstation/data.ts 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mes/md/workstation/modules/form.vue 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mes/pro/mps/index.vue 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mes/pro/task/modules/schedule-form.vue 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mes/pro/task/modules/task-list.vue 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mes/pro/workorder/modules/form.vue 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/wls/warehouse/components/area-select.vue 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/wls/warehouse/components/location-select.vue 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/wls/warehouse/index.vue 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicData/mdm/index.vue
@@ -5,8 +5,6 @@
import { computed, ref } from 'vue';
import { isAiEnable } from '@vben/hooks';
import { confirm, Page, useVbenModal } from '#/packages/effects/common-ui/src';
import { downloadFileFromBlobPart, isEmpty } from '#/packages/utils/src';
@@ -25,7 +23,6 @@
import { $t } from '#/locales';
import { useGridColumns, useGridFormSchema } from './data';
import AgentImport from './modules/agent-import.vue';
import Form from './modules/form.vue';
import ImportForm from './modules/import-form.vue';
@@ -38,11 +35,6 @@
const [ImportModal, importModalApi] = useVbenModal({
  connectedComponent: ImportForm,
  destroyOnClose: true,
});
const [AgentImportModal, agentImportModalApi] = useVbenModal({
  connectedComponent: AgentImport,
  destroyOnClose: true,
});
@@ -105,12 +97,7 @@
  importModalApi.open();
}
/** 智能体导入物料 */
function handleAgentImport() {
  agentImportModalApi.open();
}
/** 工具栏按钮:智能体导入受 AI 总开关控制 */
/** 工具栏按钮 */
const toolbarActions = computed(() => [
  {
    label: $t('ui.actionTitle.create', ['物料']),
@@ -126,17 +113,6 @@
    auth: ['mdm:item:import'],
    onClick: handleImport,
  },
  ...(isAiEnable()
    ? [
        {
          label: '智能体导入',
          type: 'primary' as const,
          icon: ACTION_ICON.UPLOAD,
          auth: ['mdm:item:import'],
          onClick: handleAgentImport,
        },
      ]
    : []),
  {
    label: $t('ui.actionTitle.export'),
    type: 'primary' as const,
@@ -281,7 +257,6 @@
  <Page auto-content-height>
    <FormModal @success="handleRefresh" />
    <ImportModal @success="handleRefresh" />
    <AgentImportModal @success="handleRefresh" />
    <Grid table-title="物料列表">
      <template #toolbar-tools>
        <TableAction :actions="toolbarActions" />
src/views/mes/md/workstation/data.ts
@@ -18,7 +18,6 @@
import { getWarehouseSimpleList } from '#/api/mes/wm/warehouse';
import { getWarehouseAreaSimpleList } from '#/api/mes/wm/warehouse/area';
import { getWarehouseLocationSimpleList } from '#/api/mes/wm/warehouse/location';
import { ProProcessSelect } from '#/views/mes/process-design/process/components';
import { MdWorkshopSelect } from './components';
@@ -90,15 +89,6 @@
      componentProps: {
        placeholder: '请输入工作站地点',
      },
    },
    {
      fieldName: 'processId',
      label: '所属工序',
      component: markRaw(ProProcessSelect),
      componentProps: {
        placeholder: '请选择所属工序',
      },
      rules: 'selectRequired',
    },
    {
      fieldName: 'warehouseId',
@@ -214,15 +204,6 @@
      },
    },
    {
      fieldName: 'processId',
      label: '所属工序',
      component: markRaw(ProProcessSelect),
      componentProps: {
        allowClear: true,
        placeholder: '请选择工序',
      },
    },
    {
      fieldName: 'status',
      label: '状态',
      component: 'Select',
@@ -260,11 +241,6 @@
      width: 140,
    },
    {
      field: 'processName',
      title: '所属工序',
      width: 140,
    },
    {
      field: 'status',
      title: '状态',
      width: 120,
@@ -298,14 +274,6 @@
      componentProps: {
        allowClear: true,
        placeholder: '请输入工作站编码',
      },
    },
    {
      fieldName: 'processId',
      label: '所属工序',
      component: markRaw(ProProcessSelect),
      componentProps: {
        placeholder: '请选择工序',
      },
    },
    {
src/views/mes/md/workstation/modules/form.vue
@@ -21,7 +21,6 @@
  import { useFormSchema } from "../data";
  import MachineList from "./machine-list.vue";
  import ToolList from "./tool-list.vue";
  import WorkerList from "./worker-list.vue";
  const emit = defineEmits(["success"]);
@@ -132,11 +131,6 @@
                    tab="设备资源">
        <MachineList :form-type="formType"
                     :workstation-id="formData.id" />
      </Tabs.TabPane>
      <Tabs.TabPane key="tool"
                    tab="工装夹具">
        <ToolList :form-type="formType"
                  :workstation-id="formData.id" />
      </Tabs.TabPane>
      <Tabs.TabPane key="worker"
                    tab="人力资源">
src/views/mes/pro/mps/index.vue
@@ -242,7 +242,7 @@
function handleGoToWorkOrder(row: MesProMpsApi.Mps) {
  if (row.workOrderId) {
    router.push({
      path: '/mes/pro/workorder',
      path: '/mes/pro/work-order',
      query: { id: row.workOrderId },
    });
  }
src/views/mes/pro/task/modules/schedule-form.vue
@@ -43,24 +43,18 @@
  wrapperClass: 'grid-cols-3',
});
/** 加载工单工序列表(仅使用工单工序,不回退到工艺路线模板) */
/** 加载工单工序列表;未配置工序时按单工序生产处理 */
async function loadRouteProcesses(workOrderId: number, productId: number) {
  const woProcesses = await getWorkOrderProcessListByWorkOrderId(workOrderId);
  if (!woProcesses || woProcesses.length === 0) {
    message.warning('当前订单未配置工序,请先在工单中维护工序信息');
    return;
  }
  // 确定工艺路线ID:工单路线 → 产品路线
  // 确定工艺路线ID:有工序时按产品路线带出;未配置工序时按单工序生产
  let tempRouteId = 0;
  if (workOrder.value?.routeId) {
    tempRouteId = workOrder.value.routeId;
  } else {
  if (woProcesses && woProcesses.length > 0) {
    const processes = await getRouteProcessListByProduct(productId);
    tempRouteId = processes?.[0]?.routeId ?? 0;
  }
  currentRouteId.value = tempRouteId;
  routeProcessList.value = [...woProcesses].toSorted(
  routeProcessList.value = [...(woProcesses ?? [])].toSorted(
    (a, b) => (a.sort ?? 0) - (b.sort ?? 0),
  );
}
@@ -121,50 +115,58 @@
  <Modal :title="getTitle" class="w-4/5">
    <Form class="mx-4" />
    <!-- 工序步骤导航 + 当前工序任务列表 -->
    <template v-if="routeProcessList.length > 0 && workOrder?.id">
      <Steps
        v-model:current="activeProcessStep"
        class="my-4 px-4"
        size="small"
        type="navigation"
      >
        <Steps.Step
          v-for="rp in routeProcessList"
          :key="rp.processId"
          :title="rp.processName"
          :description="rp.paramTemplateId ? `参数模板 #${rp.paramTemplateId}` : '未配置参数模板'"
        />
      </Steps>
      <template v-for="(rp, index) in routeProcessList" :key="rp.processId">
        <Card
          v-if="activeProcessStep === index"
          class="mx-4"
    <template v-if="workOrder?.id">
      <template v-if="routeProcessList.length > 0">
        <Steps
          v-model:current="activeProcessStep"
          class="my-4 px-4"
          size="small"
          type="navigation"
        >
          <TaskList
            :color-code="rp.colorCode"
            :disabled="isReadonly"
            :item-id="rp.outputItemId || workOrder.productId"
            :process-id="rp.processId!"
            :route-id="currentRouteId"
            :work-order-id="workOrder.id!"
            :work-order-quantity="workOrder.quantity"
          <Steps.Step
            v-for="rp in routeProcessList"
            :key="rp.processId"
            :title="rp.processName"
            :description="rp.paramTemplateId ? `参数模板 #${rp.paramTemplateId}` : '未配置参数模板'"
          />
        </Card>
        </Steps>
        <template v-for="(rp, index) in routeProcessList" :key="rp.processId">
          <Card
            v-if="activeProcessStep === index"
            class="mx-4"
          >
            <TaskList
              :color-code="rp.colorCode"
              :disabled="isReadonly"
              :item-id="rp.outputItemId || workOrder.productId"
              :process-id="rp.processId!"
              :route-id="currentRouteId"
              :work-order-id="workOrder.id!"
              :work-order-quantity="workOrder.quantity"
            />
          </Card>
        </template>
      </template>
      <!-- 未配置工序/工艺路线:整张工单按单工序排产 -->
      <Card v-else class="mx-4">
        <TaskList
          :disabled="isReadonly"
          :item-id="workOrder.productId"
          :route-id="currentRouteId || undefined"
          :work-order-id="workOrder.id!"
          :work-order-quantity="workOrder.quantity"
        />
      </Card>
    </template>
    <template #prepend-footer>
      <div class="flex flex-auto items-center gap-2">
        <template v-if="formType === 'schedule'">
          <Popconfirm
            v-if="routeProcessList.length > 0"
            title="确认要完成该订单吗?完成后订单下所有任务将标记为已完成。"
            @confirm="handleFinish"
          >
            <Button type="primary">完成</Button>
          </Popconfirm>
          <span v-else class="text-gray-400 text-sm">
            当前订单未配置工序,请先在工单中维护工序信息后再完成
          </span>
        </template>
      </div>
    </template>
src/views/mes/pro/task/modules/task-list.vue
@@ -20,8 +20,8 @@
  colorCode?: string;
  disabled?: boolean;
  itemId?: number;
  processId: number;
  routeId: number;
  processId?: number;
  routeId?: number;
  workOrderId: number;
  workOrderQuantity?: number;
}>();
@@ -103,13 +103,24 @@
          if (!props.workOrderId) {
            return { list: [], total: 0 };
          }
          return await getTaskPage({
          const params: {
            pageNo: number;
            pageSize: number;
            processId?: number;
            routeId?: number;
            workOrderId: number;
          } = {
            pageNo: 1,
            pageSize: 100,
            processId: props.processId,
            routeId: props.routeId,
            workOrderId: props.workOrderId,
          });
          };
          if (props.processId != null) {
            params.processId = props.processId;
          }
          if (props.routeId != null) {
            params.routeId = props.routeId;
          }
          return await getTaskPage(params);
        },
      },
    },
src/views/mes/pro/workorder/modules/form.vue
@@ -2,7 +2,6 @@
  import type { FormType } from "../data";
  import type { MesProWorkOrderApi } from "#/api/mes/pro/workorder";
  import type { MesProWorkOrderProcessApi } from "#/api/mes/pro/workorder/process";
  import { computed, ref } from "vue";
@@ -22,7 +21,6 @@
    getWorkOrder,
    updateWorkOrder,
  } from "#/api/mes/pro/workorder";
  import { batchSaveWorkOrderProcess, getWorkOrderProcessListByWorkOrderId } from "#/api/mes/pro/workorder/process";
  import { $t } from "#/locales";
  // import { BarcodeDetail } from "#/views/wls/barcode/components";
@@ -35,17 +33,13 @@
  import ItemList from "./item-list.vue";
  import MaterialPreview from "./material-preview.vue";
  import ProcessList from "./process-list.vue";
  const emit = defineEmits(["success"]);
  const formType = ref<FormType>("create");
  const formData = ref<MesProWorkOrderApi.WorkOrder>();
  const originalSnapshot = ref("");
  const subTabsName = ref("process");
  const subTabsName = ref("item");
  // const barcodeDetailRef = ref<InstanceType<typeof BarcodeDetail>>();
  const processListRef = ref<InstanceType<typeof ProcessList>>();
  const currentProductId = ref<number>(); // 当前选中的产品 ID(用于工序加载)
  const tempProcessList = ref<MesProWorkOrderProcessApi.WorkOrderProcess[]>([]); // 临时工序列表
  const previewParams = ref<{ productId?: number; quantity?: number }>({}); // 辅料预览参数
  const isEditable = computed(() =>
@@ -107,13 +101,6 @@
      if (fieldsChanged.includes('factoryId')) {
        await formApi.setFieldValue('workshopId', undefined);
      }
      // 产品变更时,触发工序加载
      if (isCreateMode.value && fieldsChanged.includes('productId')) {
        const newProductId = values.productId;
        if (newProductId && newProductId !== currentProductId.value) {
          currentProductId.value = newProductId;
        }
      }
      // 同步辅料预览参数(产品 / 数量变化时自动重新计算辅料与库存)
      if (
        fieldsChanged.includes('productId') ||
@@ -152,13 +139,6 @@
        data.feedbackRole = data.feedbackRole.join(',');
      }
      await updateWorkOrder({ ...formData.value, ...data });
      if (tempProcessList.value.length > 0) {
        const processList = tempProcessList.value.map(item => ({
          ...item,
          workOrderId: formData.value!.id,
        }));
        await batchSaveWorkOrderProcess(processList);
      }
      formData.value = { ...formData.value, ...data };
      originalSnapshot.value = JSON.stringify(await formApi.getValues());
      emit('success');
@@ -224,11 +204,6 @@
    });
  }
  /** 工序列表变化回调 */
  function handleProcessListChange(list: MesProWorkOrderProcessApi.WorkOrderProcess[]) {
    tempProcessList.value = list;
  }
  const [Modal, modalApi] = useVbenModal({
    async onConfirm() {
      // ---- 确认订单模式 ----
@@ -254,21 +229,7 @@
              originalSnapshot.value = current;
            }
          }
          // 2. 批量保存工序(如果有)
          if (tempProcessList.value.length > 0) {
            const processList = tempProcessList.value.map(item => ({
              ...item,
              workOrderId: formData.value!.id,
            }));
            await batchSaveWorkOrderProcess(processList);
          }
          // 3. 校验是否有工序
          const processes = await getWorkOrderProcessListByWorkOrderId(formData.value.id);
          if (!processes || processes.length === 0) {
            message.warning('当前订单未配置工序,请先在工单中维护工序信息后再确认');
            return;
          }
          // 4. 确认工单
          // 2. 确认工单(未配置工序时按单工序生产)
          await confirmWorkOrder(formData.value.id);
          message.success('订单已确认');
          await modalApi.close();
@@ -281,12 +242,6 @@
      // ---- 完成订单模式 ----
      if (isFinish.value) {
        if (!formData.value?.id) return;
        // 校验是否有工序
        const processes = await getWorkOrderProcessListByWorkOrderId(formData.value.id);
        if (!processes || processes.length === 0) {
          message.warning('当前订单未配置工序,请先在工单中维护工序信息后再完成');
          return;
        }
        try {
          await confirm('确认要完成该订单吗?');
        } catch {
@@ -319,14 +274,6 @@
        if (formData.value?.id) {
          // 编辑模式
          await updateWorkOrder({ ...formData.value, ...data });
          // 批量保存工序
          if (tempProcessList.value.length > 0) {
            const processList = tempProcessList.value.map(item => ({
              ...item,
              workOrderId: formData.value!.id,
            }));
            await batchSaveWorkOrderProcess(processList);
          }
          formData.value = { ...formData.value, ...data };
          emit("success");
          message.success($t("ui.actionMessage.operationSuccess"));
@@ -336,14 +283,6 @@
          const insufficient = await checkMaterialStock(data);
          if (!insufficient) return;
          const id = await createWorkOrder(data);
          // 批量保存工序
          if (tempProcessList.value.length > 0) {
            const processList = tempProcessList.value.map(item => ({
              ...item,
              workOrderId: id,
            }));
            await batchSaveWorkOrderProcess(processList);
          }
          formData.value = {
            ...data,
            id,
@@ -363,8 +302,6 @@
      if (!isOpen) {
        formData.value = undefined;
        originalSnapshot.value = "";
        currentProductId.value = undefined;
        tempProcessList.value = [];
        previewParams.value = {};
        return;
      }
@@ -374,8 +311,7 @@
        parentRow?: MesProWorkOrderApi.WorkOrder;
      }>();
      formType.value = data.formType;
      subTabsName.value = "process";
      tempProcessList.value = [];
      subTabsName.value = "item";
      applySchema();
      if (data?.id) {
        modalApi.lock();
@@ -386,7 +322,6 @@
            formValues.feedbackRole = formValues.feedbackRole.split(',');
          }
          await formApi.setValues(formValues);
          currentProductId.value = formData.value.productId;
        } finally {
          modalApi.unlock();
        }
@@ -412,29 +347,14 @@
         class="w-3/5"
         content-class="!max-h-[80vh] overflow-y-auto">
    <Form class="mx-4" />
    <!-- 工序 / 物料需求 Tab -->
    <!-- 物料需求(辅料明细)-->
    <template v-if="showTabs">
      <Tabs v-model:active-key="subTabsName"
            class="mx-4">
        <Tabs.TabPane key="process"
                      tab="工序"
                      forceRender>
          <p class="mb-3 text-xs text-gray-400 leading-relaxed">
            新增模式会自动从所选产品的工艺路线带出工序,点击行首手柄可拖拽调整顺序;「关键工序」需重点管控、「质检工序」由质检人员检验、勾选「倒冲」的工序在报工后按投料用量自动扣减物料库存。每道工序可点「新增物料」配置投料明细。
          </p>
          <ProcessList
            ref="processListRef"
            :form-type="formType"
            :work-order="formData || {}"
            :work-order-id="formData?.id"
            :product-id="currentProductId"
            @process-list-change="handleProcessListChange"
          />
        </Tabs.TabPane>
        <Tabs.TabPane key="item"
                      tab="物料需求">
          <p class="mb-3 text-xs text-gray-400 leading-relaxed">
            物料需求按各工序「投料明细」×订单数量自动汇总生成,仅供查看;如需调整,请回到「工序」页签维护投料。新增工单时会按所选产品与数量预先计算辅料用量及库存情况。
            新增工单时会按所选产品与数量预先计算辅料用量及库存情况;工单生成后,物料需求按产品用量自动汇总,仅供查看。
          </p>
          <ItemList v-if="formData?.id"
                    :work-order-id="formData.id" />
src/views/wls/warehouse/components/area-select.vue
@@ -5,7 +5,10 @@
import { Select, SelectOption, Tooltip } from 'ant-design-vue';
import { getWarehouseAreaSimpleList } from '#/api/mes/wm/warehouse/area';
import {
  createWarehouseArea,
  getWarehouseAreaSimpleList,
} from '#/api/mes/wm/warehouse/area';
defineOptions({ name: 'WmWarehouseAreaSelect', inheritAttrs: false });
@@ -31,24 +34,66 @@
  'update:modelValue': [value: number | undefined];
}>();
const CREATE_VALUE = '__CREATE_AREA__';
const attrs = useAttrs();
const allList = ref<MesWmWarehouseAreaApi.WarehouseArea[]>([]);
const selectedItem = ref<MesWmWarehouseAreaApi.WarehouseArea>();
const searchText = ref('');
const selectValue = computed({
  get: () => props.modelValue,
  set: (val) => emit('update:modelValue', val),
});
/** 选中变化 */
function handleChange(val: any) {
/** 输入内容尚未存在于列表时,允许直接新建 */
const canCreate = computed(() => {
  const keyword = searchText.value.trim();
  if (!keyword || !props.locationId) {
    return false;
  }
  return !allList.value.some((o) => o.name === keyword);
});
/** 选中变化;选中“新增”项时按输入名称直接建档 */
async function handleChange(val: any) {
  if (val === CREATE_VALUE) {
    await handleCreate();
    return;
  }
  const item = allList.value.find((o) => o.id === val);
  selectedItem.value = item;
  emit('change', item);
}
/** 前端过滤(name + code) */
/** 输入名称直接新建库位并选中 */
async function handleCreate() {
  const name = searchText.value.trim();
  if (!name || !props.locationId) {
    return;
  }
  const id = await createWarehouseArea({
    allowBatchMixing: true,
    allowItemMixing: true,
    code: `KW${Date.now()}`,
    frozen: false,
    locationId: props.locationId,
    name,
    status: 0,
  });
  allList.value = await getWarehouseAreaSimpleList(props.locationId);
  const item = allList.value.find((o) => o.id === id);
  selectedItem.value = item;
  searchText.value = '';
  emit('update:modelValue', id);
  emit('change', item);
}
/** 前端过滤(name + code),始终保留“新增”项 */
function filterOption(input: string, option: any) {
  if (option.value === CREATE_VALUE) {
    return true;
  }
  const item = allList.value.find((o) => o.id === option.value);
  if (!item) {
    return false;
@@ -75,6 +120,7 @@
/** 库区变更时清空已选库位并重新加载列表 */
watchEffect(async () => {
  searchText.value = '';
  if (!props.locationId) {
    allList.value = [];
    return;
@@ -113,10 +159,14 @@
      :popup-match-select-width="false"
      show-search
      @change="handleChange"
      @search="searchText = $event"
    >
      <SelectOption v-for="item in allList" :key="item.id" :value="item.id">
        {{ item.name }}
      </SelectOption>
      <SelectOption v-if="canCreate" :value="CREATE_VALUE">
        新增库位“{{ searchText.trim() }}”
      </SelectOption>
    </Select>
  </Tooltip>
</template>
src/views/wls/warehouse/components/location-select.vue
@@ -5,7 +5,10 @@
import { Select, SelectOption, Tooltip } from 'ant-design-vue';
import { getWarehouseLocationSimpleList } from '#/api/mes/wm/warehouse/location';
import {
  createWarehouseLocation,
  getWarehouseLocationSimpleList,
} from '#/api/mes/wm/warehouse/location';
defineOptions({ name: 'WmWarehouseLocationSelect', inheritAttrs: false });
@@ -31,24 +34,63 @@
  'update:modelValue': [value: number | undefined];
}>();
const CREATE_VALUE = '__CREATE_LOCATION__';
const attrs = useAttrs();
const allList = ref<MesWmWarehouseLocationApi.WarehouseLocation[]>([]);
const selectedItem = ref<MesWmWarehouseLocationApi.WarehouseLocation>();
const searchText = ref('');
const selectValue = computed({
  get: () => props.modelValue,
  set: (val) => emit('update:modelValue', val),
});
/** 选中变化 */
function handleChange(val: any) {
/** 输入内容尚未存在于列表时,允许直接新建 */
const canCreate = computed(() => {
  const keyword = searchText.value.trim();
  if (!keyword || !props.warehouseId) {
    return false;
  }
  return !allList.value.some((o) => o.name === keyword);
});
/** 选中变化;选中“新增”项时按输入名称直接建档 */
async function handleChange(val: any) {
  if (val === CREATE_VALUE) {
    await handleCreate();
    return;
  }
  const item = allList.value.find((o) => o.id === val);
  selectedItem.value = item;
  emit('change', item);
}
/** 前端过滤(name + code) */
/** 输入名称直接新建库区并选中 */
async function handleCreate() {
  const name = searchText.value.trim();
  if (!name || !props.warehouseId) {
    return;
  }
  const id = await createWarehouseLocation({
    code: `ZD${Date.now()}`,
    frozen: false,
    name,
    warehouseId: props.warehouseId,
  });
  allList.value = await getWarehouseLocationSimpleList(props.warehouseId);
  const item = allList.value.find((o) => o.id === id);
  selectedItem.value = item;
  searchText.value = '';
  emit('update:modelValue', id);
  emit('change', item);
}
/** 前端过滤(name + code),始终保留“新增”项 */
function filterOption(input: string, option: any) {
  if (option.value === CREATE_VALUE) {
    return true;
  }
  const item = allList.value.find((o) => o.id === option.value);
  if (!item) {
    return false;
@@ -75,6 +117,7 @@
/** 仓库变更时清空已选库区并重新加载列表 */
watchEffect(async () => {
  searchText.value = '';
  if (!props.warehouseId) {
    allList.value = [];
    return;
@@ -112,10 +155,14 @@
      :popup-match-select-width="false"
      show-search
      @change="handleChange"
      @search="searchText = $event"
    >
      <SelectOption v-for="item in allList" :key="item.id" :value="item.id">
        {{ item.name }}
      </SelectOption>
      <SelectOption v-if="canCreate" :value="CREATE_VALUE">
        新增库区“{{ searchText.trim() }}”
      </SelectOption>
    </Select>
  </Tooltip>
</template>
src/views/wls/warehouse/index.vue
@@ -3,7 +3,6 @@
import type { MesWmWarehouseApi } from '#/api/mes/wm/warehouse';
import { ref } from 'vue';
import { useRouter } from 'vue-router';
import { Page, useVbenModal } from '@vben/common-ui';
import { BarcodeBizTypeEnum } from '@vben/constants';
@@ -19,8 +18,6 @@
import Form from './modules/form.vue';
defineOptions({ name: 'WlsWarehouse' });
const router = useRouter();
const [FormModal, formModalApi] = useVbenModal({
  connectedComponent: Form,
@@ -62,14 +59,6 @@
  } finally {
    hideLoading();
  }
}
/** 跳转库区列表 */
function handleOpenLocation(row: MesWmWarehouseApi.Warehouse) {
  router.push({
    path: '/wls/location',
    query: { warehouseId: String(row.id) },
  });
}
/** 查看仓库条码 */
@@ -139,12 +128,6 @@
      <template #actions="{ row }">
        <TableAction
          :actions="[
            {
              label: '库区',
              type: 'link',
              auth: ['mes:wm-warehouse:query'],
              onClick: handleOpenLocation.bind(null, row),
            },
            {
              label: $t('common.edit'),
              type: 'link',