已添加1个文件
已修改21个文件
1057 ■■■■■ 文件已修改
src/api/productionManagement/productionOrder.js 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicData/product/index.vue 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/ledger/Form.vue 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/ledger/index.vue 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/dispatchLog/Record.vue 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/receiptManagement/Record.vue 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/stockManagement/Qualified.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/stockManagement/Unqualified.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/stockReport/index.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/processRoute/index.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productStructure/index.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productionOrder/index.vue 676 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productionProcess/index.vue 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productionReporting/Input.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productionReporting/index.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/workOrder/components/ProductionRecordForm.vue 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/workOrder/index.vue 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/finalInspection/index.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/nonconformingManagement/index.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/processInspection/index.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/rawMaterialInspection/index.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/salesLedger/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/productionManagement/productionOrder.js
@@ -129,4 +129,11 @@
    method: "post",
    data: data,
  });
}
export function finishOrder(id) {
  return request({
    url: `/productOrder/${id}`,
    method: "patch",
  });
}
src/views/basicData/product/index.vue
@@ -162,6 +162,43 @@
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="有效期(年):" prop="validityPeriod">
              <el-input-number
                  :step="0.01"
                  :min="0"
                  style="width: 100%"
                  v-model="modelForm.validityPeriod"
                  placeholder="请输入有效期"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="备案凭证号:" prop="filingCertificateNo">
              <el-input
                  v-model="modelForm.filingCertificateNo"
                  placeholder="请输入备案凭证号"
                  clearable
                  @keydown.enter.prevent
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="UID码:" prop="uidNo">
              <el-input
                  v-model="modelForm.uidNo"
                  placeholder="请输入UID码"
                  clearable
                  @keydown.enter.prevent
              />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
@@ -210,6 +247,18 @@
    prop: "unit",
  },
  {
    label: "有效期(年)",
    prop: "validityPeriod",
  },
  {
    label: "备案凭证号",
    prop: "filingCertificateNo",
  },
  {
    label: "UID码",
    prop: "uidNo",
  },
  {
    dataType: "action",
    label: "操作",
    align: "center",
@@ -246,6 +295,9 @@
  modelForm: {
    model: "",
    unit: "",
    validityPeriod: undefined,
    filingCertificateNo: undefined,
    uidNo: undefined,
  },
  modelRules: {
    model: [{ required: true, message: "请输入", trigger: "blur" }],
src/views/equipmentManagement/ledger/Form.vue
@@ -2,6 +2,11 @@
  <el-form :model="form" label-width="120px" :rules="formRules" ref="formRef">
    <el-row :gutter="20">
      <el-col :span="12">
        <el-form-item label="设备编号" prop="deviceCode">
          <el-input v-model="form.deviceCode" placeholder="请输入设备编号" />
        </el-form-item>
      </el-col>
      <el-col :span="12">
        <el-form-item label="设备名称" prop="deviceName">
          <el-input v-model="form.deviceName" placeholder="请输入设备名称" />
        </el-form-item>
@@ -40,6 +45,14 @@
      <el-col :span="12">
        <el-form-item label="供应商" prop="supplierName">
          <el-input v-model="form.supplierName" placeholder="请输入供应商" />
        </el-form-item>
      </el-col>
      <el-col :span="12">
        <el-form-item label="转数(转/min)" prop="rpm">
          <el-input-number :min="0" style="width: 100%"
                           v-model="form.rpm"
                           placeholder="请输入转数"
          />
        </el-form-item>
      </el-col>
      <el-col :span="12">
@@ -147,8 +160,8 @@
          />
        </el-form-item>
      </el-col>
            <el-col :span="12">
                <el-form-item label="预计运行时间" prop="planRuntimeTime">
      <el-col :span="12">
        <el-form-item label="预计运行时间" prop="planRuntimeTime">
                    <el-date-picker
                        style="width: 100%"
                        v-model="form.planRuntimeTime"
@@ -190,6 +203,7 @@
  '其他设备'
]);
const formRules = {
    deviceCode: [{ required: true, trigger: "blur", message: "请输入设备编号" }],
    deviceName: [{ required: true, trigger: "blur", message: "请输入" }],
    deviceModel: [{ required: true, trigger: "blur", message: "请输入" }],
    type: [{ required: true, trigger: "change", message: "请选择或输入设备类型" }],
@@ -214,6 +228,7 @@
}
const { form, resetForm } = useFormData({
  deviceCode: undefined, // è®¾å¤‡ç¼–号
  deviceName: undefined, // è®¾å¤‡åç§°
  deviceModel: undefined, // è§„格型号
  deviceBrand: undefined, // è®¾å¤‡å“ç‰Œ
@@ -239,6 +254,7 @@
    }
  const { code, data } = await getLedgerById(id);
  if (code == 200) {
    form.deviceCode = data.deviceCode;
    form.deviceName = data.deviceName;
    form.deviceModel = data.deviceModel;
    form.deviceBrand = data.deviceBrand;
src/views/equipmentManagement/ledger/index.vue
@@ -122,6 +122,10 @@
  },
  [
    {
      label: "设备编号",
      prop: "deviceCode",
    },
    {
      label: "设备名称",
      prop: "deviceName",
    },
@@ -142,6 +146,10 @@
      prop: "supplierName",
    },
    {
      label: "转数(转/min)",
      prop: "rpm",
    },
    {
      label: "存放位置",
      prop: "storageLocation",
    },
src/views/inventoryManagement/dispatchLog/Record.vue
@@ -66,6 +66,9 @@
                    prop="model"
                    show-overflow-tooltip
                />
        <el-table-column label="UID码"
                         prop="uidNO"
                         show-overflow-tooltip/>
                <el-table-column
                    label="单位"
                    prop="unit"
src/views/inventoryManagement/receiptManagement/Record.vue
@@ -67,6 +67,9 @@
        <el-table-column label="规格型号"
                         prop="model"
                         show-overflow-tooltip/>
        <el-table-column label="UID码"
                         prop="uidNO"
                         show-overflow-tooltip/>
        <el-table-column label="单位"
                         prop="unit"
                         show-overflow-tooltip/>
src/views/inventoryManagement/stockManagement/Qualified.vue
@@ -25,6 +25,7 @@
        <el-table-column align="center" label="序号" type="index" width="60" />
        <el-table-column label="产品大类" prop="productName" show-overflow-tooltip />
        <el-table-column label="规格型号" prop="model" show-overflow-tooltip />
        <el-table-column label="UID码" prop="uidNo" show-overflow-tooltip />
        <el-table-column label="单位" prop="unit" show-overflow-tooltip />
        <el-table-column label="库存数量" prop="qualitity" show-overflow-tooltip />
        <el-table-column label="冻结数量" prop="lockedQuantity" show-overflow-tooltip />
src/views/inventoryManagement/stockManagement/Unqualified.vue
@@ -22,6 +22,7 @@
        <el-table-column align="center" label="序号" type="index" width="60" />
        <el-table-column label="产品大类" prop="productName" show-overflow-tooltip />
        <el-table-column label="规格型号" prop="model" show-overflow-tooltip />
        <el-table-column label="UID码" prop="uidNo" show-overflow-tooltip />
        <el-table-column label="单位" prop="unit" show-overflow-tooltip />
        <el-table-column label="库存数量" prop="qualitity" show-overflow-tooltip />
        <el-table-column label="冻结数量" prop="lockedQuantity" show-overflow-tooltip />
src/views/inventoryManagement/stockReport/index.vue
@@ -186,6 +186,11 @@
             show-overflow-tooltip
           />
           <el-table-column
               label="UID码"
               prop="uid码"
               show-overflow-tooltip
           />
           <el-table-column
             label="单位"
             prop="unit"
             show-overflow-tooltip
src/views/productionManagement/processRoute/index.vue
@@ -80,6 +80,10 @@
    prop: "model",
  },
  {
    label: "UID码",
    prop: "uid码",
  },
  {
    label: "BOM编号",
    prop: "bomNo",
  },
