liding
16 小时以前 4bca9dd2a51a3564a59e7cf8e0d36ba54ad140ce
src/views/productionManagement/productionProcess/index.vue
@@ -30,7 +30,9 @@
           class="mb10">
        <el-button type="primary"
                   @click="showNewModal">新增工序</el-button>
        <el-button type="info" plain @click="handleImport">导入</el-button>
        <el-button type="info"
                   plain
                   @click="handleImport">导入</el-button>
        <el-button type="danger"
                   @click="handleDelete"
                   :disabled="selectedRows.length === 0"
@@ -46,6 +48,90 @@
                @pagination="pagination"
                :total="page.total"></PIMTable>
    </div>
    <!-- 工序生产记录列表弹框 -->
    <el-dialog v-model="isShowProcessParamModal"
               title="生产记录"
               width="800px">
      <div style="text-align: right"
           class="mb10">
        <el-button type="primary"
                   @click="showSelectProductParamModal">新增</el-button>
        <el-button type="danger"
                   plain
                   @click="handleDeleteProcessParam"
                   :disabled="processParamSelectedRows.length === 0">批量删除</el-button>
      </div>
      <PIMTable rowKey="id"
                :column="processParamColumns"
                :tableData="processParamTableData"
                :page="processParamPage"
                :isSelection="true"
                @selection-change="handleProcessParamSelectionChange"
                @pagination="processParamPagination"
                :total="processParamPage.total"></PIMTable>
    </el-dialog>
    <!-- 选择生产记录弹框 -->
    <el-dialog v-model="isShowSelectParamModal"
               title="选择生产记录"
               width="800px">
      <PIMTable rowKey="id"
                :column="productParamColumns"
                :tableData="productParamTableData"
                :page="productParamPage"
                :isSelection="true"
                @selection-change="handleProductParamSelectionChange"
                @pagination="productParamPagination"
                :total="productParamPage.total"></PIMTable>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary"
                     @click="handleAddProcessParam">确定</el-button>
          <el-button @click="isShowSelectParamModal = false">取消</el-button>
        </div>
      </template>
    </el-dialog>
    <!-- 查看设备弹框 -->
    <el-dialog v-model="isShowDeviceModal"
               title="设备列表"
               width="900px">
      <div style="text-align: right"
           class="mb10">
        <el-button type="primary"
                   @click="showAddDeviceModal">添加设备</el-button>
      </div>
      <PIMTable rowKey="id"
                :column="deviceColumns"
                :tableData="deviceTableData"
                :page="devicePage"
                :isSelection="false"
                @pagination="devicePagination"
                :total="devicePage.total"></PIMTable>
    </el-dialog>
    <!-- 添加设备弹框 -->
    <el-dialog v-model="isShowSelectDeviceModal"
               title="选择设备"
               width="900px">
      <PIMTable rowKey="id"
                :column="selectDeviceColumns"
                :tableData="selectDeviceTableData"
                :page="selectDevicePage"
                :isSelection="true"
                @selection-change="handleSelectDeviceChange"
                @pagination="selectDevicePagination"
                :total="selectDevicePage.total"></PIMTable>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary"
                     @click="handleBindDevices">确定</el-button>
          <el-button @click="isShowSelectDeviceModal = false">取消</el-button>
        </div>
      </template>
    </el-dialog>
    <new-process v-if="isShowNewModal"
                 v-model:visible="isShowNewModal"
                 @completed="getList" />
@@ -53,19 +139,17 @@
                  v-model:visible="isShowEditModal"
                  :record="record"
                  @completed="getList" />
    <ImportDialog
      ref="importDialogRef"
      v-model="importDialogVisible"
      title="导入工序"
      :action="importAction"
      :headers="importHeaders"
      :auto-upload="false"
      :on-success="handleImportSuccess"
      :on-error="handleImportError"
      @confirm="handleImportConfirm"
      @download-template="handleDownloadTemplate"
      @close="handleImportClose"
    />
    <ImportDialog ref="importDialogRef"
                  v-model="importDialogVisible"
                  title="导入工序"
                  :action="importAction"
                  :headers="importHeaders"
                  :auto-upload="false"
                  :on-success="handleImportSuccess"
                  :on-error="handleImportError"
                  @confirm="handleImportConfirm"
                  @download-template="handleDownloadTemplate"
                  @close="handleImportClose" />
  </div>
</template>
@@ -74,7 +158,22 @@
  import NewProcess from "@/views/productionManagement/productionProcess/New.vue";
  import EditProcess from "@/views/productionManagement/productionProcess/Edit.vue";
  import ImportDialog from "@/components/Dialog/ImportDialog.vue";
  import { listPage, del, importData, downloadTemplate } from "@/api/productionManagement/productionProcess.js";
  import {
    listPage,
    del,
    importData,
    downloadTemplate,
    getBindDevices,
    bindDevices,
    unbindDevice,
  } from "@/api/productionManagement/productionProcess.js";
  import {
    listPage as listProcessParamPage,
    del as delProcessParam,
    addProductProcessParameter,
  } from "@/api/productionManagement/productProcessParameter.js";
  import { listPage as listProductParamPage } from "@/api/productionManagement/productionRecords.js";
  import { getLedgerPage } from "@/api/equipmentManagement/ledger.js";
  import { getToken } from "@/utils/auth";
  const data = reactive({
@@ -93,16 +192,26 @@
      label: "工序名称",
      prop: "name",
    },
    {
      label: "工序类型",
      prop: "typeText",
    },
    {
      label: "工资定额",
      prop: "salaryQuota",
    },
    {
      label: "是否质检",
      prop: "isQuality",
      formatData: (params) => {
        return params ? "是" : "否";
      },
    },
    {
      label: "备注",
      prop: "remark",
    },
     {
    {
      label: "更新时间",
      prop: "updateTime",
    },
@@ -111,8 +220,22 @@
      label: "操作",
      align: "center",
      fixed: "right",
      width: 280,
      width: 350,
      operation: [
        {
          name: "生产参数",
          type: "text",
          clickFun: row => {
            showProcessParamModal(row);
          },
        },
        {
          name: "查看设备",
          type: "text",
          clickFun: row => {
            showDeviceModal(row);
          },
        },
        {
          name: "编辑",
          type: "text",
@@ -123,12 +246,95 @@
      ],
    },
  ]);
  // 工序已绑定的生产记录列表列配置
  const processParamColumns = ref([
    { label: "参数编码", prop: "code" },
    { label: "参数项", prop: "parameterItem" },
    {
      label: "参数类型",
      prop: "type",
      formatData: val => {
        const dictList = (proxy.useDict && proxy.useDict("parameter_tyep")?.parameter_tyep) || [];
        const list = dictList.value || dictList;
        const hit = (list || []).find(d => d.value === val);
        return hit ? hit.label : val;
      },
    },
    { label: "单位", prop: "unit" },
    { label: "参数格式", prop: "parameterFormat" },
    {
      label: "是否必填",
      prop: "isRequired",
      formatData: v => (v === "1" || v === 1 ? "是" : "否"),
    },
  ]);
  // 可选择的生产记录列表列配置
  const productParamColumns = ref([
    { label: "参数编码", prop: "code" },
    { label: "参数项", prop: "parameterItem" },
    {
      label: "参数类型",
      prop: "type",
      formatData: val => {
        const dictList = (proxy.useDict && proxy.useDict("parameter_tyep")?.parameter_tyep) || [];
        const list = dictList.value || dictList;
        const hit = (list || []).find(d => d.value === val);
        return hit ? hit.label : val;
      },
    },
    { label: "单位", prop: "unit" },
    { label: "参数格式", prop: "parameterFormat" },
    {
      label: "是否必填",
      prop: "isRequired",
      formatData: v => (v === "1" || v === 1 ? "是" : "否"),
    },
  ]);
  // 设备列表列配置
  const deviceColumns = ref([
    { label: "设备编号", prop: "deviceCode" },
    { label: "设备名称", prop: "deviceName" },
    { label: "规格型号", prop: "deviceModel" },
    { label: "设备品牌", prop: "deviceBrand" },
    { label: "设备类型", prop: "type" },
    { label: "供应商", prop: "supplierName" },
    {
      dataType: "action",
      label: "操作",
      align: "center",
      width: 100,
      operation: [
        {
          name: "删除",
          type: "text",
          typeAttrs: { danger: true },
          clickFun: row => {
            handleUnbindDevice(row);
          },
        },
      ],
    },
  ]);
  // 可选设备列表列配置
  const selectDeviceColumns = ref([
    { label: "设备编号", prop: "deviceCode" },
    { label: "设备名称", prop: "deviceName" },
    { label: "规格型号", prop: "deviceModel" },
    { label: "设备品牌", prop: "deviceBrand" },
    { label: "设备类型", prop: "type" },
    { label: "供应商", prop: "supplierName" },
  ]);
  const tableData = ref([]);
  const selectedRows = ref([]);
  const tableLoading = ref(false);
  const isShowNewModal = ref(false);
  const isShowEditModal = ref(false);
  const isShowProcessParamModal = ref(false);
  const isShowSelectParamModal = ref(false);
  const record = ref({});
  const currentProcess = ref(null);
  const importDialogVisible = ref(false);
  const importDialogRef = ref(null);
  const page = reactive({
@@ -136,10 +342,42 @@
    size: 100,
    total: 0,
  });
  const processParamPage = reactive({
    current: 1,
    size: 100,
    total: 0,
  });
  const productParamPage = reactive({
    current: 1,
    size: 100,
    total: 0,
  });
  const processParamTableData = ref([]);
  const productParamTableData = ref([]);
  const processParamSelectedRows = ref([]);
  const productParamSelectedRows = ref([]);
  // 设备相关变量
  const isShowDeviceModal = ref(false);
  const isShowSelectDeviceModal = ref(false);
  const deviceTableData = ref([]);
  const selectDeviceTableData = ref([]);
  const selectedDeviceRows = ref([]);
  const devicePage = reactive({
    current: 1,
    size: 100,
    total: 0,
  });
  const selectDevicePage = reactive({
    current: 1,
    size: 100,
    total: 0,
  });
  const { proxy } = getCurrentInstance();
  // 导入相关配置
  const importAction = import.meta.env.VITE_APP_BASE_API + "/productProcess/importData";
  const importAction =
    import.meta.env.VITE_APP_BASE_API + "/productProcess/importData";
  const importHeaders = { Authorization: "Bearer " + getToken() };
  // 查询列表