src/views/productionManagement/productStructure/index.vue
@@ -88,6 +88,11 @@
    width: 100
  },
  {
    label: "UID码",
    prop: "uidNo",
    width: 100
  },
  {
    label: "备注",
    prop: "remark",
    minWidth: 160
src/views/productionManagement/productionOrder/index.vue
@@ -9,7 +9,7 @@
                    clearable
                    prefix-icon="Search"
                    style="width: 160px;"
                    @change="handleQuery" />
                    @change="handleQuery"/>
        </el-form-item>
        <el-form-item label="合同号:">
          <el-input v-model="searchForm.salesContractNo"
@@ -17,7 +17,7 @@
                    clearable
                    prefix-icon="Search"
                    style="width: 160px;"
                    @change="handleQuery" />
                    @change="handleQuery"/>
        </el-form-item>
        <el-form-item label="产品名称:">
          <el-input v-model="searchForm.productCategory"
@@ -25,7 +25,7 @@
                    clearable
                    prefix-icon="Search"
                    style="width: 160px;"
                    @change="handleQuery" />
                    @change="handleQuery"/>
        </el-form-item>
        <el-form-item label="规格:">
          <el-input v-model="searchForm.specificationModel"
@@ -33,11 +33,12 @@
                    clearable
                    prefix-icon="Search"
                    style="width: 160px;"
                    @change="handleQuery" />
                    @change="handleQuery"/>
        </el-form-item>
        <el-form-item>
          <el-button type="primary"
                     @click="handleQuery">搜索</el-button>
                     @click="handleQuery">搜索
          </el-button>
        </el-form-item>
      </el-form>
      <div>
@@ -58,9 +59,9 @@
                @pagination="pagination">
        <template #completionStatus="{ row }">
          <el-progress
            :percentage="toProgressPercentage(row?.completionStatus)"
            :color="progressColor(toProgressPercentage(row?.completionStatus))"
            :status="toProgressPercentage(row?.completionStatus) >= 100 ? 'success' : ''"
              :percentage="toProgressPercentage(row?.completionStatus)"
              :color="progressColor(toProgressPercentage(row?.completionStatus))"
              :status="toProgressPercentage(row?.completionStatus) >= 100 ? 'success' : ''"
          />
        </template>
      </PIMTable>
@@ -77,7 +78,7 @@
            <el-option v-for="item in routeOptions"
                       :key="item.id"
                       :label="`${item.processRouteCode || ''}`"
                       :value="item.id" />
                       :value="item.id"/>
          </el-select>
        </el-form-item>
      </el-form>
@@ -92,264 +93,278 @@
    </el-dialog>
    <new-product-order v-if="isShowNewModal"
                         v-model:visible="isShowNewModal"
                         @completed="handleQuery" />
                       v-model:visible="isShowNewModal"
                       @completed="handleQuery"/>
  </div>
</template>
<script setup>
  import { onMounted, ref } from "vue";
  import { ElMessageBox } from "element-plus";
  import dayjs from "dayjs";
  import { useRouter } from "vue-router";
  import {
    productOrderListPage,
    listProcessRoute,
    bindingRoute,
    listProcessBom, delProductOrder,
  } from "@/api/productionManagement/productionOrder.js";
  import { listMain as getOrderProcessRouteMain } from "@/api/productionManagement/productProcessRoute.js";
  import {fileDel} from "@/api/financialManagement/revenueManagement.js";
  import PIMTable from "@/components/PIMTable/PIMTable.vue";
  const NewProductOrder = defineAsyncComponent(() => import("@/views/productionManagement/productionOrder/New.vue"));
import {onMounted, ref} from "vue";
import {ElMessageBox} from "element-plus";
import dayjs from "dayjs";
import {useRouter} from "vue-router";
import {
  productOrderListPage,
  listProcessRoute,
  bindingRoute,
  delProductOrder, finishOrder,
} from "@/api/productionManagement/productionOrder.js";
import {listMain as getOrderProcessRouteMain} from "@/api/productionManagement/productProcessRoute.js";
import {fileDel} from "@/api/financialManagement/revenueManagement.js";
import PIMTable from "@/components/PIMTable/PIMTable.vue";
  const { proxy } = getCurrentInstance();
const NewProductOrder = defineAsyncComponent(() => import("@/views/productionManagement/productionOrder/New.vue"));
  const router = useRouter();
  const isShowNewModal = ref(false);
const {proxy} = getCurrentInstance();
  const tableColumn = ref([
    {
      label: "生产订单号",
      prop: "npsNo",
      width: '120px',
    },
    {
      label: "产品名称",
      prop: "productCategory",
      width: '120px',
    },
    {
      label: "规格",
      prop: "specificationModel",
      width: '120px',
    },
    {
      label: "工艺路线编号",
      prop: "processRouteCode",
      width: '200px',
    },
    {
      label: "预计生产数量",
      prop: "quantity",
      width: '140px',
    },
    {
      label: "完成数量",
      prop: "completeQuantity",
    },
    {
      dataType: "slot",
      label: "完成进度",
      prop: "completionStatus",
      slot: "completionStatus",
      width: 180,
    },
    {
      label: "开始日期",
      prop: "startTime",
      formatData: val => (val ? dayjs(val).format("YYYY-MM-DD") : ""),
      width: 120,
    },
    {
      label: "结束日期",
      prop: "endTime",
      formatData: val => (val ? dayjs(val).format("YYYY-MM-DD") : ""),
      width: 120,
    },
    {
      label: "交付日期",
      prop: "deliveryDate",
      formatData: val => (val ? dayjs(val).format("YYYY-MM-DD") : ""),
      width: 120,
    },
    {
      label: "预计日程(天)",
      prop: "expectedSchedule",
      width: 120,
    },
    {
      label: "制造班组",
      prop: "manufacturingTeam",
      width: 120,
    },
    {
      dataType: "action",
      label: "操作",
      align: "center",
      fixed: "right",
      width: 200,
      operation: [
        {
          name: "工艺路线",
          type: "text",
          clickFun: row => {
            showRouteItemModal(row);
          },
const router = useRouter();
const isShowNewModal = ref(false);
const tableColumn = ref([
  {
    label: "生产订单号",
    prop: "npsNo",
    width: '120px',
  },
  {
    label: "产品名称",
    prop: "productCategory",
    width: '120px',
  },
  {
    label: "规格",
    prop: "specificationModel",
    width: '120px',
  },
  {
    label: "UID码",
    prop: "uidNo",
    width: '120px',
  },
  {
    label: "工艺路线编号",
    prop: "processRouteCode",
    width: '200px',
  },
  {
    label: "预计生产数量",
    prop: "quantity",
    width: '140px',
  },
  {
    label: "完成数量",
    prop: "completeQuantity",
  },
  {
    dataType: "slot",
    label: "完成进度",
    prop: "completionStatus",
    slot: "completionStatus",
    width: 180,
  },
  {
    label: "开始日期",
    prop: "startTime",
    formatData: val => (val ? dayjs(val).format("YYYY-MM-DD") : ""),
    width: 120,
  },
  {
    label: "结束日期",
    prop: "endTime",
    formatData: val => (val ? dayjs(val).format("YYYY-MM-DD") : ""),
    width: 120,
  },
  {
    label: "交付日期",
    prop: "deliveryDate",
    formatData: val => (val ? dayjs(val).format("YYYY-MM-DD") : ""),
    width: 120,
  },
  {
    label: "预计日程(天)",
    prop: "expectedSchedule",
    width: 120,
  },
  {
    label: "制造班组",
    prop: "manufacturingTeam",
    width: 120,
  },
  {
    dataType: "action",
    label: "操作",
    align: "center",
    fixed: "right",
    width: 200,
    operation: [
      {
        name: "工艺路线",
        type: "text",
        clickFun: row => {
          showRouteItemModal(row);
        },
        {
          name: "绑定工艺路线",
          type: "text",
          showHide: row => !row.processRouteCode,
          clickFun: row => {
            openBindRouteDialog(row);
          },
      },
      {
        name: "绑定工艺路线",
        type: "text",
        showHide: row => !row.processRouteCode,
        clickFun: row => {
          openBindRouteDialog(row);
        },
        {
          name: "产品结构",
          type: "text",
          clickFun: row => {
            showProductStructure(row);
          },
      },
      {
        name: "产品结构",
        type: "text",
        clickFun: row => {
          showProductStructure(row);
        },
      ],
    },
  ]);
  const tableData = ref([]);
  const tableLoading = ref(false);
  const page = reactive({
    current: 1,
    size: 100,
    total: 0,
  });
  const selectedRows = ref([]);
      },
      {
        name: "结束生产",
        type: "text",
        showHide: row => !row.isEnd,
        clickFun: row => {
          handleFinishOrder(row);
        },
      },
    ],
  },
]);
const tableData = ref([]);
const tableLoading = ref(false);
const page = reactive({
  current: 1,
  size: 100,
  total: 0,
});
const selectedRows = ref([]);
  const data = reactive({
    searchForm: {
      customerName: "",
      salesContractNo: "",
      projectName: "",
      productCategory: "",
      specificationModel: "",
    },
  });
  const { searchForm } = toRefs(data);
const data = reactive({
  searchForm: {
    customerName: "",
    salesContractNo: "",
    projectName: "",
    productCategory: "",
    specificationModel: "",
  },
});
const {searchForm} = toRefs(data);
  const toProgressPercentage = val => {
    const n = Number(val);
    if (!Number.isFinite(n)) return 0;
    if (n <= 0) return 0;
    if (n >= 100) return 100;
    return Math.round(n);
  };
const toProgressPercentage = val => {
  const n = Number(val);
  if (!Number.isFinite(n)) return 0;
  if (n <= 0) return 0;
  if (n >= 100) return 100;
  return Math.round(n);
};
  // 30/50/80/100 åˆ†æ®µé¢œè‰²ï¼šçº¢/橙/蓝/绿
  const progressColor = percentage => {
    const p = toProgressPercentage(percentage);
    if (p < 30) return "#f56c6c";
    if (p < 50) return "#e6a23c";
    if (p < 80) return "#409eff";
    return "#67c23a";
  };
// 30/50/80/100 åˆ†æ®µé¢œè‰²ï¼šçº¢/橙/蓝/绿
const progressColor = percentage => {
  const p = toProgressPercentage(percentage);
  if (p < 30) return "#f56c6c";
  if (p < 50) return "#e6a23c";
  if (p < 80) return "#409eff";
  return "#67c23a";
};
  // æ·»åŠ è¡¨è¡Œç±»åæ–¹æ³•
  const tableRowClassName = ({ row }) => {
    if (!row.deliveryDate) return '';
    if (row.isFh) return '';
// æ·»åŠ è¡¨è¡Œç±»åæ–¹æ³•
const tableRowClassName = ({row}) => {
  if (!row.deliveryDate) return '';
  if (row.isFh) return '';
    const diff = row.deliveryDaysDiff;
    if (diff === 15) {
      return 'yellow';
    } else if (diff === 10) {
      return 'pink';
    } else if (diff === 2) {
      return 'purple';
    } else if (diff < 2) {
      return 'red';
    }
  };
  const diff = row.deliveryDaysDiff;
  if (diff === 15) {
    return 'yellow';
  } else if (diff === 10) {
    return 'pink';
  } else if (diff === 2) {
    return 'purple';
  } else if (diff < 2) {
    return 'red';
  }
};
  // ç»‘定工艺路线弹框
  const bindRouteDialogVisible = ref(false);
  const bindRouteLoading = ref(false);
  const bindRouteSaving = ref(false);
  const routeOptions = ref([]);
  const bindForm = reactive({
    orderId: null,
    routeId: null,
  });
// ç»‘定工艺路线弹框
const bindRouteDialogVisible = ref(false);
const bindRouteLoading = ref(false);
const bindRouteSaving = ref(false);
const routeOptions = ref([]);
const bindForm = reactive({
  orderId: null,
  routeId: null,
});
  const openBindRouteDialog = async row => {
    bindForm.orderId = row.id;
    bindForm.routeId = null;
    bindRouteDialogVisible.value = true;
    routeOptions.value = [];
    if (!row.productModelId) {
      proxy.$modal.msgWarning("当前订单缺少产品型号,无法查询工艺路线");
      bindRouteDialogVisible.value = false;
      return;
    }
    bindRouteLoading.value = true;
    try {
      const res = await listProcessRoute({ productModelId: row.productModelId });
      routeOptions.value = res.data || [];
    } catch (e) {
      console.error("获取工艺路线列表失败:", e);
      proxy.$modal.msgError("获取工艺路线列表失败");
    } finally {
      bindRouteLoading.value = false;
    }
  };
const openBindRouteDialog = async row => {
  bindForm.orderId = row.id;
  bindForm.routeId = null;
  bindRouteDialogVisible.value = true;
  routeOptions.value = [];
  if (!row.productModelId) {
    proxy.$modal.msgWarning("当前订单缺少产品型号,无法查询工艺路线");
    bindRouteDialogVisible.value = false;
    return;
  }
  bindRouteLoading.value = true;
  try {
    const res = await listProcessRoute({productModelId: row.productModelId});
    routeOptions.value = res.data || [];
  } catch (e) {
    console.error("获取工艺路线列表失败:", e);
    proxy.$modal.msgError("获取工艺路线列表失败");
  } finally {
    bindRouteLoading.value = false;
  }
};
  const handleBindRouteConfirm = async () => {
    if (!bindForm.routeId) {
      proxy.$modal.msgWarning("请选择工艺路线");
      return;
    }
    bindRouteSaving.value = true;
    try {
      await bindingRoute({
        id: bindForm.orderId,
        routeId: bindForm.routeId,
      });
      proxy.$modal.msgSuccess("绑定成功");
      bindRouteDialogVisible.value = false;
      getList();
    } catch (e) {
      console.error("绑定工艺路线失败:", e);
      proxy.$modal.msgError("绑定工艺路线失败");
    } finally {
      bindRouteSaving.value = false;
    }
  };
  // æŸ¥è¯¢åˆ—表
  /** æœç´¢æŒ‰é’®æ“ä½œ */
  const handleQuery = () => {
    page.current = 1;
const handleBindRouteConfirm = async () => {
  if (!bindForm.routeId) {
    proxy.$modal.msgWarning("请选择工艺路线");
    return;
  }
  bindRouteSaving.value = true;
  try {
    await bindingRoute({
      id: bindForm.orderId,
      routeId: bindForm.routeId,
    });
    proxy.$modal.msgSuccess("绑定成功");
    bindRouteDialogVisible.value = false;
    getList();
  };
  const pagination = obj => {
    page.current = obj.page;
    page.size = obj.limit;
    getList();
  };
  const changeDaterange = value => {
    if (value) {
      searchForm.value.entryDateStart = value[0];
      searchForm.value.entryDateEnd = value[1];
    } else {
      searchForm.value.entryDateStart = undefined;
      searchForm.value.entryDateEnd = undefined;
    }
    handleQuery();
  };
  const getList = () => {
    tableLoading.value = true;
    // æž„造一个新的对象,不包含entryDate字段
    const params = { ...searchForm.value, ...page };
    params.entryDate = undefined;
    productOrderListPage(params)
  } catch (e) {
    console.error("绑定工艺路线失败:", e);
    proxy.$modal.msgError("绑定工艺路线失败");
  } finally {
    bindRouteSaving.value = false;
  }
};
// æŸ¥è¯¢åˆ—表
/** æœç´¢æŒ‰é’®æ“ä½œ */
const handleQuery = () => {
  page.current = 1;
  getList();
};
const pagination = obj => {
  page.current = obj.page;
  page.size = obj.limit;
  getList();
};
const changeDaterange = value => {
  if (value) {
    searchForm.value.entryDateStart = value[0];
    searchForm.value.entryDateEnd = value[1];
  } else {
    searchForm.value.entryDateStart = undefined;
    searchForm.value.entryDateEnd = undefined;
  }
  handleQuery();
};
const getList = () => {
  tableLoading.value = true;
  // æž„造一个新的对象,不包含entryDate字段
  const params = {...searchForm.value, ...page};
  params.entryDate = undefined;
  productOrderListPage(params)
      .then(res => {
        tableLoading.value = false;
        tableData.value = res.data.records;
@@ -358,101 +373,118 @@
      .catch(() => {
        tableLoading.value = false;
      });
  };
};
  const showRouteItemModal = async row => {
    const orderId = row.id;
    try {
      const res = await getOrderProcessRouteMain(orderId);
      const data = res.data || {};
      if (!data || !data.id) {
        proxy.$modal.msgWarning("未找到关联的工艺路线");
        return;
      }
      router.push({
        path: "/productionManagement/processRouteItem",
        query: {
          id: data.id,
          processRouteCode: data.processRouteCode || "",
          productName: data.productName || "",
          model: data.model || "",
          bomNo: data.bomNo || "",
          description: data.description || "",
          orderId,
          type: "order",
        },
      });
    } catch (e) {
      console.error("获取工艺路线主信息失败:", e);
      proxy.$modal.msgError("获取工艺路线信息失败");
const showRouteItemModal = async row => {
  const orderId = row.id;
  try {
    const res = await getOrderProcessRouteMain(orderId);
    const data = res.data || {};
    if (!data || !data.id) {
      proxy.$modal.msgWarning("未找到关联的工艺路线");
      return;
    }
  };
  const showProductStructure = row => {
    router.push({
      path: "/productionManagement/productStructureDetail",
      path: "/productionManagement/processRouteItem",
      query: {
        id: row.id,
        bomNo: row.bomNo || "",
        productName: row.productCategory || "",
        productModelName: row.specificationModel || "",
        orderId: row.id,
        id: data.id,
        processRouteCode: data.processRouteCode || "",
        productName: data.productName || "",
        model: data.model || "",
        bomNo: data.bomNo || "",
        description: data.description || "",
        orderId,
        type: "order",
      },
    });
  };
  } catch (e) {
    console.error("获取工艺路线主信息失败:", e);
    proxy.$modal.msgError("获取工艺路线信息失败");
  }
};
  // è¡¨æ ¼é€‰æ‹©æ•°æ®
  const handleSelectionChange = (selection) => {
    selectedRows.value = selection;
  };
const showProductStructure = row => {
  router.push({
    path: "/productionManagement/productStructureDetail",
    query: {
      id: row.id,
      bomNo: row.bomNo || "",
      productName: row.productCategory || "",
      productModelName: row.specificationModel || "",
      orderId: row.id,
      type: "order",
    },
  });
};
  const handleDelete = () => {
    let ids = [];
    if (selectedRows.value.length > 0) {
      ids = selectedRows.value.map((item) => item.id);
    } else {
      proxy.$modal.msgWarning("请选择数据");
      return;
    }
    ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "导出", {
      confirmButtonText: "确认",
      cancelButtonText: "取消",
      type: "warning",
    }).then(() => {
      delProductOrder(ids).then((res) => {
        proxy.$modal.msgSuccess("删除成功");
        getList();
      });
    }).catch(() => {
      proxy.$modal.msg("已取消");
// è¡¨æ ¼é€‰æ‹©æ•°æ®
const handleSelectionChange = (selection) => {
  selectedRows.value = selection;
};
const handleDelete = () => {
  let ids = [];
  if (selectedRows.value.length > 0) {
    ids = selectedRows.value.map((item) => item.id);
  } else {
    proxy.$modal.msgWarning("请选择数据");
    return;
  }
  ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "导出", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  }).then(() => {
    delProductOrder(ids).then((res) => {
      proxy.$modal.msgSuccess("删除成功");
      getList();
    });
  };
  }).catch(() => {
    proxy.$modal.msg("已取消");
  });
};
  // å¯¼å‡º
  const handleOut = () => {
    ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
      confirmButtonText: "确认",
      cancelButtonText: "取消",
      type: "warning",
    })
// å¯¼å‡º
const handleOut = () => {
  ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  })
      .then(() => {
        proxy.download("/productOrder/export", {...searchForm.value}, "生产订单.xlsx");
      })
      .catch(() => {
        proxy.$modal.msg("已取消");
      });
  };
};
  const handleConfirmRoute = () => {};
const handleConfirmRoute = () => {
};
  onMounted(() => {
    getList();
  });
const handleFinishOrder = (row) => {
  ElMessageBox.confirm("是否确认结束?", "结束", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  })
      .then(() => {
        finishOrder(row.id).then(res => {
          proxy.$modal.msgSuccess("结束成功");
          getList()
        })
      })
      .catch(() => {
        proxy.$modal.msg("已取消");
      });
};
onMounted(() => {
  getList();
});
</script>
<style scoped lang="scss">
.search_form{
.search_form {
  align-items: start;
}
@@ -468,7 +500,7 @@
  background-color: #f80202;
}
::v-deep .purple{
::v-deep .purple {
  background-color: #F4DEFA;
}
</style>
src/views/productionManagement/productionProcess/index.vue
@@ -223,7 +223,7 @@
      width: 350,
      operation: [
        {
          name: "查看",
          name: "生产参数",
          type: "text",
          clickFun: row => {
            showProcessParamModal(row);
@@ -293,6 +293,7 @@
  // è®¾å¤‡åˆ—表列配置
  const deviceColumns = ref([
    { label: "设备编号", prop: "deviceCode" },
    { label: "设备名称", prop: "deviceName" },
    { label: "规格型号", prop: "deviceModel" },
    { label: "设备品牌", prop: "deviceBrand" },
@@ -318,6 +319,7 @@
  // å¯é€‰è®¾å¤‡åˆ—表列配置
  const selectDeviceColumns = ref([
    { label: "设备编号", prop: "deviceCode" },
    { label: "设备名称", prop: "deviceName" },
    { label: "规格型号", prop: "deviceModel" },
    { label: "设备品牌", prop: "deviceBrand" },
src/views/productionManagement/productionReporting/Input.vue
@@ -67,6 +67,10 @@
    prop: 'model',
  },
  {
    label: 'UID吗',
    prop: 'uid_no',
  },
  {
    label: '投入数量',
    prop: 'quantity',
  },
src/views/productionManagement/productionReporting/index.vue
@@ -183,6 +183,11 @@
      width: 120,
    },
    {
      label: "UID码",
      prop: "uidNo",
      width: 120,
    },
    {
      label: "产出数量",
      prop: "quantity",
      width: 120,
src/views/productionManagement/workOrder/components/ProductionRecordForm.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,128 @@
<script setup lang="ts">
import {computed, reactive, ref, watch} from "vue";
defineOptions({
  name: "ProductionRecordForm"
});
const props = defineProps({
  list: {
    type: Array,
    default() {
      return [];
    }
  },
  labelWidth: {
    type: Number,
    default: 120
  }
});
const formRef = ref();
const formData = reactive({
  list: [] as any[],
});
const fieldLabel = (item: any) => {
  if (!item.unit || item.unit === "/") {
    return item.parameterItem;
  }
  return `${item.parameterItem}(${item.unit})`;
};
const getType = (item: any) => item.type || "文本格式";
const rules = computed(() => {
  const result: Record<string, any[]> = {};
  formData.list.forEach((item, index) => {
    if (String(item.isRequired) === "1") {
      result[`list.${index}.value`] = [{required: true, message: `请输入${item.parameterItem}`, trigger: "blur"}];
    }
  });
  return result;
});
const initData = () => {
  formData.list = props.list || [];
  formData.list.forEach(item => {
    if (item.value === undefined) {
      item.value = null;
    }
  });
};
const submitData = async () => {
  const valid = await formRef.value.validate().catch(() => false)
  if (valid) {
    return formData.list
  } else {
    return null
  }
}
watch(
    () => props.list,
    () => {
      initData();
    },
    {immediate: true, deep: true}
);
defineExpose({
  submitData
})
</script>
<template>
  <el-form ref="formRef" :model="formData" :rules="rules" :label-width="`${labelWidth}px`">
    <el-form-item
        v-for="(item, index) in formData.list"
        :key="item.id"
        :label="fieldLabel(item)"
        :prop="`list.${index}.value`"
    >
      <el-input-number
          v-if="getType(item) === '数值格式'"
          v-model="item.value"
          :controls="false"
          style="width: 100%"
          placeholder="请输入"
      />
      <el-date-picker
          v-else-if="getType(item) === '时间格式'"
          v-model="item.value"
          type="datetime"
          value-format="YYYY-MM-DD HH:mm:ss"
          format="YYYY-MM-DD HH:mm:ss"
          placeholder="请选择"
          style="width: 100%"
      />
      <el-date-picker
          v-else-if="getType(item) === '日期格式'"
          v-model="item.value"
          type="date"
          value-format="YYYY-MM-DD"
          format="YYYY-MM-DD"
          placeholder="请选择"
          style="width: 100%"
      />
      <el-select
          v-else-if="getType(item) === '是/否选框'"
          v-model="item.value"
          placeholder="请选择"
          clearable
          style="width: 100%"
      >
        <el-option label="是" value="是"/>
        <el-option label="否" value="否"/>
      </el-select>
      <el-input
          v-else
          v-model="item.value"
          placeholder="请输入"
          clearable
      />
    </el-form-item>
  </el-form>
</template>
src/views/productionManagement/workOrder/index.vue
@@ -229,6 +229,30 @@
                       :value="user.userId" />
          </el-select>
        </el-form-item>
        <el-form-item label="设备选择">
          <el-select v-model="reportForm.deviceId"
                     style="width: 300px"
                     placeholder="请选择设备"
                     clearable
                     filterable
                     @change="handleDeviceChange">
            <el-option v-for="device in deviceOptions"
                       :key="device.id"
                       :label="device.deviceName"
                       :value="device.id" />
          </el-select>
        </el-form-item>
        <el-form-item v-if="currentDevice" label="设备编号">
          <el-input v-model="currentDevice.deviceCode"
                    disabled
                    style="width: 300px" />
        </el-form-item>
        <el-form-item v-if="currentDevice" label="转数">
          <el-input v-model="currentDevice.rpm"
                    disabled
                    style="width: 300px" />
        </el-form-item>
        <ProductionRecordForm ref="productionRecordFormRef" :list="processParamList"/>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
@@ -243,7 +267,7 @@
</template>
<script setup>
  import { onMounted, ref, nextTick } from "vue";
  import { onMounted, ref, nextTick, computed } from "vue";
  import { ElMessageBox } from "element-plus";
  import dayjs from "dayjs";
  import {
@@ -253,10 +277,17 @@
    downProductWorkOrder,
  } from "@/api/productionManagement/workOrder.js";
  import { getUserProfile, userListNoPageByTenantId } from "@/api/system/user.js";
  import { getBindDevices } from "@/api/productionManagement/productionProcess.js";
  import QRCode from "qrcode";
  import { getCurrentInstance, reactive, toRefs } from "vue";
  import FilesDia from "./components/filesDia.vue";
  import {
    listPage as listProcessParamPage,
  } from "@/api/productionManagement/productProcessParameter.js";
  const { proxy } = getCurrentInstance();
  const ProductionRecordForm = defineAsyncComponent(() => import("./components/ProductionRecordForm.vue"));
  const tableColumn = ref([
    {
@@ -282,6 +313,10 @@
    {
      label: "规格",
      prop: "model",
    },
    {
      label: "UID码",
      prop: "uidNo",
    },
    {
      label: "单位",
@@ -362,7 +397,7 @@
          clickFun: row => {
            showReportDialog(row);
          },
          disabled: row => row.planQuantity <= 0,
          disabled: row => row.planQuantity <= 0 || row.productOrderIsEnd,
        },
      ],
    },
@@ -380,6 +415,7 @@
  const workOrderFilesRef = ref(null);
  const reportFormRef = ref(null);
  const userOptions = ref([]);
  const deviceOptions = ref([]);
  const reportForm = reactive({
    planQuantity: 0,
    totalInvestment: 0,
@@ -392,6 +428,16 @@
    productProcessRouteItemId: "",
    userId: "",
    productMainId: null,
    deviceId: null,
    otherData: {
      rows: []
    },
  });
  const productionRecordFormRef = ref();
  const currentDevice = computed(() => {
    if (!reportForm.deviceId) return null;
    return deviceOptions.value.find(device => device.id === reportForm.deviceId) || null;
  });
  // æŠ•入总量验证规则
@@ -711,8 +757,24 @@
      });
  };
  const showReportDialog = row => {
  const processParamPage = reactive({
    current: 1,
    size: 9999,
    total: 0,
  });
  const getProcessParamList = async (row) => {
    const params = {
      processId: row.processId,
      ...processParamPage,
    };
    const res = await listProcessParamPage(params)
    return res.data.records
  };
  const processParamList = ref([])
  const showReportDialog = async row => {
    currentReportRowData.value = row;
    processParamList.value = await getProcessParamList(row)
    reportForm.planQuantity = row.planQuantity;
    reportForm.totalInvestment = row.totalInvestment;
    reportForm.quantity =
@@ -724,6 +786,11 @@
    reportForm.inspectedQuantity = row.inspectedQuantity;
    reportForm.scrapQty =
      row.scrapQty !== undefined && row.scrapQty !== null ? row.scrapQty : null;
    reportForm.deviceId = row.deviceId || null;
    // èŽ·å–å·¥åºç»‘å®šè®¾å¤‡åˆ—è¡¨
    getDeviceList(row.processId);
    nextTick(() => {
      reportFormRef.value?.clearValidate();
    });
@@ -746,7 +813,16 @@
    workOrderFilesRef.value?.openDialog(row);
  };
  const handleReport = () => {
  const handleReport = async () => {
    try {
      const data = await productionRecordFormRef.value.submitData();
      console.log("生产记录表单数据:", data);
      reportForm.otherData.rows = data || [];
    } catch (error) {
      console.error("获取生产记录表单数据失败", error);
      return;
    }
    reportFormRef.value?.validate(valid => {
      if (!valid) {
        return false;
@@ -806,9 +882,9 @@
        ...reportForm,
        quantity: quantity,
        scrapQty: scrapQty,
        otherData: JSON.stringify(reportForm.otherData)
      };
      // console.log(submitData);
      addProductMain(submitData).then(res => {
        if (res.code === 200) {
          proxy.$modal.msgSuccess("报工成功");
@@ -819,6 +895,11 @@
            confirmButtonText: "确定",
          });
        }
      }).catch(err => {
        console.error("报工失败", err);
        ElMessageBox.alert("报工失败", "提示", {
          confirmButtonText: "确定",
        });
      });
    });
  };
@@ -836,6 +917,24 @@
      });
  };
  // èŽ·å–è®¾å¤‡åˆ—è¡¨
  const getDeviceList = (processId) => {
    if (!processId) {
      deviceOptions.value = [];
      return;
    }
    getBindDevices(processId)
      .then(res => {
        if (res.code === 200) {
          deviceOptions.value = res.data || [];
        }
      })
      .catch(err => {
        console.error("获取设备列表失败", err);
        deviceOptions.value = [];
      });
  };
  // ç”¨æˆ·é€‰æ‹©å˜åŒ–æ—¶æ›´æ–° userName
  const handleUserChange = userId => {
    if (userId) {
@@ -848,6 +947,11 @@
    }
  };
  // è®¾å¤‡é€‰æ‹©å˜åŒ–æ—¶æ›´æ–° deviceId
  const handleDeviceChange = deviceId => {
    reportForm.deviceId = deviceId;
  };
  onMounted(() => {
    getList();
    getUserList();
src/views/qualityManagement/finalInspection/index.vue
@@ -125,6 +125,10 @@
    prop: "model",
  },
  {
    label: "UID码",
    prop: "uidNo",
  },
  {
    label: "单位",
    prop: "unit",
  },
src/views/qualityManagement/nonconformingManagement/index.vue
@@ -144,6 +144,10 @@
    prop: "model",
  },
  {
    label: "UID码",
    prop: "uidNo",
  },
  {
    label: "单位",
    prop: "unit",
  },
src/views/qualityManagement/processInspection/index.vue
@@ -118,6 +118,10 @@
    prop: "model",
  },
  {
    label: "UID码",
    prop: "uidNo",
  },
  {
    label: "单位",
    prop: "unit",
  },
src/views/qualityManagement/rawMaterialInspection/index.vue
@@ -120,6 +120,10 @@
    prop: "model",
  },
  {
    label: "UID码",
    prop: "uidNO",
  },
  {
    label: "单位",
    prop: "unit",
  },
src/views/salesManagement/salesLedger/index.vue
@@ -227,6 +227,7 @@
                    <el-table-column align="center" label="序号" type="index" width="60" />
                    <el-table-column label="产品大类" prop="productCategory" />
                    <el-table-column label="规格型号" prop="specificationModel" />
                    <el-table-column label="UID码" prop="uidNo" />
                    <el-table-column label="单位" prop="unit" />
                    <el-table-column label="数量" prop="quantity" />
                    <el-table-column label="税率(%)" prop="taxRate" />