@@ -154,6 +392,16 @@
    page.size = obj.limit;
    getList();
  };
  const processParamPagination = obj => {
    processParamPage.current = obj.page;
    processParamPage.size = obj.limit;
    getProcessParamList();
  };
  const productParamPagination = obj => {
    productParamPage.current = obj.page;
    productParamPage.size = obj.limit;
    getProductParamList();
  };
  const getList = () => {
    tableLoading.value = true;
    const params = { ...searchForm.value, ...page };
@@ -163,6 +411,7 @@
        tableLoading.value = false;
        tableData.value = res.data.records.map(item => ({
          ...item,
          typeText: item.type !== undefined && item.type !== null ? (item.type === 0 ? "计时" : "计件") : "",
        }));
        page.total = res.data.total;
      })
@@ -175,6 +424,14 @@
    selectedRows.value = selection;
  };
  const handleProcessParamSelectionChange = selection => {
    processParamSelectedRows.value = selection;
  };
  const handleProductParamSelectionChange = selection => {
    productParamSelectedRows.value = selection;
  };
  // 打开新增弹框
  const showNewModal = () => {
    isShowNewModal.value = true;
@@ -183,6 +440,189 @@
  const showEditModal = row => {
    isShowEditModal.value = true;
    record.value = row;
  };
  // 查看当前工序的生产记录
  const showProcessParamModal = row => {
    currentProcess.value = row;
    isShowProcessParamModal.value = true;
    processParamPage.current = 1;
    getProcessParamList();
  };
  const getProcessParamList = () => {
    if (!currentProcess.value) return;
    const params = {
      processId: currentProcess.value.id,
      ...processParamPage,
    };
    listProcessParamPage(params).then(res => {
      processParamTableData.value = res.data.records || [];
      processParamPage.total = res.data.total || 0;
    });
  };
  // 删除当前工序绑定的生产记录
  const handleDeleteProcessParam = () => {
    const ids = processParamSelectedRows.value.map(item => item.id);
    if (!ids.length) {
      proxy.$modal.msgWarning("请选择要删除的记录");
      return;
    }
    proxy.$modal
        .confirm("是否确认删除选中的生产记录?")
        .then(() => delProcessParam(ids))
        .then(() => {
          proxy.$modal.msgSuccess("删除成功");
          getProcessParamList();
        })
        .catch(() => {});
  };
  // 打开选择生产记录弹框
  const showSelectProductParamModal = () => {
    isShowSelectParamModal.value = true;
    productParamPage.current = 1;
    getProductParamList();
  };
  const getProductParamList = () => {
    const params = {
      ...productParamPage,
    };
    listProductParamPage(params).then(res => {
      const records = res.data.records || [];
      // 已绑定到当前工序的生产记录,不允许再次选择 -> 根据参数编码打上 disabled 标记
      const boundCodeSet = new Set(
          (processParamTableData.value || [])
              .map(item => item.code ?? item.parameterCode)
              .filter(code => !!code)
      );
      productParamTableData.value = records.map(item => ({
        ...item,
        disabled: item.code ? boundCodeSet.has(item.code) : false,
      }));
      productParamPage.total = res.data.total || 0;
    });
  };
  // 确认给当前工序新增生产记录
  const handleAddProcessParam = () => {
    if (!currentProcess.value) return;
    const selectedList = productParamSelectedRows.value || [];
    if (!selectedList.length) {
      proxy.$modal.msgWarning("请选择要绑定的生产记录");
      return;
    }
    // processId 放在路径里,body 直接传选中的生产记录数组
    addProductProcessParameter(currentProcess.value.id, selectedList)
        .then(() => {
          proxy.$modal.msgSuccess("新增成功");
          isShowSelectParamModal.value = false;
          getProcessParamList();
        })
        .catch(() => {});
  };
  // 查看设备弹框
  const showDeviceModal = row => {
    currentProcess.value = row;
    isShowDeviceModal.value = true;
    devicePage.current = 1;
    getDeviceList();
  };
  // 获取已绑定的设备列表
  const getDeviceList = () => {
    if (!currentProcess.value) return;
    getBindDevices(currentProcess.value.id)
      .then(res => {
        deviceTableData.value = res.data || [];
        devicePage.total = res.data?.length || 0;
      })
      .catch(() => {});
  };
  // 设备列表分页
  const devicePagination = obj => {
    devicePage.current = obj.page;
    devicePage.size = obj.limit;
    getDeviceList();
  };
  // 解绑设备
  const handleUnbindDevice = row => {
    if (!currentProcess.value) return;
    proxy.$modal.confirm("是否确认解绑该设备?")
      .then(() => {
        return unbindDevice(currentProcess.value.id, row.id);
      })
      .then(() => {
        proxy.$modal.msgSuccess("解绑成功");
        getDeviceList();
      })
      .catch(() => {});
  };
  // 打开添加设备弹框
  const showAddDeviceModal = () => {
    isShowSelectDeviceModal.value = true;
    selectDevicePage.current = 1;
    selectedDeviceRows.value = [];
    getSelectDeviceList();
  };
  // 获取可选设备列表
  const getSelectDeviceList = () => {
    if (!currentProcess.value) return;
    // 先获取已绑定的设备ID
    getBindDevices(currentProcess.value.id)
      .then(res => {
        const boundDeviceIds = new Set(
          (res.data || []).map(item => item.id).filter(id => !!id)
        );
        // 获取设备台账分页列表
        return getLedgerPage(selectDevicePage).then(deviceRes => {
          const allDevices = deviceRes.data?.records || [];
          // 过滤掉已绑定的设备,并标记为disabled
          selectDeviceTableData.value = allDevices.map(item => ({
            ...item,
            disabled: boundDeviceIds.has(item.id),
          }));
          selectDevicePage.total = deviceRes.data?.total || 0;
        });
      })
      .catch(() => {});
  };
  // 选择设备变化
  const handleSelectDeviceChange = selection => {
    selectedDeviceRows.value = selection;
  };
  // 选择设备分页
  const selectDevicePagination = obj => {
    selectDevicePage.current = obj.page;
    selectDevicePage.size = obj.limit;
    getSelectDeviceList();
  };
  // 绑定设备
  const handleBindDevices = () => {
    if (!currentProcess.value) return;
    const selectedList = selectedDeviceRows.value || [];
    if (!selectedList.length) {
      proxy.$modal.msgWarning("请选择要绑定的设备");
      return;
    }
    const deviceIds = selectedList.map(item => item.id);
    bindDevices(currentProcess.value.id, deviceIds)
      .then(() => {
        proxy.$modal.msgSuccess("绑定成功");
        isShowSelectDeviceModal.value = false;
        getDeviceList();
      })
      .catch(() => {});
  };
  // 删除
@@ -235,7 +675,7 @@
  };
  // 导入成功
  const handleImportSuccess = (response) => {
  const handleImportSuccess = response => {
    if (response.code === 200) {
      proxy.$modal.msgSuccess("导入成功");
      importDialogVisible.value = false;
@@ -249,7 +689,7 @@
  };
  // 导入失败
  const handleImportError = (error) => {
  const handleImportError = error => {
    proxy.$modal.msgError("导入失败:" + (error.message || "未知错误"));
  };