已修改10个文件
已添加16个文件
3532 ■■■■ 文件已修改
src/api/inventoryManagement/stockIn.js 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/inventoryManagement/stockManage.js 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/qualityManagement/nonconformingManagement.js 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/qualityManagement/qualityInspectFile.js 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/qualityManagement/qualityInspectParam.js 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/qualityManagement/rawMaterialInspection.js 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/dispatchLog/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/issueManagement/index.vue 46 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/receiptManagement/index.vue 392 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/stockManagement/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/finalInspection/components/filesDia.vue 178 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/finalInspection/components/formDia.vue 209 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/finalInspection/components/inspectionFormDia.vue 140 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/finalInspection/index.vue 236 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/metricMaintenance/index.vue 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/nonconformingManagement/components/formDia.vue 249 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/nonconformingManagement/components/inspectionFormDia.vue 257 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/nonconformingManagement/index.vue 285 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/processInspection/components/filesDia.vue 178 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/processInspection/components/formDia.vue 216 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/processInspection/components/inspectionFormDia.vue 140 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/processInspection/index.vue 241 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/rawMaterialInspection/components/filesDia.vue 170 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/rawMaterialInspection/components/formDia.vue 208 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/rawMaterialInspection/components/inspectionFormDia.vue 140 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/rawMaterialInspection/index.vue 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/inventoryManagement/stockIn.js
@@ -46,5 +46,14 @@
    })
}
export function selectProductRecordListByPuechaserId(query) {
    return request({
        url: '/stockin/productlist',
        method: 'get',
        params: query
    })
}
//
src/api/inventoryManagement/stockManage.js
@@ -9,13 +9,6 @@
    });
};
export const getStockManageOutPage = (params) => {
    return request({
        url: "/stockmanagement/stockoutpage",
        method: "get",
        params,
    });
};
// ä¿®æ”¹åº“存信息
export const updateStockManage = (data) => {
src/api/qualityManagement/nonconformingManagement.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,42 @@
import request from '@/utils/request'
// æŸ¥è¯¢ä¸åˆæ ¼ç®¡ç†åˆ—表
export function qualityUnqualifiedListPage(query) {
    return request({
        url: '/quality/qualityUnqualified/listPage',
        method: 'get',
        params: query,
    })
}
// æ–°å¢žä¸åˆæ ¼ç®¡ç†åˆ—表
export function qualityUnqualifiedAdd(query) {
    return request({
        url: '/quality/qualityUnqualified/add',
        method: 'post',
        data: query,
    })
}
// ä¿®æ”¹ä¸åˆæ ¼ç®¡ç†åˆ—表
export function qualityUnqualifiedUpdate(query) {
    return request({
        url: '/quality/qualityUnqualified/update',
        method: 'post',
        data: query,
    })
}
// åˆ é™¤ä¸åˆæ ¼ç®¡ç†åˆ—表
export function qualityUnqualifiedDel(query) {
    return request({
        url: '/quality/qualityUnqualified/del',
        method: 'delete',
        data: query,
    })
}
// æŸ¥è¯¢ä¸åˆæ ¼ç®¡ç†ä¿¡æ¯
export function getQualityUnqualifiedInfo(query) {
    return request({
        url: '/quality/qualityUnqualified/' + query,
        method: 'get',
        data: query,
    })
}
src/api/qualityManagement/qualityInspectFile.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
import request from '@/utils/request'
// æŸ¥è¯¢é™„件列表
export function qualityInspectFileListPage(query) {
    return request({
        url: '/quality/qualityInspectFile/listPage',
        method: 'get',
        params: query,
    })
}
// æŸ¥è¯¢é™„件列表
export function qualityInspectFileAdd(query) {
    return request({
        url: '/quality/qualityInspectFile/add',
        method: 'post',
        data: query,
    })
}
// æŸ¥è¯¢é™„件列表
export function qualityInspectFileDel(query) {
    return request({
        url: '/quality/qualityInspectFile/del',
        method: 'delete',
        data: query,
    })
}
src/api/qualityManagement/qualityInspectParam.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,27 @@
import request from '@/utils/request'
// æŸ¥è¯¢æ£€éªŒæŒ‡æ ‡
export function qualityInspectParamInfo(query) {
    return request({
        url: '/quality/qualityInspectParam/' + query,
        method: 'get',
        data: query,
    })
}
// æäº¤æ£€éªŒ
export function qualityInspectParamUpdate(query) {
    return request({
        url: '/quality/qualityInspectParam/update',
        method: 'post',
        data: query,
    })
}
// åˆ é™¤æ£€éªŒè®°å½•
export function qualityInspectParamDel(query) {
    return request({
        url: '/quality/qualityInspectParam/del',
        method: 'delete',
        data: query,
    })
}
src/api/qualityManagement/rawMaterialInspection.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,34 @@
import request from '@/utils/request'
// æŸ¥è¯¢åŽŸææ–™æ£€éªŒåˆ—è¡¨
export function qualityInspectListPage(query) {
    return request({
        url: '/quality/qualityInspect/listPage',
        method: 'get',
        params: query,
    })
}
// æ–°å¢žåŽŸææ–™æ£€éªŒ
export function qualityInspectAdd(query) {
    return request({
        url: '/quality/qualityInspect/add',
        method: 'post',
        data: query,
    })
}
// ä¿®æ”¹åŽŸææ–™æ£€éªŒ
export function qualityInspectUpdate(query) {
    return request({
        url: '/quality/qualityInspect/update',
        method: 'post',
        data: query,
    })
}
// åˆ é™¤åŽŸææ–™æ£€éªŒ
export function qualityInspectDel(query) {
    return request({
        url: '/quality/qualityInspect/del',
        method: 'delete',
        data: query,
    })
}
src/views/inventoryManagement/dispatchLog/index.vue
@@ -231,7 +231,7 @@
// å¯¼å‡º
const handleOut = () => {
  ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
  ElMessageBox.confirm("是否确认导出?", "导出", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
src/views/inventoryManagement/issueManagement/index.vue
@@ -75,16 +75,13 @@
  getStockManagePage,
    delStockManage,
    stockOut,
  getStockManageOutPage
} from "@/api/inventoryManagement/stockManage.js";
const userStore = useUserStore()
const { proxy } = getCurrentInstance()
const tableData = ref([])
const productData = ref([])
const selectedRows = ref([])
const userList = ref([])
const customerOption = ref([])
const tableLoading = ref(false)
const page = reactive({
  current: 1,
@@ -98,37 +95,17 @@
const data = reactive({
  searchForm: {
    supplierName: '',
    inboundQuantity:'',
    inboundTime:'',
    nickName: '',
    userId: '',
  },
  form: {
    supplierId: null,
    supplierName: '',
    productId: null,
    productName: '',
    userId: userStore.userId,
    nickName: '',
    productModelId: null,
    model: '',
    unit: '',
    productrecordId: null,
    taxInclusiveUnitPrice: '',
    taxInclusiveTotalPrice: '',
    taxRate: '',
    taxExclusiveTotalPrice: '',
    inboundTime: '',
    inboundBatch: '',
    stockQuantity: '',
    boundTime: '',
    productrecordId: '',
  },
  rules: {
    supplierName: [{ required: true, message: "请输入", trigger: "blur" }],
    productCategory: [{ required: true, message: "请选择", trigger: "change" }],
    specificationModel: [{ required: true, message: "请输入", trigger: "blur" }],
    unit: [{ required: true, message: "请输入", trigger: "blur" }],
    inboundTime: [{ required: true, message: "请选择", trigger: "change" }],
    inboundBatch: [{ required: true, message: "请输入", trigger: "blur" }],
    inboundQuantity: [{ required: true, message: "请输入", trigger: "blur" }],
    taxInclusiveUnitPrice: [{ required: true, message: "请输入", trigger: "blur" }],
    taxRate: [{ required: true, message: "请输入", trigger: "blur" }],
    nickname: [{ required: true, message: "请选择", trigger: "change" }]
  }
})
@@ -147,7 +124,7 @@
}
const getList = () => {
  tableLoading.value = true
  getStockManageOutPage({ ...searchForm.value, ...page }).then(res => {
  getStockManagePage({ ...searchForm.value, ...page }).then(res => {
    tableLoading.value = false
    tableData.value = res.data.records
    console.log('res', res.data.records)
@@ -155,6 +132,7 @@
    tableLoading.value = false
  })
}
const findNodeById = (nodes, productId) => {
  for (let i = 0; i < nodes.length; i++) {
    if (nodes[i].value === productId) {
@@ -171,7 +149,6 @@
};
// è¡¨æ ¼é€‰æ‹©æ•°æ®
const handleSelectionChange = (selection) => {
  // è¿‡æ»¤æŽ‰å­æ•°æ®
  selectedRows.value = selection.filter(item => item.id);
  console.log('selection', selectedRows.value)
@@ -191,12 +168,12 @@
  form.value = {}
  // åˆå§‹åŒ–表单数据
  form.value = {
    productrecordId: '',
    inboundQuantity: '', // å‡ºåº“数量清空
    inboundTime: getCurrentDate(), // é»˜è®¤å½“前日期
    nickName: '', // é»˜è®¤å½“前用户
  }
  console.log('form',form.value)
  // åŠ è½½ç”¨æˆ·åˆ—è¡¨
  try {
    const userLists = await userListNoPage()
@@ -212,10 +189,11 @@
    if (valid && currentRowId.value) {
      const outData = {
        id: currentRowId.value, // åŽŸå§‹è®°å½•ID
        outQuantity: form.value.inboundQuantity, // å‡ºåº“数量
        outTime: form.value.inboundTime, // å‡ºåº“æ—¶é—´
        Quantity: form.value.inboundQuantity, // å‡ºåº“数量
        Time: form.value.inboundTime, // å‡ºåº“æ—¶é—´
        userId: form.value.userId // æ“ä½œäºº
      }
      console.log(outData)
      stockOut(outData).then(res => {
        proxy.$modal.msgSuccess("提交成功")
@@ -236,7 +214,7 @@
// å¯¼å‡º
const handleOut = () => {
  ElMessageBox.confirm(
    '选中的内容将被导出,是否确认导出?',
    '是否确认导出?',
    '导出', {
    confirmButtonText: '确认',
    cancelButtonText: '取消',
src/views/inventoryManagement/receiptManagement/index.vue
@@ -40,16 +40,32 @@
      <pagination v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper"
        :page="page.current" :limit="page.size" @pagination="paginationChange" />
    </div>
    <el-dialog v-model="dialogFormVisible" :title="operationType === 'add' ? '新增入库' : '编辑入库'" width="70%"
      @close="closeDia">
      <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
        <el-form-item label="采购订单号" prop="salesContractNo">
              <el-input v-model="form.salesContractNo" placeholder="请输入" clearable />
              <el-input
                  v-model="form.purchaseContractNumber"
                  placeholder="请输入合同号"
                  clearable
                  @change="searchByContractNo"
                  :disabled="operationType === 'edit'"
              >
                <template #append>
                  <el-button
                      icon="Search"
                      @click="searchByContractNo"
                      :loading="loadingProducts"
                  />
                </template>
              </el-input>
            </el-form-item>
        <el-table
          :data="productData"
          :data="productList"
          border
          @selection-change="productSelected"
          v-loading="loadingProducts"
          @selection-change="handleSelectionChange"
        >
          <el-table-column align="center" type="selection" width="55" />
          <el-table-column
@@ -61,6 +77,7 @@
          <el-table-column label="产品大类" prop="productCategory" />
          <el-table-column label="规格型号" prop="specificationModel" />
          <el-table-column label="单位" prop="unit" width="70" />
          <el-table-column label="供应商" prop="supplierName" width="100" />
          <el-table-column label="采购数量" prop="quantity" width="100" />
          <el-table-column label="待入库数量" prop="quantity0" width="100" />
          <el-table-column label="本次入库数量" prop="quantityStock" width="120">
@@ -104,29 +121,25 @@
import { ref } from 'vue'
import { ElMessageBox } from "element-plus";
import useUserStore from '@/store/modules/user'
import { userListNoPage } from "@/api/system/user.js";
import {
  getStockInPage,
  updateStockIn,
  addSutockIn,
  delStockIn,
  exportStockIn
  selectProductRecordListByPuechaserId
} from "@/api/inventoryManagement/stockIn.js";
import {listSupplier} from "@/api/basicData/supplierManageFile.js";
import {modelListPage, productTreeList} from "@/api/basicData/product.js";
const userStore = useUserStore()
const { proxy } = getCurrentInstance()
const tableData = ref([])
const selectedRows = ref([])
const userList = ref([])
const supplierLists = ref([])
const productList = ref([]);
const productModelList = ref([]);
const purchaseRecords  = ref([]);
const loadingProducts = ref(false);
const loading = ref(false);
const tableLoading = ref(false)
const page = reactive({
  current: 1,
  size: 100,
@@ -134,52 +147,32 @@
const total = ref(0)
// ç”¨æˆ·ä¿¡æ¯è¡¨å•弹框数据
const operationType = ref('')
const dialogFormVisible = ref(false)
const operationType = ref('')// æ“ä½œç±»åž‹: 'add' æˆ– 'edit'
const dialogFormVisible = ref(false)// å¼¹æ¡†æ˜¾ç¤ºçŠ¶æ€
const productList = ref([]);// äº§å“åˆ—表数据
const loadingProducts = ref(false);// äº§å“åŠ è½½çŠ¶æ€
const productSelectedRows = ref([]) // äº§å“è¡¨æ ¼é€‰ä¸­è¡Œ
const data = reactive({
  searchForm: {
    supplierName: '',
  },
  form: {
    supplierId: null,
    supplierName: '',
    productId: null,
    productName: '',
    userId: userStore.userId,
    nickName: '',
    model: '',
    productModelId: null,
    unit: '',
    productrecordId: null,
    taxInclusiveUnitPrice: '',
    taxInclusiveTotalPrice: '',
    taxRate: '',
    taxExclusiveTotalPrice: '',
    inboundTime: '',
    inboundBatch: '',
    inboundQuantity: ''
    id: null,
    purchaseContractNumber: '', // é‡‡è´­è®¢å•号
    supplierId: null,       // ä¾›åº”商ID
    supplierName: '',       // ä¾›åº”商名称
    inboundTime: '',        // å…¥åº“æ—¶é—´
    inboundBatch: '',       // å…¥åº“批次
    recorderId: userStore.userId, // å½•入人ID
    recorderName: userStore.name, // å½•入人姓名
    entryDate: getCurrentDate(),  // å½•入日期
    remark: '',             // å¤‡æ³¨
  },
  rules: {
    productId: [
      { required: true, message: "请选择产品大类", trigger: "change" }
    ],
    productModelId: [
      { required: true, message: "请选择规格型号", trigger: "change" }
    ],
    supplierId: [
      { required: true, message: "请选择供应商", trigger: "change" }
    ],
    inboundQuantity: [
      { required: true, message: "请输入入库数量", trigger: "blur" }
    ],
    userId: [
      { required: true, message: "请选择入库人", trigger: "change" }
    ],
    unit: [{ required: true, message: "请输入", trigger: "blur" }],
    inboundTime: [{ required: true, message: "请选择", trigger: "change" }],
    inboundBatch: [{ required: true, message: "请输入", trigger: "blur" }],
    taxInclusiveUnitPrice: [{ required: true, message: "请输入", trigger: "blur" }],
    taxRate: [{ required: true, message: "请输入", trigger: "blur" }],
    purchaseContractNumber: [{ required: true, message: "请输入采购合同号", trigger: "blur" }],
    supplierId: [{ required: true, message: "请选择供应商", trigger: "change" }],
    inboundTime: [{ required: true, message: "请选择入库时间", trigger: "change" }],
    inboundBatch: [{ required: true, message: "请输入入库批次", trigger: "blur" }]
  }
})
const { searchForm, form, rules } = toRefs(data)
@@ -190,13 +183,11 @@
  page.current = 1
  getList()
}
const paginationChange = (obj) => {
  page.current = obj.page;
  page.size = obj.limit;
  getList()
}
const getList = () => {
  tableLoading.value = true
  getStockInPage({ ...searchForm.value, ...page }).then(res => {
@@ -209,211 +200,139 @@
  })
}
// æ­£ç¡®çš„产品列表加载方法
const loadProductList = async () => {
  loadingProducts.value = true;
// è°ƒç”¨selectProductRecordListByPuechaserId这个方法根据合同查询到id,再调用getProductRecordByhetong这个方法根据id查询到产品订单记录
// æ–°å¢žæ ¹æ®åˆåŒå·æŸ¥è¯¢äº§å“è®°å½•的方法
const searchByContractNo = async () =>
{
  if (!form.value.purchaseContractNumber) {
    proxy.$modal.msgWarning('请输入合同号')
    return
  }
  try {
    const res = await productTreeList();
    // æ‰å¹³åŒ–处理产品树
    const flattenProducts = (nodes, parentId = null) => {
      let result = [];
      nodes.forEach(node => {
        // åªæ·»åŠ æœ‰id和label的节点
        if (node.id && node.label) {
          result.push({
            id: node.id,
            productName: node.label,
            parentId: parentId
          });
        }
        // é€’归处理子节点
        if (node.children) {
          result = result.concat(flattenProducts(node.children, node.id));
        }
      });
      return result;
    };
    productList.value = flattenProducts(res.data);
    console.log('加载的产品列表:', productList.value);
    loadingProducts.value = true
    // æ ¹æ®åˆåŒæŸ¥è¯¢äº§å“è®°å½•
    const productRes = await selectProductRecordListByPuechaserId({
      purchaseContractNumber: form.value.purchaseContractNumber
    });
    console.log('productRes:', productRes)
    if (!productRes.data || productRes.data.length === 0) {
      proxy.$modal.msgWarning('该合同下没有产品记录')
      productList.value = [];
      return
    }
    // å¤„理产品数据,添加本次入库数量字段
    productList.value = productRes.data.map(item => ({
      ...item,
      quantityStock: 0 // åˆå§‹åŒ–本次入库数量为0
    }))
  } catch (error) {
    console.error('加载产品列表失败:', error);
    proxy.$modal.msgError('加载产品列表失败');
    console.error('查询产品记录失败:', error)
    proxy.$modal.msgError('查询产品记录失败')
    productList.value = [];
  } finally {
    loadingProducts.value = false;
    loadingProducts.value = false
  }
  return null; // æ²¡æœ‰æ‰¾åˆ°èŠ‚ç‚¹ï¼Œè¿”å›žnull
};
}
// è¡¨æ ¼é€‰æ‹©æ•°æ®
// const handleSelectionChange = (selection) => {
// åŠ è½½è§„æ ¼åž‹å·åˆ—è¡¨
  const loadProductModels = async (productId) => {
    if (!productId) {
      productModelList.value = [];
      return;
    }
    try {
      const res = await modelListPage({
        id: productId,
        current: 1,
        size: 100
      });
      productModelList.value = res.data.records.map(item => ({
        id: item.id,
        model: item.model,
        unit: item.unit
      }));
    } catch (error) {
      console.error('加载规格型号失败:', error);
      proxy.$modal.msgError('加载规格型号失败');
    }
  };
// äº§å“é€‰æ‹©å˜åŒ–
  const handleProductChange = (productId) => {
    form.value.productModelId = null
    form.value.productrecordId = null
    resetPurchaseFields()
    if (productId) {
      loadProductModels(productId)
    } else {
      productModelList.value = []
    }
  }
// è§„格型号选择变化
  const handleModelChange = async (modelId) => {
    if (!form.value.productId || !modelId) return
    try {
      // æ ¹æ®äº§å“ID和型号ID查询采购记录
      const res = await getPurchaseRecords({
        productId: form.value.productId,
        productModelId: form.value.productModelId,
        type: 2 // å‡è®¾2表示已批准的采购记录
      })
      purchaseRecords.value = res.data.records
      if (purchaseRecords.value.length > 0) {
        // é»˜è®¤å–第一条采购记录
        const record = purchaseRecords.value[0]
        fillFormFromPurchaseRecord(record)
      }
    } catch (error) {
      console.error('查询采购记录失败:', error)
      proxy.$modal.msgError('查询采购记录失败')
    }
  }
// ä»Žé‡‡è´­è®°å½•填充表单
  const fillFormFromPurchaseRecord = (record) => {
    form.value.productrecordId = record.id
    form.value.taxInclusiveUnitPrice = record.taxInclusiveUnitPrice
    form.value.taxRate = record.taxRate
    form.value.taxInclusiveTotalPrice = record.taxInclusiveTotalPrice
    form.value.taxExclusiveTotalPrice = record.taxExclusiveTotalPrice
  }
// é‡ç½®é‡‡è´­ç›¸å…³å­—段
  const resetPurchaseFields = () => {
    form.value.productrecordId = null
    form.value.unit = ''
    form.value.taxInclusiveUnitPrice = null
    form.value.taxRate = null
    form.value.taxInclusiveTotalPrice = null
    form.value.taxExclusiveTotalPrice = null
  }
  const loadUserList = async () => {
    try {
      const res = await userListNoPage()
      userList.value = res.data
    } catch (error) {
      console.error('加载用户列表失败:', error)
    }
  }
  const loadSupplierList = async () => {
    try {
      const res = await listSupplier()
      supplierLists.value = res.data.records
    } catch (error) {
      console.error('加载供应商列表失败:', error)
    }
  }
// æ‰“开弹框
  const openForm = async (type, row) => {
    operationType.value = type
    dialogFormVisible.value = true
    // åŠ è½½å¿…è¦æ•°æ®
    await Promise.all([
      loadUserList(),
      loadSupplierList(),
      loadProductList()
    ])
    if (type === 'add') {
      // æ–°å¢žæ—¶é‡ç½®è¡¨å•
      // æ–°å¢žæ—¶åˆå§‹åŒ–表单
      form.value = {
        userId: userStore.userId // è®¾ç½®é»˜è®¤å…¥åº“人为当前用户
        id: null,
        purchaseContractNumber: '',
        supplierId: null,
        supplierName: '',
        inboundTime: '',
        inboundBatch: '',
        recorderId: userStore.userId,
        recorderName: userStore.name,
        entryDate: getCurrentDate(),
        remark: ''
      }
      productList.value = [] // æ¸…空产品列表
    } else {
      // ç¼–辑时填充表单数据
      form.value = {
        ...row,
        supplierId: row.supplierId,
        productId: row.productId,
        productModelId: row.productModelId,
        userId: row.userId
      }
      if (row.productId) {
        await loadProductModels(row.productId)
      form.value = JSON.parse(JSON.stringify(row))
      try {
        loadingProducts.value = true
        // æ ¹æ®åˆåŒå·åŠ è½½å¯¹åº”çš„äº§å“åˆ—è¡¨ï¼ˆå‡è®¾ getProductByContract æ˜¯å¯ç”¨æŽ¥å£ï¼‰
        const res = await getProductRecordByhetong(form.value.purchaseContractNumber)
        productList.value = res.data.map(item => ({
          ...item,
          quantityStock: item.quantityStock || 0 // å¦‚果已有入库数量则保留
        }))
      } catch (error) {
        proxy.$modal.msgError('加载产品失败')
        productList.value = []
      } finally {
        loadingProducts.value = false
      }
    }
  }
// æäº¤è¡¨å•
  const submitForm = async () => {
    try {
      await proxy.$refs.formRef.validate()
      if (!form.value.productrecordId) {
        proxy.$modal.msgError('请选择产品大类和规格型号以获取采购记录')
      // éªŒè¯è‡³å°‘选择了一个产品
      if (selectedRows.value.length === 0) {
        proxy.$modal.msgError('请先查询并选择产品')
        return
      }
      const submitData = {
        productrecordId: form.value.productrecordId,
        supplierId: form.value.supplierId,
        inboundQuantity: form.value.inboundQuantity,
        userId: form.value.userId,
      // éªŒè¯å…¥åº“数量
      const invalidProducts = selectedRows.value.filter(
          product => product.quantityStock <= 0 || product.quantityStock > product.quantity0
      )
      if (invalidProducts.length > 0) {
        proxy.$modal.msgError('请为所有产品输入有效的入库数量')
        return
      }
      const apiMethod = operationType.value === 'add' ? addSutockIn : updateStockIn
      await apiMethod(submitData)
      // å‡†å¤‡æäº¤æ•°æ®
      // å‡†å¤‡æäº¤æ•°æ® - ä¿®æ”¹ä¸ºåŽç«¯éœ€è¦çš„æ ¼å¼
      const stockInData = {
        // å…¥åº“单基本信息
        ...form.value,
        inboundTime: formatDateTime(form.value.inboundTime),
        nickName: userStore.nickName,// ä½¿ç”¨æ–°æ ¼å¼åŒ–函数
        details: selectedRows.value.map(product => ({
          id: product.id,
          inboundQuantity: Number(product.quantityStock)
        })),
      };
      console.log('准备提交的数据:', JSON.parse(JSON.stringify(stockInData)));
      // è°ƒç”¨API
      loading.value = true
      await addSutockIn(stockInData)
      proxy.$modal.msgSuccess(operationType.value === 'add' ? '新增成功' : '修改成功')
      proxy.$modal.msgSuccess('新增入库成功')
      closeDia()
      getList()
      getList() // åˆ·æ–°åˆ—表
    } catch (error) {
      console.error('提交失败:', error)
      if (!error.errors) {
        proxy.$modal.msgError('操作失败,请重试')
      }
    } finally {
      loading.value = false
    }
  }
// å…³é—­å¼¹æ¡†
  const closeDia = () => {
    proxy.$refs.formRef.resetFields()
    dialogFormVisible.value = false
  }
// è¡¨æ ¼é€‰æ‹©æ•°æ®
  const handleSelectionChange = (selection) => {
@@ -421,6 +340,7 @@
    selectedRows.value = selection.filter(item => item.id);
    console.log('selection', selectedRows.value)
  }
  const expandedRowKeys = ref([])
// ä¸»è¡¨åˆè®¡æ–¹æ³•
@@ -431,7 +351,7 @@
// å¯¼å‡º
  const handleOut = () => {
    ElMessageBox.confirm(
        '选中的内容将被导出,是否确认导出?',
        '是否确认导出?',
        '导出', {
          confirmButtonText: '确认',
          cancelButtonText: '取消',
@@ -470,26 +390,36 @@
  }
// èŽ·å–å½“å‰æ—¥æœŸå¹¶æ ¼å¼åŒ–ä¸º YYYY-MM-DD
  function getCurrentDate() {
    const today = new Date();
    const year = today.getFullYear();
    const month = String(today.getMonth() + 1).padStart(2, '0'); // æœˆä»½ä»Ž0开始
    const day = String(today.getDate()).padStart(2, '0');
    return `${year}-${month}-${day}`;
// ä¿®æ”¹ä¸ºæ›´é€šç”¨çš„æ—¥æœŸæ—¶é—´æ ¼å¼åŒ–函数
function formatDateTime(date = new Date(), includeTime = true) {
  const d = new Date(date);
  const year = d.getFullYear();
  const month = String(d.getMonth() + 1).padStart(2, '0');
  const day = String(d.getDate()).padStart(2, '0');
  if (!includeTime) {
    return `${year}-${month}-${day}`; // ä¿æŒåŽŸæœ‰ getCurrentDate åŠŸèƒ½
  }
  const productSelectedRows = ref([])
  const productSelected = (selectedRows) => {
    productSelectedRows.value = selectedRows;
  };
  // æ–°å¢žæ—¶é—´éƒ¨åˆ†æ ¼å¼åŒ–
  const hours = String(d.getHours()).padStart(2, '0');
  const minutes = String(d.getMinutes()).padStart(2, '0');
  const seconds = String(d.getSeconds()).padStart(2, '0');
  const formattedNumber = (row, column, cellValue) => {
    return parseFloat(cellValue).toFixed(2);
  };
  return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
// ä¿æŒåŽŸæœ‰ getCurrentDate çš„兼容性
function getCurrentDate() {
  return formatDateTime(new Date(), false);
}
  onMounted(() => {
    getList()
  })
}
</script>
<style scoped lang="scss"></style>
src/views/inventoryManagement/stockManagement/index.vue
@@ -304,7 +304,7 @@
// å¯¼å‡º
const handleOut = () => {
  ElMessageBox.confirm(
    '选中的内容将被导出,是否确认导出?',
    '是否确认导出?',
    '导出', {
    confirmButtonText: '确认',
    cancelButtonText: '取消',
src/views/qualityManagement/finalInspection/components/filesDia.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,178 @@
<template>
  <div>
    <el-dialog
        v-model="dialogFormVisible"
        title="上传附件"
        width="50%"
        @close="closeDia"
    >
      <div style="margin-bottom: 10px;text-align: right">
        <el-upload
            v-model:file-list="fileList"
            class="upload-demo"
            :action="uploadUrl"
            :on-success="handleUploadSuccess"
            :on-error="handleUploadError"
            name="file"
            :show-file-list="false"
            :headers="headers"
            style="display: inline;margin-right: 10px"
        >
          <el-button type="primary">上传附件</el-button>
        </el-upload>
        <el-button type="danger" plain @click="handleDelete">删除</el-button>
      </div>
      <PIMTable
          rowKey="id"
          :column="tableColumn"
          :tableData="tableData"
          :tableLoading="tableLoading"
          :isSelection="true"
          @selection-change="handleSelectionChange"
          height="600"
      >
      </PIMTable>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="closeDia">取消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import {ref} from "vue";
import {getStaffJoinInfo, staffJoinAdd, staffJoinUpdate} from "@/api/personnelManagement/onboarding.js";
import {Search} from "@element-plus/icons-vue";
import {
  qualityInspectParamDel,
  qualityInspectParamInfo,
  qualityInspectParamUpdate
} from "@/api/qualityManagement/qualityInspectParam.js";
import {ElMessageBox} from "element-plus";
import {getToken} from "@/utils/auth.js";
import {
  qualityInspectFileAdd,
  qualityInspectFileDel,
  qualityInspectFileListPage
} from "@/api/qualityManagement/qualityInspectFile.js";
const { proxy } = getCurrentInstance()
const emit = defineEmits(['close'])
const dialogFormVisible = ref(false);
const currentId = ref('')
const selectedRows = ref([]);
const tableColumn = ref([
  {
    label: "文件名称",
    prop: "name",
  },
  // {
  //   label: "上传人",
  //   prop: "createUser",
  // },
  // {
  //   label: "上传时间",
  //   prop: "createTime",
  // },
  {
    dataType: "action",
    label: "操作",
    align: "center",
    operation: [
      {
        name: "下载",
        type: "text",
        clickFun: (row) => {
          downLoadFile(row);
        },
      }
    ],
  },
]);
const tableData = ref([]);
const fileList = ref([]);
const tableLoading = ref(false);
const headers = ref({
  Authorization: "Bearer " + getToken(),
});
const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + "/file/upload"); // ä¸Šä¼ çš„图片服务器地址
// æ‰“开弹框
const openDialog = (row) => {
  dialogFormVisible.value = true;
  currentId.value = row.id;
  getList()
}
const getList = () => {
  qualityInspectFileListPage({inspectId: currentId.value}).then(res => {
    tableData.value = res.data.records;
  })
}
// è¡¨æ ¼é€‰æ‹©æ•°æ®
const handleSelectionChange = (selection) => {
  selectedRows.value = selection;
};
// ä¸‹è½½é™„ä»¶
const downLoadFile = (row) => {
  proxy.$download.name(row.url);
}
// å…³é—­å¼¹æ¡†
const closeDia = () => {
  dialogFormVisible.value = false;
  emit('close')
};
// ä¸Šä¼ æˆåŠŸå¤„ç†
function handleUploadSuccess(res, file) {
  // å¦‚果上传成功
  if (res.code == 200) {
    const fileRow = {}
    fileRow.name = res.data.originalName
    fileRow.url = res.data.tempPath
    uploadFile(fileRow)
  } else {
    proxy.$modal.msgError("文件上传失败");
  }
}
function uploadFile(file) {
  file.inspectId = currentId.value;
  qualityInspectFileAdd(file).then(res => {
    proxy.$modal.msgSuccess("文件上传成功");
    getList()
  })
}
// ä¸Šä¼ å¤±è´¥å¤„理
function handleUploadError() {
  proxy.$modal.msgError("文件上传失败");
}
// åˆ é™¤
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(() => {
    qualityInspectFileDel(ids).then((res) => {
      proxy.$modal.msgSuccess("删除成功");
      getList();
    });
  }).catch(() => {
    proxy.$modal.msg("已取消");
  });
};
defineExpose({
  openDialog,
});
</script>
<style scoped>
</style>
src/views/qualityManagement/finalInspection/components/formDia.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,209 @@
<template>
  <div>
    <el-dialog
        v-model="dialogFormVisible"
        :title="operationType === 'add' ? '新增原材料检验' : '编辑原材料检验'"
        width="70%"
        @close="closeDia"
    >
      <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="产品名称:" prop="productId">
              <el-tree-select
                  v-model="form.productId"
                  placeholder="请选择"
                  clearable
                  check-strictly
                  @change="getModels"
                  :data="productOptions"
                  :render-after-expand="false"
                  style="width: 100%"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="规格型号:" prop="model">
              <el-input v-model="form.model" placeholder="请输入" clearable/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="单位:" prop="unit">
              <el-input v-model="form.unit" placeholder="请输入" clearable/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="数量:" prop="quantity">
              <el-input v-model="form.quantity" placeholder="请输入" clearable/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="检测单位:" prop="checkCompany">
              <el-input v-model="form.checkCompany" placeholder="请输入" clearable/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="检测结果:" prop="checkResult">
              <el-select v-model="form.checkResult">
                <el-option label="合格" value="合格" />
                <el-option label="不合格" value="不合格" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="检验员:" prop="checkName">
              <el-input v-model="form.checkName" placeholder="请输入" clearable/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="检测日期:" prop="checkTime">
              <el-date-picker
                  v-model="form.checkTime"
                  type="date"
                  placeholder="请选择日期"
                  value-format="YYYY-MM-DD"
                  format="YYYY-MM-DD"
                  clearable
                  style="width: 100%"
              />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确认</el-button>
          <el-button @click="closeDia">取消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import {ref} from "vue";
import {getOptions} from "@/api/procurementManagement/procurementLedger.js";
import {productTreeList} from "@/api/basicData/product.js";
import {qualityInspectAdd, qualityInspectUpdate} from "@/api/qualityManagement/rawMaterialInspection.js";
const { proxy } = getCurrentInstance()
const emit = defineEmits(['close'])
const dialogFormVisible = ref(false);
const operationType = ref('')
const data = reactive({
  form: {
    checkTime: "",
    process: "",
    checkName: "",
    productName: "",
    productId: "",
    model: "",
    unit: "",
    quantity: "",
    checkCompany: "",
    checkResult: "",
  },
  rules: {
    checkTime: [{ required: false, message: "请输入", trigger: "blur" },],
    process: [{ required: true, message: "请输入", trigger: "blur" }],
    checkName: [{ required: false, message: "请输入", trigger: "blur" }],
    productId: [{ required: true, message: "请输入", trigger: "blur" }],
    model: [{ required: false, message: "请输入", trigger: "blur" }],
    unit: [{ required: false, message: "请输入", trigger: "blur" }],
    quantity: [{ required: true, message: "请输入", trigger: "blur" }],
    checkCompany: [{ required: false, message: "请输入", trigger: "blur" }],
    checkResult: [{ required: false, message: "请输入", trigger: "blur" }],
  },
});
const { form, rules } = toRefs(data);
const supplierList = ref([]);
const productOptions = ref([]);
// æ‰“开弹框
const openDialog = (type, row) => {
  operationType.value = type;
  dialogFormVisible.value = true;
  getOptions().then((res) => {
    supplierList.value = res.data;
  });
  getProductOptions();
  if (operationType.value === 'edit') {
    form.value = {...row}
  }
}
const getProductOptions = () => {
  productTreeList().then((res) => {
    productOptions.value = convertIdToValue(res);
  });
};
const getModels = (value) => {
  form.value.productName = findNodeById(productOptions.value, value);
};
const findNodeById = (nodes, productId) => {
  for (let i = 0; i < nodes.length; i++) {
    if (nodes[i].value === productId) {
      return nodes[i].label; // æ‰¾åˆ°èŠ‚ç‚¹ï¼Œè¿”å›žè¯¥èŠ‚ç‚¹
    }
    if (nodes[i].children && nodes[i].children.length > 0) {
      const foundNode = findNodeById(nodes[i].children, productId);
      if (foundNode) {
        return foundNode; // åœ¨å­èŠ‚ç‚¹ä¸­æ‰¾åˆ°ï¼Œè¿”å›žè¯¥èŠ‚ç‚¹
      }
    }
  }
  return null; // æ²¡æœ‰æ‰¾åˆ°èŠ‚ç‚¹ï¼Œè¿”å›žnull
};
function convertIdToValue(data) {
  return data.map((item) => {
    const { id, children, ...rest } = item;
    const newItem = {
      ...rest,
      value: id, // å°† id æ”¹ä¸º value
    };
    if (children && children.length > 0) {
      newItem.children = convertIdToValue(children);
    }
    return newItem;
  });
}
// æäº¤äº§å“è¡¨å•
const submitForm = () => {
  proxy.$refs.formRef.validate(valid => {
    if (valid) {
      form.value.inspectType = 2
      if (operationType.value === "add") {
        qualityInspectAdd(form.value).then(res => {
          proxy.$modal.msgSuccess("提交成功");
          closeDia();
        })
      } else {
        qualityInspectUpdate(form.value).then(res => {
          proxy.$modal.msgSuccess("提交成功");
          closeDia();
        })
      }
    }
  })
}
// å…³é—­å¼¹æ¡†
const closeDia = () => {
  proxy.resetForm("formRef");
  dialogFormVisible.value = false;
  emit('close')
};
defineExpose({
  openDialog,
});
</script>
<style scoped>
</style>
src/views/qualityManagement/finalInspection/components/inspectionFormDia.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,140 @@
<template>
  <div>
    <el-dialog
        v-model="dialogFormVisible"
        title="填写检验记录"
        width="70%"
        @close="closeDia"
    >
      <div style="margin-bottom: 10px;text-align: right">
        <el-button type="danger" plain @click="handleDelete">删除</el-button>
      </div>
      <PIMTable
          rowKey="id"
          :column="tableColumn"
          :tableData="tableData"
          :tableLoading="tableLoading"
          :isSelection="true"
          @selection-change="handleSelectionChange"
          height="600"
      >
        <template #slot="{ row }">
          <el-input v-model="row.testValue" clearable/>
        </template>
      </PIMTable>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确认</el-button>
          <el-button @click="closeDia">取消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import {ref} from "vue";
import {getStaffJoinInfo, staffJoinAdd, staffJoinUpdate} from "@/api/personnelManagement/onboarding.js";
import {Search} from "@element-plus/icons-vue";
import {
  qualityInspectParamDel,
  qualityInspectParamInfo,
  qualityInspectParamUpdate
} from "@/api/qualityManagement/qualityInspectParam.js";
import {ElMessageBox} from "element-plus";
const { proxy } = getCurrentInstance()
const emit = defineEmits(['close'])
const dialogFormVisible = ref(false);
const operationType = ref('')
const currentId = ref('')
const selectedRows = ref([]);
const tableColumn = ref([
  {
    label: "指标",
    prop: "parameterItem",
  },
  {
    label: "单位",
    prop: "unit",
  },
  {
    label: "标准值",
    prop: "standardValue",
  },
  {
    label: "内控值",
    prop: "controlValue",
  },
  {
    label: "检验值",
    prop: "testValue",
    dataType: 'slot',
    slot: 'slot',
  },
]);
const tableData = ref([]);
const tableLoading = ref(false);
// æ‰“开弹框
const openDialog = (type, row) => {
  operationType.value = type;
  dialogFormVisible.value = true;
  if (operationType.value === 'edit') {
    currentId.value = row.id;
    getList()
  }
}
const getList = () => {
  qualityInspectParamInfo(currentId.value).then(res => {
    tableData.value = res.data;
  })
}
// è¡¨æ ¼é€‰æ‹©æ•°æ®
const handleSelectionChange = (selection) => {
  selectedRows.value = selection;
};
// æäº¤äº§å“è¡¨å•
const submitForm = () => {
  qualityInspectParamUpdate(tableData.value).then(res => {
    proxy.$modal.msgSuccess("提交成功");
    closeDia();
  })
}
// å…³é—­å¼¹æ¡†
const closeDia = () => {
  dialogFormVisible.value = false;
  emit('close')
};
// åˆ é™¤
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(() => {
        qualityInspectParamDel(ids).then((res) => {
          proxy.$modal.msgSuccess("删除成功");
          getList();
        });
      })
      .catch(() => {
        proxy.$modal.msg("已取消");
      });
};
defineExpose({
  openDialog,
});
</script>
<style scoped>
</style>
src/views/qualityManagement/finalInspection/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,236 @@
<template>
  <div class="app-container">
    <div class="search_form">
      <div>
        <span class="search_title">产品名称:</span>
        <el-input
            v-model="searchForm.productName"
            style="width: 240px"
            placeholder="请输入产品名称搜索"
            @change="handleQuery"
            clearable
            :prefix-icon="Search"
        />
        <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
        >搜索</el-button
        >
      </div>
      <div>
        <el-button type="primary" @click="openForm('add')">新增</el-button>
        <el-button @click="handleOut">导出</el-button>
        <el-button type="danger" plain @click="handleDelete">删除</el-button>
      </div>
    </div>
    <div class="table_list">
      <PIMTable
          rowKey="id"
          :column="tableColumn"
          :tableData="tableData"
          :page="page"
          :isSelection="true"
          @selection-change="handleSelectionChange"
          :tableLoading="tableLoading"
          @pagination="pagination"
          :total="page.total"
      ></PIMTable>
    </div>
    <InspectionFormDia ref="inspectionFormDia" @close="handleQuery"></InspectionFormDia>
    <FormDia ref="formDia" @close="handleQuery"></FormDia>
    <files-dia ref="filesDia" @close="handleQuery"></files-dia>
  </div>
</template>
<script setup>
import { Search } from "@element-plus/icons-vue";
import {onMounted, ref} from "vue";
import InspectionFormDia from "@/views/qualityManagement/finalInspection/components/inspectionFormDia.vue";
import FormDia from "@/views/qualityManagement/finalInspection/components/formDia.vue";
import {ElMessageBox} from "element-plus";
import {qualityInspectDel, qualityInspectListPage} from "@/api/qualityManagement/rawMaterialInspection.js";
import FilesDia from "@/views/qualityManagement/finalInspection/components/filesDia.vue";
const data = reactive({
  searchForm: {
    productName: "",
  },
});
const { searchForm } = toRefs(data);
const tableColumn = ref([
  {
    label: "检测日期",
    prop: "checkTime",
    width: 120
  },
  {
    label: "检验员",
    prop: "checkName",
  },
  {
    label: "产品名称",
    prop: "productName",
  },
  {
    label: "规格型号",
    prop: "model",
  },
  {
    label: "单位",
    prop: "unit",
  },
  {
    label: "数量",
    prop: "quantity",
    width: 100
  },
  {
    label: "检测单位",
    prop: "checkCompany",
    width: 120
  },
  {
    label: "检测结果",
    prop: "checkResult",
    dataType: "tag",
    formatType: (params) => {
      if (params == '不合格') {
        return "danger";
      } else if (params == '合格') {
        return "success";
      } else {
        return null;
      }
    },
  },
  {
    dataType: "action",
    label: "操作",
    align: "center",
    fixed: "right",
    width: 190,
    operation: [
      {
        name: "编辑",
        type: "text",
        clickFun: (row) => {
          openForm("edit", row);
        },
      },
      {
        name: "新增检验记录",
        type: "text",
        clickFun: (row) => {
          openInspectionForm("edit", row);
        },
      },
      {
        name: "附件",
        type: "text",
        clickFun: (row) => {
          openFilesFormDia(row);
        },
      },
    ],
  },
]);
const tableData = ref([]);
const selectedRows = ref([]);
const tableLoading = ref(false);
const page = reactive({
  current: 1,
  size: 100,
  total: 0
});
const formDia = ref()
const filesDia = ref()
const inspectionFormDia = ref()
const { proxy } = getCurrentInstance()
// æŸ¥è¯¢åˆ—表
/** æœç´¢æŒ‰é’®æ“ä½œ */
const handleQuery = () => {
  page.current = 1;
  getList();
};
const pagination = (obj) => {
  page.current = obj.page;
  page.size = obj.limit;
  getList();
};
const getList = () => {
  tableLoading.value = true;
  qualityInspectListPage({...page, ...searchForm.value, inspectType: 2}).then(res => {
    tableLoading.value = false;
    tableData.value = res.data.records
    page.total = res.data.total;
  }).catch(err => {
    tableLoading.value = false;
  })
};
// è¡¨æ ¼é€‰æ‹©æ•°æ®
const handleSelectionChange = (selection) => {
  selectedRows.value = selection;
};
// æ‰“开弹框
const openForm = (type, row) => {
  nextTick(() => {
    formDia.value?.openDialog(type, row)
  })
};
// æ‰“开新增检验弹框
const openInspectionForm = (type, row) => {
  nextTick(() => {
    inspectionFormDia.value?.openDialog(type, row)
  })
};
// æ‰“开附件弹框
const openFilesFormDia = (type, row) => {
  nextTick(() => {
    filesDia.value?.openDialog(type, row)
  })
};
// åˆ é™¤
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(() => {
        qualityInspectDel(ids).then((res) => {
          proxy.$modal.msgSuccess("删除成功");
          getList();
        });
      })
      .catch(() => {
        proxy.$modal.msg("已取消");
      });
};
// å¯¼å‡º
const handleOut = () => {
  ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  })
      .then(() => {
        proxy.download("/quality/qualityInspect/export", {inspectType: 2}, "过程检验.xlsx");
      })
      .catch(() => {
        proxy.$modal.msg("已取消");
      });
};
onMounted(() => {
  getList();
});
</script>
<style scoped></style>
src/views/qualityManagement/metricMaintenance/index.vue
@@ -317,14 +317,13 @@
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  })
      .then(() => {
        proxy.download("/quality/qualityTestStandard/export", {}, "检测指标.xlsx");
      })
      .catch(() => {
        proxy.$modal.msg("已取消");
      });
  }).then(() => {
    proxy.download("/quality/qualityTestStandard/export", {}, "检测指标.xlsx");
  }).catch(() => {
    proxy.$modal.msg("已取消");
  });
};
// åˆ é™¤æŒ‡æ ‡
const handleDelete = () => {
  let ids = [];
src/views/qualityManagement/nonconformingManagement/components/formDia.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,249 @@
<template>
  <div>
    <el-dialog
        v-model="dialogFormVisible"
        :title="operationType === 'add' ? '新增原材料检验' : '编辑原材料检验'"
        width="70%"
        @close="closeDia"
    >
      <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="状态:" prop="inspectState">
              <el-select v-model="form.inspectState">
                <el-option label="待处理" :value="0" />
                <el-option label="已处理" :value="1" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="类别:" prop="inspectType">
              <el-select v-model="form.inspectType">
                <el-option label="原材料检验" :value="0" />
                <el-option label="过程检验" :value="1" />
                <el-option label="出厂检验" :value="2" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="产品名称:" prop="productId">
              <el-tree-select
                  v-model="form.productId"
                  placeholder="请选择"
                  clearable
                  check-strictly
                  @change="getModels"
                  :data="productOptions"
                  :render-after-expand="false"
                  style="width: 100%"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="规格型号:" prop="model">
              <el-input v-model="form.model" placeholder="请输入" clearable/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="单位:" prop="unit">
              <el-input v-model="form.unit" placeholder="请输入" clearable/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="数量:" prop="quantity">
              <el-input v-model="form.quantity" placeholder="请输入" clearable/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="检验员:" prop="checkName">
              <el-input v-model="form.checkName" placeholder="请输入" clearable/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="检测日期:" prop="checkTime">
              <el-date-picker
                  v-model="form.checkTime"
                  type="date"
                  placeholder="请选择日期"
                  value-format="YYYY-MM-DD"
                  format="YYYY-MM-DD"
                  clearable
                  style="width: 100%"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="不合格现象:" prop="defectivePhenomena">
              <el-input v-model="form.defectivePhenomena" placeholder="请输入" clearable/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="处理结果:" prop="dealResult">
              <el-input v-model="form.dealResult" placeholder="请输入" clearable/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="处理人:" prop="dealName">
              <el-input v-model="form.dealName" placeholder="请输入" clearable/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="处理日期:" prop="dealTime">
              <el-date-picker
                  v-model="form.dealTime"
                  type="date"
                  placeholder="请选择日期"
                  value-format="YYYY-MM-DD"
                  format="YYYY-MM-DD"
                  clearable
                  style="width: 100%"
              />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确认</el-button>
          <el-button @click="closeDia">取消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import {ref} from "vue";
import {productTreeList} from "@/api/basicData/product.js";
import {
  getQualityUnqualifiedInfo,
  qualityUnqualifiedAdd,
  qualityUnqualifiedUpdate
} from "@/api/qualityManagement/nonconformingManagement.js";
const { proxy } = getCurrentInstance()
const emit = defineEmits(['close'])
const dialogFormVisible = ref(false);
const operationType = ref('')
const data = reactive({
  form: {
    checkTime: "",
    process: "",
    checkName: "",
    productName: "",
    productId: "",
    model: "",
    unit: "",
    quantity: "",
    checkCompany: "",
    checkResult: "",
    inspectState: '',
    inspectType: '',
    defectivePhenomena: '',
    dealResult: '',
  },
  rules: {
    checkTime: [{ required: false, message: "请输入", trigger: "blur" },],
    process: [{ required: true, message: "请输入", trigger: "blur" }],
    checkName: [{ required: false, message: "请输入", trigger: "blur" }],
    productId: [{ required: true, message: "请输入", trigger: "blur" }],
    model: [{ required: false, message: "请输入", trigger: "blur" }],
    unit: [{ required: false, message: "请输入", trigger: "blur" }],
    quantity: [{ required: true, message: "请输入", trigger: "blur" }],
    checkCompany: [{ required: false, message: "请输入", trigger: "blur" }],
    checkResult: [{ required: false, message: "请输入", trigger: "blur" }],
  },
});
const { form, rules } = toRefs(data);
const productOptions = ref([]);
// æ‰“开弹框
const openDialog = (type, row) => {
  operationType.value = type;
  dialogFormVisible.value = true;
  form.value = {}
  getProductOptions();
  if (operationType.value === 'edit') {
    getQualityUnqualifiedInfo(row.id).then(res => {
      form.value = {...res.data}
    })
  }
}
const getProductOptions = () => {
  productTreeList().then((res) => {
    productOptions.value = convertIdToValue(res);
  });
};
const getModels = (value) => {
  form.value.productName = findNodeById(productOptions.value, value);
};
const findNodeById = (nodes, productId) => {
  for (let i = 0; i < nodes.length; i++) {
    if (nodes[i].value === productId) {
      return nodes[i].label; // æ‰¾åˆ°èŠ‚ç‚¹ï¼Œè¿”å›žè¯¥èŠ‚ç‚¹
    }
    if (nodes[i].children && nodes[i].children.length > 0) {
      const foundNode = findNodeById(nodes[i].children, productId);
      if (foundNode) {
        return foundNode; // åœ¨å­èŠ‚ç‚¹ä¸­æ‰¾åˆ°ï¼Œè¿”å›žè¯¥èŠ‚ç‚¹
      }
    }
  }
  return null; // æ²¡æœ‰æ‰¾åˆ°èŠ‚ç‚¹ï¼Œè¿”å›žnull
};
function convertIdToValue(data) {
  return data.map((item) => {
    const { id, children, ...rest } = item;
    const newItem = {
      ...rest,
      value: id, // å°† id æ”¹ä¸º value
    };
    if (children && children.length > 0) {
      newItem.children = convertIdToValue(children);
    }
    return newItem;
  });
}
// æäº¤äº§å“è¡¨å•
const submitForm = () => {
  proxy.$refs.formRef.validate(valid => {
    if (valid) {
      if (operationType.value === "add") {
        qualityUnqualifiedAdd(form.value).then(res => {
          proxy.$modal.msgSuccess("提交成功");
          closeDia();
        })
      } else {
        qualityUnqualifiedUpdate(form.value).then(res => {
          proxy.$modal.msgSuccess("提交成功");
          closeDia();
        })
      }
    }
  })
}
// å…³é—­å¼¹æ¡†
const closeDia = () => {
  proxy.resetForm("formRef");
  dialogFormVisible.value = false;
  emit('close')
};
defineExpose({
  openDialog,
});
</script>
<style scoped>
</style>
src/views/qualityManagement/nonconformingManagement/components/inspectionFormDia.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,257 @@
<template>
  <div>
    <el-dialog
        v-model="dialogFormVisible"
        :title="operationType === 'add' ? '新增原材料检验' : '编辑原材料检验'"
        width="70%"
        @close="closeDia"
    >
      <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="状态:" prop="inspectState">
              <el-select v-model="form.inspectState">
                <el-option label="待处理" :value="0" />
                <el-option label="已处理" :value="1" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="类别:" prop="inspectType">
              <el-select v-model="form.inspectType" disabled>
                <el-option label="原材料检验" :value="0" />
                <el-option label="过程检验" :value="1" />
                <el-option label="出厂检验" :value="2" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="产品名称:" prop="productId">
              <el-tree-select
                  v-model="form.productId"
                  placeholder="请选择"
                  clearable
                  disabled
                  check-strictly
                  @change="getModels"
                  :data="productOptions"
                  :render-after-expand="false"
                  style="width: 100%"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="规格型号:" prop="model">
              <el-input v-model="form.model" placeholder="请输入" clearable disabled/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="单位:" prop="unit">
              <el-input v-model="form.unit" placeholder="请输入" clearable disabled/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="数量:" prop="quantity">
              <el-input v-model="form.quantity" placeholder="请输入" clearable disabled/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="检验员:" prop="checkName">
              <el-input v-model="form.checkName" placeholder="请输入" clearable disabled/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="检测日期:" prop="checkTime">
              <el-date-picker
                  v-model="form.checkTime"
                  type="date"
                  disabled
                  placeholder="请选择日期"
                  value-format="YYYY-MM-DD"
                  format="YYYY-MM-DD"
                  clearable
                  style="width: 100%"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="不合格现象:" prop="defectivePhenomena">
              <el-input v-model="form.defectivePhenomena" placeholder="请输入" clearable/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="处理结果:" prop="dealResult">
              <el-input v-model="form.dealResult" placeholder="请输入" clearable/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="处理人:" prop="dealName">
              <el-input v-model="form.dealName" placeholder="请输入" clearable/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="处理日期:" prop="dealTime">
              <el-date-picker
                  v-model="form.dealTime"
                  type="date"
                  placeholder="请选择日期"
                  value-format="YYYY-MM-DD"
                  format="YYYY-MM-DD"
                  clearable
                  style="width: 100%"
              />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确认</el-button>
          <el-button @click="closeDia">取消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import {ref} from "vue";
import {productTreeList} from "@/api/basicData/product.js";
import {
  getQualityUnqualifiedInfo,
  qualityUnqualifiedAdd,
  qualityUnqualifiedUpdate
} from "@/api/qualityManagement/nonconformingManagement.js";
const { proxy } = getCurrentInstance()
const emit = defineEmits(['close'])
const dialogFormVisible = ref(false);
const operationType = ref('')
const data = reactive({
  form: {
    checkTime: "",
    process: "",
    checkName: "",
    productName: "",
    productId: "",
    model: "",
    unit: "",
    quantity: "",
    checkCompany: "",
    checkResult: "",
    inspectState: '',
    inspectType: '',
    defectivePhenomena: '',
    dealResult: '',
    dealName: '',
    dealTime: '',
  },
  rules: {
    checkTime: [{ required: false, message: "请输入", trigger: "blur" },],
    process: [{ required: false, message: "请输入", trigger: "blur" }],
    checkName: [{ required: false, message: "请输入", trigger: "blur" }],
    productId: [{ required: false, message: "请输入", trigger: "blur" }],
    model: [{ required: false, message: "请输入", trigger: "blur" }],
    unit: [{ required: false, message: "请输入", trigger: "blur" }],
    quantity: [{ required: false, message: "请输入", trigger: "blur" }],
    checkCompany: [{ required: false, message: "请输入", trigger: "blur" }],
    checkResult: [{ required: false, message: "请输入", trigger: "blur" }],
    defectivePhenomena: [{ required: true, message: "请输入", trigger: "blur" }],
    dealResult: [{ required: true, message: "请输入", trigger: "blur" }],
    dealName: [{ required: true, message: "请输入", trigger: "blur" }],
    dealTime: [{ required: true, message: "请输入", trigger: "change" }],
  },
});
const { form, rules } = toRefs(data);
const productOptions = ref([]);
// æ‰“开弹框
const openDialog = (type, row) => {
  operationType.value = type;
  dialogFormVisible.value = true;
  form.value = {}
  getProductOptions();
  if (operationType.value === 'edit') {
    getQualityUnqualifiedInfo(row.id).then(res => {
      form.value = {...res.data}
    })
  }
}
const getProductOptions = () => {
  productTreeList().then((res) => {
    productOptions.value = convertIdToValue(res);
  });
};
const getModels = (value) => {
  form.value.productName = findNodeById(productOptions.value, value);
};
const findNodeById = (nodes, productId) => {
  for (let i = 0; i < nodes.length; i++) {
    if (nodes[i].value === productId) {
      return nodes[i].label; // æ‰¾åˆ°èŠ‚ç‚¹ï¼Œè¿”å›žè¯¥èŠ‚ç‚¹
    }
    if (nodes[i].children && nodes[i].children.length > 0) {
      const foundNode = findNodeById(nodes[i].children, productId);
      if (foundNode) {
        return foundNode; // åœ¨å­èŠ‚ç‚¹ä¸­æ‰¾åˆ°ï¼Œè¿”å›žè¯¥èŠ‚ç‚¹
      }
    }
  }
  return null; // æ²¡æœ‰æ‰¾åˆ°èŠ‚ç‚¹ï¼Œè¿”å›žnull
};
function convertIdToValue(data) {
  return data.map((item) => {
    const { id, children, ...rest } = item;
    const newItem = {
      ...rest,
      value: id, // å°† id æ”¹ä¸º value
    };
    if (children && children.length > 0) {
      newItem.children = convertIdToValue(children);
    }
    return newItem;
  });
}
// æäº¤äº§å“è¡¨å•
const submitForm = () => {
  proxy.$refs.formRef.validate(valid => {
    if (valid) {
      if (operationType.value === "add") {
        qualityUnqualifiedAdd(form.value).then(res => {
          proxy.$modal.msgSuccess("提交成功");
          closeDia();
        })
      } else {
        qualityUnqualifiedUpdate(form.value).then(res => {
          proxy.$modal.msgSuccess("提交成功");
          closeDia();
        })
      }
    }
  })
}
// å…³é—­å¼¹æ¡†
const closeDia = () => {
  proxy.resetForm("formRef");
  dialogFormVisible.value = false;
  emit('close')
};
defineExpose({
  openDialog,
});
</script>
<style scoped>
</style>
src/views/qualityManagement/nonconformingManagement/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,285 @@
<template>
  <div class="app-container">
    <div class="search_form">
      <div style="display: flex;flex-direction: row;align-items: center;">
        <div>
          <span class="search_title">类型:</span>
          <el-select v-model="searchForm.inspectType" clearable style="width: 240px" @change="handleQuery">
            <el-option label="原材料检验" :value="0" />
            <el-option label="过程检验" :value="1" />
            <el-option label="出厂检验" :value="2" />
          </el-select>
        </div>
        <div style="margin-left: 10px">
          <span class="search_title">状态:</span>
          <el-select v-model="searchForm.inspectState" clearable style="width: 240px" @change="handleQuery">
            <el-option label="待处理" :value="0" />
            <el-option label="已处理" :value="1" />
          </el-select>
        </div>
        <div style="margin-left: 10px">
          <span class="search_title">产品名称:</span>
          <el-input
              v-model="searchForm.productName"
              style="width: 240px"
              placeholder="请输入产品名称搜索"
              @change="handleQuery"
              clearable
              :prefix-icon="Search"
          />
        </div>
        <el-button type="primary" @click="handleQuery" style="margin-left: 10px">搜索</el-button>
      </div>
      <div>
        <el-button type="primary" @click="openForm('add')">新增</el-button>
        <el-button @click="handleOut">导出</el-button>
        <el-button type="danger" plain @click="handleDelete">删除</el-button>
      </div>
    </div>
    <div class="table_list">
      <PIMTable
          rowKey="id"
          :column="tableColumn"
          :tableData="tableData"
          :page="page"
          :isSelection="true"
          @selection-change="handleSelectionChange"
          :tableLoading="tableLoading"
          @pagination="pagination"
          :total="page.total"
      ></PIMTable>
    </div>
    <FormDia ref="formDia" @close="handleQuery"></FormDia>
    <InspectionFormDia ref="inspectionFormDia" @close="handleQuery"></InspectionFormDia>
  </div>
</template>
<script setup>
import { Search } from "@element-plus/icons-vue";
import {onMounted, ref} from "vue";
import FormDia from "@/views/qualityManagement/nonconformingManagement/components/formDia.vue";
import {ElMessageBox} from "element-plus";
import {qualityUnqualifiedDel, qualityUnqualifiedListPage} from "@/api/qualityManagement/nonconformingManagement.js";
import InspectionFormDia from "@/views/qualityManagement/nonconformingManagement/components/inspectionFormDia.vue";
const data = reactive({
  searchForm: {
    inspectType: "",
    inspectState: "",
    productName: "",
  },
});
const { searchForm } = toRefs(data);
const tableColumn = ref([
  {
    label: "状态",
    prop: "inspectState",
    dataType: "tag",
    formatData: (params) => {
      if (params == 0) {
        return "待处理";
      } else if (params == 1) {
        return "已处理";
      } else {
        return null;
      }
    },
    formatType: (params) => {
      if (params == '不合格') {
        return "danger";
      } else if (params == '合格') {
        return "success";
      } else {
        return null;
      }
    },
  },
  {
    label: "检测日期",
    prop: "checkTime",
    width: 120
  },
  {
    label: "类别",
    prop: "inspectType",
    dataType: "tag",
    width: 120,
    formatData: (params) => {
      if (params == 0) {
        return "原材料检验";
      } else if (params == 1) {
        return "过程检验";
      } else {
        return '出厂检验';
      }
    },
    formatType: (params) => {
      if (params == '不合格') {
        return "info";
      } else if (params == '合格') {
        return "success";
      } else {
        return 'primary';
      }
    },
  },
  {
    label: "检验员",
    prop: "checkName",
  },
  {
    label: "产品名称",
    prop: "productName",
  },
  {
    label: "规格型号",
    prop: "model",
  },
  {
    label: "单位",
    prop: "unit",
  },
  {
    label: "数量",
    prop: "quantity",
    width: 100
  },
  {
    label: "不合格现象",
    prop: "defectivePhenomena",
    width: 120
  },
  {
    label: "处理结果",
    prop: "dealResult",
    width: 120
  },
  {
    label: "处理人",
    prop: "dealName",
    width: 120
  },
  {
    label: "处理日期",
    prop: "dealTime",
    width: 120
  },
  {
    dataType: "action",
    label: "操作",
    align: "center",
    fixed: "right",
    width: 120,
    operation: [
      {
        name: "编辑",
        type: "text",
        clickFun: (row) => {
          openForm("edit", row);
        },
      },
      {
        name: "处理",
        type: "text",
        clickFun: (row) => {
          openInspectionForm("edit", row);
        },
      },
    ],
  },
]);
const tableData = ref([]);
const selectedRows = ref([]);
const tableLoading = ref(false);
const page = reactive({
  current: 1,
  size: 100,
  total: 0
});
const formDia = ref()
const inspectionFormDia = ref()
const { proxy } = getCurrentInstance()
// æŸ¥è¯¢åˆ—表
/** æœç´¢æŒ‰é’®æ“ä½œ */
const handleQuery = () => {
  page.current = 1;
  getList();
};
const pagination = (obj) => {
  page.current = obj.page;
  page.size = obj.limit;
  getList();
};
const getList = () => {
  tableLoading.value = true;
  qualityUnqualifiedListPage({...page, ...searchForm.value}).then(res => {
    tableLoading.value = false;
    tableData.value = res.data.records
    page.total = res.data.total;
  }).catch(err => {
    tableLoading.value = false;
  })
};
// è¡¨æ ¼é€‰æ‹©æ•°æ®
const handleSelectionChange = (selection) => {
  selectedRows.value = selection;
};
// æ‰“开弹框
const openForm = (type, row) => {
  nextTick(() => {
    formDia.value?.openDialog(type, row)
  })
};
// æ‰“开处理弹框
const openInspectionForm = (type, row) => {
  nextTick(() => {
    inspectionFormDia.value?.openDialog(type, row)
  })
};
// åˆ é™¤
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(() => {
        qualityUnqualifiedDel(ids).then((res) => {
          proxy.$modal.msgSuccess("删除成功");
          getList();
        });
      })
      .catch(() => {
        proxy.$modal.msg("已取消");
      });
};
// å¯¼å‡º
const handleOut = () => {
  ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  })
      .then(() => {
        proxy.download("/quality/qualityUnqualified/export", {}, "不合格管理.xlsx");
      })
      .catch(() => {
        proxy.$modal.msg("已取消");
      });
};
onMounted(() => {
  getList();
});
</script>
<style scoped></style>
src/views/qualityManagement/processInspection/components/filesDia.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,178 @@
<template>
  <div>
    <el-dialog
        v-model="dialogFormVisible"
        title="上传附件"
        width="50%"
        @close="closeDia"
    >
      <div style="margin-bottom: 10px;text-align: right">
        <el-upload
            v-model:file-list="fileList"
            class="upload-demo"
            :action="uploadUrl"
            :on-success="handleUploadSuccess"
            :on-error="handleUploadError"
            name="file"
            :show-file-list="false"
            :headers="headers"
            style="display: inline;margin-right: 10px"
        >
          <el-button type="primary">上传附件</el-button>
        </el-upload>
        <el-button type="danger" plain @click="handleDelete">删除</el-button>
      </div>
      <PIMTable
          rowKey="id"
          :column="tableColumn"
          :tableData="tableData"
          :tableLoading="tableLoading"
          :isSelection="true"
          @selection-change="handleSelectionChange"
          height="600"
      >
      </PIMTable>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="closeDia">取消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import {ref} from "vue";
import {getStaffJoinInfo, staffJoinAdd, staffJoinUpdate} from "@/api/personnelManagement/onboarding.js";
import {Search} from "@element-plus/icons-vue";
import {
  qualityInspectParamDel,
  qualityInspectParamInfo,
  qualityInspectParamUpdate
} from "@/api/qualityManagement/qualityInspectParam.js";
import {ElMessageBox} from "element-plus";
import {getToken} from "@/utils/auth.js";
import {
  qualityInspectFileAdd,
  qualityInspectFileDel,
  qualityInspectFileListPage
} from "@/api/qualityManagement/qualityInspectFile.js";
const { proxy } = getCurrentInstance()
const emit = defineEmits(['close'])
const dialogFormVisible = ref(false);
const currentId = ref('')
const selectedRows = ref([]);
const tableColumn = ref([
  {
    label: "文件名称",
    prop: "name",
  },
  // {
  //   label: "上传人",
  //   prop: "createUser",
  // },
  // {
  //   label: "上传时间",
  //   prop: "createTime",
  // },
  {
    dataType: "action",
    label: "操作",
    align: "center",
    operation: [
      {
        name: "下载",
        type: "text",
        clickFun: (row) => {
          downLoadFile(row);
        },
      }
    ],
  },
]);
const tableData = ref([]);
const fileList = ref([]);
const tableLoading = ref(false);
const headers = ref({
  Authorization: "Bearer " + getToken(),
});
const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + "/file/upload"); // ä¸Šä¼ çš„图片服务器地址
// æ‰“开弹框
const openDialog = (row) => {
  dialogFormVisible.value = true;
  currentId.value = row.id;
  getList()
}
const getList = () => {
  qualityInspectFileListPage({inspectId: currentId.value}).then(res => {
    tableData.value = res.data.records;
  })
}
// è¡¨æ ¼é€‰æ‹©æ•°æ®
const handleSelectionChange = (selection) => {
  selectedRows.value = selection;
};
// ä¸‹è½½é™„ä»¶
const downLoadFile = (row) => {
  proxy.$download.name(row.url);
}
// å…³é—­å¼¹æ¡†
const closeDia = () => {
  dialogFormVisible.value = false;
  emit('close')
};
// ä¸Šä¼ æˆåŠŸå¤„ç†
function handleUploadSuccess(res, file) {
  // å¦‚果上传成功
  if (res.code == 200) {
    const fileRow = {}
    fileRow.name = res.data.originalName
    fileRow.url = res.data.tempPath
    uploadFile(fileRow)
  } else {
    proxy.$modal.msgError("文件上传失败");
  }
}
function uploadFile(file) {
  file.inspectId = currentId.value;
  qualityInspectFileAdd(file).then(res => {
    proxy.$modal.msgSuccess("文件上传成功");
    getList()
  })
}
// ä¸Šä¼ å¤±è´¥å¤„理
function handleUploadError() {
  proxy.$modal.msgError("文件上传失败");
}
// åˆ é™¤
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(() => {
    qualityInspectFileDel(ids).then((res) => {
      proxy.$modal.msgSuccess("删除成功");
      getList();
    });
  }).catch(() => {
    proxy.$modal.msg("已取消");
  });
};
defineExpose({
  openDialog,
});
</script>
<style scoped>
</style>
src/views/qualityManagement/processInspection/components/formDia.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,216 @@
<template>
  <div>
    <el-dialog
        v-model="dialogFormVisible"
        :title="operationType === 'add' ? '新增原材料检验' : '编辑原材料检验'"
        width="70%"
        @close="closeDia"
    >
      <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="工序:" prop="process">
              <el-input v-model="form.process" placeholder="请输入" clearable/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="产品名称:" prop="productId">
              <el-tree-select
                  v-model="form.productId"
                  placeholder="请选择"
                  clearable
                  check-strictly
                  @change="getModels"
                  :data="productOptions"
                  :render-after-expand="false"
                  style="width: 100%"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="规格型号:" prop="model">
              <el-input v-model="form.model" placeholder="请输入" clearable/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="单位:" prop="unit">
              <el-input v-model="form.unit" placeholder="请输入" clearable/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="数量:" prop="quantity">
              <el-input v-model="form.quantity" placeholder="请输入" clearable/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="检测单位:" prop="checkCompany">
              <el-input v-model="form.checkCompany" placeholder="请输入" clearable/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="检测结果:" prop="checkResult">
              <el-select v-model="form.checkResult">
                <el-option label="合格" value="合格" />
                <el-option label="不合格" value="不合格" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="检验员:" prop="checkName">
              <el-input v-model="form.checkName" placeholder="请输入" clearable/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="检测日期:" prop="checkTime">
              <el-date-picker
                  v-model="form.checkTime"
                  type="date"
                  placeholder="请选择日期"
                  value-format="YYYY-MM-DD"
                  format="YYYY-MM-DD"
                  clearable
                  style="width: 100%"
              />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确认</el-button>
          <el-button @click="closeDia">取消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import {ref} from "vue";
import {getOptions} from "@/api/procurementManagement/procurementLedger.js";
import {productTreeList} from "@/api/basicData/product.js";
import {qualityInspectAdd, qualityInspectUpdate} from "@/api/qualityManagement/rawMaterialInspection.js";
const { proxy } = getCurrentInstance()
const emit = defineEmits(['close'])
const dialogFormVisible = ref(false);
const operationType = ref('')
const data = reactive({
  form: {
    checkTime: "",
    process: "",
    checkName: "",
    productName: "",
    productId: "",
    model: "",
    unit: "",
    quantity: "",
    checkCompany: "",
    checkResult: "",
  },
  rules: {
    checkTime: [{ required: false, message: "请输入", trigger: "blur" },],
    process: [{ required: true, message: "请输入", trigger: "blur" }],
    checkName: [{ required: false, message: "请输入", trigger: "blur" }],
    productId: [{ required: true, message: "请输入", trigger: "blur" }],
    model: [{ required: false, message: "请输入", trigger: "blur" }],
    unit: [{ required: false, message: "请输入", trigger: "blur" }],
    quantity: [{ required: true, message: "请输入", trigger: "blur" }],
    checkCompany: [{ required: false, message: "请输入", trigger: "blur" }],
    checkResult: [{ required: false, message: "请输入", trigger: "blur" }],
  },
});
const { form, rules } = toRefs(data);
const supplierList = ref([]);
const productOptions = ref([]);
// æ‰“开弹框
const openDialog = (type, row) => {
  operationType.value = type;
  dialogFormVisible.value = true;
  getOptions().then((res) => {
    supplierList.value = res.data;
  });
  getProductOptions();
  if (operationType.value === 'edit') {
    form.value = {...row}
  }
}
const getProductOptions = () => {
  productTreeList().then((res) => {
    productOptions.value = convertIdToValue(res);
  });
};
const getModels = (value) => {
  form.value.productName = findNodeById(productOptions.value, value);
};
const findNodeById = (nodes, productId) => {
  for (let i = 0; i < nodes.length; i++) {
    if (nodes[i].value === productId) {
      return nodes[i].label; // æ‰¾åˆ°èŠ‚ç‚¹ï¼Œè¿”å›žè¯¥èŠ‚ç‚¹
    }
    if (nodes[i].children && nodes[i].children.length > 0) {
      const foundNode = findNodeById(nodes[i].children, productId);
      if (foundNode) {
        return foundNode; // åœ¨å­èŠ‚ç‚¹ä¸­æ‰¾åˆ°ï¼Œè¿”å›žè¯¥èŠ‚ç‚¹
      }
    }
  }
  return null; // æ²¡æœ‰æ‰¾åˆ°èŠ‚ç‚¹ï¼Œè¿”å›žnull
};
function convertIdToValue(data) {
  return data.map((item) => {
    const { id, children, ...rest } = item;
    const newItem = {
      ...rest,
      value: id, // å°† id æ”¹ä¸º value
    };
    if (children && children.length > 0) {
      newItem.children = convertIdToValue(children);
    }
    return newItem;
  });
}
// æäº¤äº§å“è¡¨å•
const submitForm = () => {
  proxy.$refs.formRef.validate(valid => {
    if (valid) {
      form.value.inspectType = 1
      if (operationType.value === "add") {
        qualityInspectAdd(form.value).then(res => {
          proxy.$modal.msgSuccess("提交成功");
          closeDia();
        })
      } else {
        qualityInspectUpdate(form.value).then(res => {
          proxy.$modal.msgSuccess("提交成功");
          closeDia();
        })
      }
    }
  })
}
// å…³é—­å¼¹æ¡†
const closeDia = () => {
  proxy.resetForm("formRef");
  dialogFormVisible.value = false;
  emit('close')
};
defineExpose({
  openDialog,
});
</script>
<style scoped>
</style>
src/views/qualityManagement/processInspection/components/inspectionFormDia.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,140 @@
<template>
  <div>
    <el-dialog
        v-model="dialogFormVisible"
        title="填写检验记录"
        width="70%"
        @close="closeDia"
    >
      <div style="margin-bottom: 10px;text-align: right">
        <el-button type="danger" plain @click="handleDelete">删除</el-button>
      </div>
      <PIMTable
          rowKey="id"
          :column="tableColumn"
          :tableData="tableData"
          :tableLoading="tableLoading"
          :isSelection="true"
          @selection-change="handleSelectionChange"
          height="600"
      >
        <template #slot="{ row }">
          <el-input v-model="row.testValue" clearable/>
        </template>
      </PIMTable>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确认</el-button>
          <el-button @click="closeDia">取消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import {ref} from "vue";
import {getStaffJoinInfo, staffJoinAdd, staffJoinUpdate} from "@/api/personnelManagement/onboarding.js";
import {Search} from "@element-plus/icons-vue";
import {
  qualityInspectParamDel,
  qualityInspectParamInfo,
  qualityInspectParamUpdate
} from "@/api/qualityManagement/qualityInspectParam.js";
import {ElMessageBox} from "element-plus";
const { proxy } = getCurrentInstance()
const emit = defineEmits(['close'])
const dialogFormVisible = ref(false);
const operationType = ref('')
const currentId = ref('')
const selectedRows = ref([]);
const tableColumn = ref([
  {
    label: "指标",
    prop: "parameterItem",
  },
  {
    label: "单位",
    prop: "unit",
  },
  {
    label: "标准值",
    prop: "standardValue",
  },
  {
    label: "内控值",
    prop: "controlValue",
  },
  {
    label: "检验值",
    prop: "testValue",
    dataType: 'slot',
    slot: 'slot',
  },
]);
const tableData = ref([]);
const tableLoading = ref(false);
// æ‰“开弹框
const openDialog = (type, row) => {
  operationType.value = type;
  dialogFormVisible.value = true;
  if (operationType.value === 'edit') {
    currentId.value = row.id;
    getList()
  }
}
const getList = () => {
  qualityInspectParamInfo(currentId.value).then(res => {
    tableData.value = res.data;
  })
}
// è¡¨æ ¼é€‰æ‹©æ•°æ®
const handleSelectionChange = (selection) => {
  selectedRows.value = selection;
};
// æäº¤äº§å“è¡¨å•
const submitForm = () => {
  qualityInspectParamUpdate(tableData.value).then(res => {
    proxy.$modal.msgSuccess("提交成功");
    closeDia();
  })
}
// å…³é—­å¼¹æ¡†
const closeDia = () => {
  dialogFormVisible.value = false;
  emit('close')
};
// åˆ é™¤
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(() => {
        qualityInspectParamDel(ids).then((res) => {
          proxy.$modal.msgSuccess("删除成功");
          getList();
        });
      })
      .catch(() => {
        proxy.$modal.msg("已取消");
      });
};
defineExpose({
  openDialog,
});
</script>
<style scoped>
</style>
src/views/qualityManagement/processInspection/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,241 @@
<template>
  <div class="app-container">
    <div class="search_form">
      <div>
        <span class="search_title">工序:</span>
        <el-input
            v-model="searchForm.process"
            style="width: 240px"
            placeholder="请输入工序搜索"
            @change="handleQuery"
            clearable
            :prefix-icon="Search"
        />
        <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
        >搜索</el-button
        >
      </div>
      <div>
        <el-button type="primary" @click="openForm('add')">新增</el-button>
        <el-button @click="handleOut">导出</el-button>
        <el-button type="danger" plain @click="handleDelete">删除</el-button>
      </div>
    </div>
    <div class="table_list">
      <PIMTable
          rowKey="id"
          :column="tableColumn"
          :tableData="tableData"
          :page="page"
          :isSelection="true"
          @selection-change="handleSelectionChange"
          :tableLoading="tableLoading"
          @pagination="pagination"
          :total="page.total"
      ></PIMTable>
    </div>
    <InspectionFormDia ref="inspectionFormDia" @close="handleQuery"></InspectionFormDia>
    <FormDia ref="formDia" @close="handleQuery"></FormDia>
    <files-dia ref="filesDia" @close="handleQuery"></files-dia>
  </div>
</template>
<script setup>
import { Search } from "@element-plus/icons-vue";
import {onMounted, ref} from "vue";
import InspectionFormDia from "@/views/qualityManagement/processInspection/components/inspectionFormDia.vue";
import FormDia from "@/views/qualityManagement/processInspection/components/formDia.vue";
import {ElMessageBox} from "element-plus";
import {qualityInspectDel, qualityInspectListPage} from "@/api/qualityManagement/rawMaterialInspection.js";
import FilesDia from "@/views/qualityManagement/processInspection/components/filesDia.vue";
const data = reactive({
  searchForm: {
    process: "",
  },
});
const { searchForm } = toRefs(data);
const tableColumn = ref([
  {
    label: "检测日期",
    prop: "checkTime",
    width: 120
  },
  {
    label: "工序",
    prop: "process",
    width: 230
  },
  {
    label: "检验员",
    prop: "checkName",
  },
  {
    label: "产品名称",
    prop: "productName",
  },
  {
    label: "规格型号",
    prop: "model",
  },
  {
    label: "单位",
    prop: "unit",
  },
  {
    label: "数量",
    prop: "quantity",
    width: 100
  },
  {
    label: "检测单位",
    prop: "checkCompany",
    width: 120
  },
  {
    label: "检测结果",
    prop: "checkResult",
    dataType: "tag",
    formatType: (params) => {
      if (params == '不合格') {
        return "danger";
      } else if (params == '合格') {
        return "success";
      } else {
        return null;
      }
    },
  },
  {
    dataType: "action",
    label: "操作",
    align: "center",
    fixed: "right",
    width: 190,
    operation: [
      {
        name: "编辑",
        type: "text",
        clickFun: (row) => {
          openForm("edit", row);
        },
      },
      {
        name: "新增检验记录",
        type: "text",
        clickFun: (row) => {
          openInspectionForm("edit", row);
        },
      },
      {
        name: "附件",
        type: "text",
        clickFun: (row) => {
          openFilesFormDia(row);
        },
      },
    ],
  },
]);
const tableData = ref([]);
const selectedRows = ref([]);
const tableLoading = ref(false);
const page = reactive({
  current: 1,
  size: 100,
  total: 0
});
const formDia = ref()
const filesDia = ref()
const inspectionFormDia = ref()
const { proxy } = getCurrentInstance()
// æŸ¥è¯¢åˆ—表
/** æœç´¢æŒ‰é’®æ“ä½œ */
const handleQuery = () => {
  page.current = 1;
  getList();
};
const pagination = (obj) => {
  page.current = obj.page;
  page.size = obj.limit;
  getList();
};
const getList = () => {
  tableLoading.value = true;
  qualityInspectListPage({...page, ...searchForm.value, inspectType: 1}).then(res => {
    tableLoading.value = false;
    tableData.value = res.data.records
    page.total = res.data.total;
  }).catch(err => {
    tableLoading.value = false;
  })
};
// è¡¨æ ¼é€‰æ‹©æ•°æ®
const handleSelectionChange = (selection) => {
  selectedRows.value = selection;
};
// æ‰“开弹框
const openForm = (type, row) => {
  nextTick(() => {
    formDia.value?.openDialog(type, row)
  })
};
// æ‰“开新增检验弹框
const openInspectionForm = (type, row) => {
  nextTick(() => {
    inspectionFormDia.value?.openDialog(type, row)
  })
};
// æ‰“开附件弹框
const openFilesFormDia = (type, row) => {
  nextTick(() => {
    filesDia.value?.openDialog(type, row)
  })
};
// åˆ é™¤
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(() => {
        qualityInspectDel(ids).then((res) => {
          proxy.$modal.msgSuccess("删除成功");
          getList();
        });
      })
      .catch(() => {
        proxy.$modal.msg("已取消");
      });
};
// å¯¼å‡º
const handleOut = () => {
  ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  })
      .then(() => {
        proxy.download("/quality/qualityInspect/export", {inspectType: 1}, "过程检验.xlsx");
      })
      .catch(() => {
        proxy.$modal.msg("已取消");
      });
};
onMounted(() => {
  getList();
});
</script>
<style scoped></style>
src/views/qualityManagement/rawMaterialInspection/components/filesDia.vue
@@ -1,9 +1,177 @@
<template>
  <div></div>
  <div>
    <el-dialog
        v-model="dialogFormVisible"
        title="上传附件"
        width="50%"
        @close="closeDia"
    >
      <div style="margin-bottom: 10px;text-align: right">
        <el-upload
            v-model:file-list="fileList"
            class="upload-demo"
            :action="uploadUrl"
            :on-success="handleUploadSuccess"
            :on-error="handleUploadError"
            name="file"
            :show-file-list="false"
            :headers="headers"
            style="display: inline;margin-right: 10px"
        >
          <el-button type="primary">上传附件</el-button>
        </el-upload>
        <el-button type="danger" plain @click="handleDelete">删除</el-button>
      </div>
      <PIMTable
          rowKey="id"
          :column="tableColumn"
          :tableData="tableData"
          :tableLoading="tableLoading"
          :isSelection="true"
          @selection-change="handleSelectionChange"
          height="600"
      >
      </PIMTable>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="closeDia">取消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import {ref} from "vue";
import {getStaffJoinInfo, staffJoinAdd, staffJoinUpdate} from "@/api/personnelManagement/onboarding.js";
import {Search} from "@element-plus/icons-vue";
import {
  qualityInspectParamDel,
  qualityInspectParamInfo,
  qualityInspectParamUpdate
} from "@/api/qualityManagement/qualityInspectParam.js";
import {ElMessageBox} from "element-plus";
import {getToken} from "@/utils/auth.js";
import {
  qualityInspectFileAdd,
  qualityInspectFileDel,
  qualityInspectFileListPage
} from "@/api/qualityManagement/qualityInspectFile.js";
const { proxy } = getCurrentInstance()
const emit = defineEmits(['close'])
const dialogFormVisible = ref(false);
const currentId = ref('')
const selectedRows = ref([]);
const tableColumn = ref([
  {
    label: "文件名称",
    prop: "name",
  },
  // {
  //   label: "上传人",
  //   prop: "createUser",
  // },
  // {
  //   label: "上传时间",
  //   prop: "createTime",
  // },
  {
    dataType: "action",
    label: "操作",
    align: "center",
    operation: [
      {
        name: "下载",
        type: "text",
        clickFun: (row) => {
          downLoadFile(row);
        },
      }
    ],
  },
]);
const tableData = ref([]);
const fileList = ref([]);
const tableLoading = ref(false);
const headers = ref({
  Authorization: "Bearer " + getToken(),
});
const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + "/file/upload"); // ä¸Šä¼ çš„图片服务器地址
// æ‰“开弹框
const openDialog = (row) => {
  dialogFormVisible.value = true;
  currentId.value = row.id;
  getList()
}
const getList = () => {
  qualityInspectFileListPage({inspectId: currentId.value}).then(res => {
    tableData.value = res.data.records;
  })
}
// è¡¨æ ¼é€‰æ‹©æ•°æ®
const handleSelectionChange = (selection) => {
  selectedRows.value = selection;
};
// å…³é—­å¼¹æ¡†
const closeDia = () => {
  dialogFormVisible.value = false;
  emit('close')
};
// ä¸Šä¼ æˆåŠŸå¤„ç†
function handleUploadSuccess(res, file) {
  // å¦‚果上传成功
  if (res.code == 200) {
    const fileRow = {}
    fileRow.name = res.data.originalName
    fileRow.url = res.data.tempPath
    uploadFile(fileRow)
  } else {
    proxy.$modal.msgError("文件上传失败");
  }
}
function uploadFile(file) {
  file.inspectId = currentId.value;
  qualityInspectFileAdd(file).then(res => {
    proxy.$modal.msgSuccess("文件上传成功");
    getList()
  })
}
// ä¸Šä¼ å¤±è´¥å¤„理
function handleUploadError() {
  proxy.$modal.msgError("文件上传失败");
}
// ä¸‹è½½é™„ä»¶
const downLoadFile = (row) => {
  proxy.$download.name(row.url);
}
// åˆ é™¤
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(() => {
    qualityInspectFileDel(ids).then((res) => {
      proxy.$modal.msgSuccess("删除成功");
      getList();
    });
  }).catch(() => {
    proxy.$modal.msg("已取消");
  });
};
defineExpose({
  openDialog,
});
</script>
<style scoped>
src/views/qualityManagement/rawMaterialInspection/components/formDia.vue
@@ -2,21 +2,99 @@
  <div>
    <el-dialog
        v-model="dialogFormVisible"
        :title="operationType === 'add' ? '新增入职' : '编辑人员'"
        :title="operationType === 'add' ? '新增原材料检验' : '编辑原材料检验'"
        width="70%"
        @close="closeDia"
    >
      <PIMTable
          rowKey="id"
          :column="tableColumn"
          :tableData="tableData"
          :tableLoading="tableLoading"
          height="600"
      >
        <template #slot="{ row }">
          <el-input v-model="row.staffName" clearable/>
        </template>
      </PIMTable>
      <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="供应商:" prop="supplier">
              <el-select
                  v-model="form.supplier"
                  placeholder="请选择"
                  clearable
              >
                <el-option
                    v-for="item in supplierList"
                    :key="item.id"
                    :label="item.supplierName"
                    :value="item.supplierName"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="产品名称:" prop="productId">
              <el-tree-select
                  v-model="form.productId"
                  placeholder="请选择"
                  clearable
                  check-strictly
                  @change="getModels"
                  :data="productOptions"
                  :render-after-expand="false"
                  style="width: 100%"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="规格型号:" prop="model">
              <el-input v-model="form.model" placeholder="请输入" clearable/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="单位:" prop="unit">
              <el-input v-model="form.unit" placeholder="请输入" clearable/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="数量:" prop="quantity">
              <el-input v-model="form.quantity" placeholder="请输入" clearable/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="检测单位:" prop="checkCompany">
              <el-input v-model="form.checkCompany" placeholder="请输入" clearable/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="检测结果:" prop="checkResult">
              <el-select v-model="form.checkResult">
                <el-option label="合格" value="合格" />
                <el-option label="不合格" value="不合格" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="检验员:" prop="checkName">
              <el-input v-model="form.checkName" placeholder="请输入" clearable/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="检测日期:" prop="checkTime">
              <el-date-picker
                  v-model="form.checkTime"
                  type="date"
                  placeholder="请选择日期"
                  value-format="YYYY-MM-DD"
                  format="YYYY-MM-DD"
                  clearable
                  style="width: 100%"
              />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确认</el-button>
@@ -29,62 +107,103 @@
<script setup>
import {ref} from "vue";
import {getStaffJoinInfo, staffJoinAdd, staffJoinUpdate} from "@/api/personnelManagement/onboarding.js";
import {Search} from "@element-plus/icons-vue";
import {getOptions} from "@/api/procurementManagement/procurementLedger.js";
import {productTreeList} from "@/api/basicData/product.js";
import {qualityInspectAdd, qualityInspectUpdate} from "@/api/qualityManagement/rawMaterialInspection.js";
const { proxy } = getCurrentInstance()
const emit = defineEmits(['close'])
const dialogFormVisible = ref(false);
const operationType = ref('')
const tableColumn = ref([
  {
    label: "指标",
    prop: "contractTerm",
const data = reactive({
  form: {
    checkTime: "",
    supplier: "",
    checkName: "",
    productName: "",
    productId: "",
    model: "",
    unit: "",
    quantity: "",
    checkCompany: "",
    checkResult: "",
  },
  {
    label: "单位",
    prop: "contractStartTime",
  rules: {
    checkTime: [{ required: false, message: "请输入", trigger: "blur" },],
    supplier: [{ required: true, message: "请输入", trigger: "blur" }],
    checkName: [{ required: false, message: "请输入", trigger: "blur" }],
    productId: [{ required: true, message: "请输入", trigger: "blur" }],
    model: [{ required: false, message: "请输入", trigger: "blur" }],
    unit: [{ required: false, message: "请输入", trigger: "blur" }],
    quantity: [{ required: true, message: "请输入", trigger: "blur" }],
    checkCompany: [{ required: false, message: "请输入", trigger: "blur" }],
    checkResult: [{ required: false, message: "请输入", trigger: "blur" }],
  },
  {
    label: "标准值",
    prop: "contractEndTime",
  },
  {
    label: "内控值",
    prop: "contractEndTime",
  },
  {
    label: "检验值",
    prop: "contractEndTime",
    dataType: 'slot',
    slot: 'slot',
  },
]);
const tableData = ref([]);
const tableLoading = ref(false);
});
const { form, rules } = toRefs(data);
const supplierList = ref([]);
const productOptions = ref([]);
// æ‰“开弹框
const openDialog = (type, row) => {
  operationType.value = type;
  dialogFormVisible.value = true;
  getOptions().then((res) => {
    supplierList.value = res.data;
  });
  getProductOptions();
  if (operationType.value === 'edit') {
    getStaffJoinInfo(row.id).then(res => {
      // tableData.value = res.data
    })
    form.value = {...row}
  }
}
const getProductOptions = () => {
  productTreeList().then((res) => {
    productOptions.value = convertIdToValue(res);
  });
};
const getModels = (value) => {
  form.value.productName = findNodeById(productOptions.value, value);
};
const findNodeById = (nodes, productId) => {
  for (let i = 0; i < nodes.length; i++) {
    if (nodes[i].value === productId) {
      return nodes[i].label; // æ‰¾åˆ°èŠ‚ç‚¹ï¼Œè¿”å›žè¯¥èŠ‚ç‚¹
    }
    if (nodes[i].children && nodes[i].children.length > 0) {
      const foundNode = findNodeById(nodes[i].children, productId);
      if (foundNode) {
        return foundNode; // åœ¨å­èŠ‚ç‚¹ä¸­æ‰¾åˆ°ï¼Œè¿”å›žè¯¥èŠ‚ç‚¹
      }
    }
  }
  return null; // æ²¡æœ‰æ‰¾åˆ°èŠ‚ç‚¹ï¼Œè¿”å›žnull
};
function convertIdToValue(data) {
  return data.map((item) => {
    const { id, children, ...rest } = item;
    const newItem = {
      ...rest,
      value: id, // å°† id æ”¹ä¸º value
    };
    if (children && children.length > 0) {
      newItem.children = convertIdToValue(children);
    }
    return newItem;
  });
}
// æäº¤äº§å“è¡¨å•
const submitForm = () => {
  proxy.$refs.formRef.validate(valid => {
    if (valid) {
      form.value.staffState = 0
      form.value.inspectType = 0
      if (operationType.value === "add") {
        staffJoinAdd(form.value).then(res => {
        qualityInspectAdd(form.value).then(res => {
          proxy.$modal.msgSuccess("提交成功");
          closeDia();
        })
      } else {
        staffJoinUpdate(form.value).then(res => {
        qualityInspectUpdate(form.value).then(res => {
          proxy.$modal.msgSuccess("提交成功");
          closeDia();
        })
@@ -94,6 +213,7 @@
}
// å…³é—­å¼¹æ¡†
const closeDia = () => {
  proxy.resetForm("formRef");
  dialogFormVisible.value = false;
  emit('close')
};
src/views/qualityManagement/rawMaterialInspection/components/inspectionFormDia.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,140 @@
<template>
  <div>
    <el-dialog
        v-model="dialogFormVisible"
        title="填写检验记录"
        width="70%"
        @close="closeDia"
    >
      <div style="margin-bottom: 10px;text-align: right">
        <el-button type="danger" plain @click="handleDelete">删除</el-button>
      </div>
      <PIMTable
          rowKey="id"
          :column="tableColumn"
          :tableData="tableData"
          :tableLoading="tableLoading"
          :isSelection="true"
          @selection-change="handleSelectionChange"
          height="600"
      >
        <template #slot="{ row }">
          <el-input v-model="row.testValue" clearable/>
        </template>
      </PIMTable>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确认</el-button>
          <el-button @click="closeDia">取消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import {ref} from "vue";
import {getStaffJoinInfo, staffJoinAdd, staffJoinUpdate} from "@/api/personnelManagement/onboarding.js";
import {Search} from "@element-plus/icons-vue";
import {
  qualityInspectParamDel,
  qualityInspectParamInfo,
  qualityInspectParamUpdate
} from "@/api/qualityManagement/qualityInspectParam.js";
import {ElMessageBox} from "element-plus";
const { proxy } = getCurrentInstance()
const emit = defineEmits(['close'])
const dialogFormVisible = ref(false);
const operationType = ref('')
const currentId = ref('')
const selectedRows = ref([]);
const tableColumn = ref([
  {
    label: "指标",
    prop: "parameterItem",
  },
  {
    label: "单位",
    prop: "unit",
  },
  {
    label: "标准值",
    prop: "standardValue",
  },
  {
    label: "内控值",
    prop: "controlValue",
  },
  {
    label: "检验值",
    prop: "testValue",
    dataType: 'slot',
    slot: 'slot',
  },
]);
const tableData = ref([]);
const tableLoading = ref(false);
// æ‰“开弹框
const openDialog = (type, row) => {
  operationType.value = type;
  dialogFormVisible.value = true;
  if (operationType.value === 'edit') {
    currentId.value = row.id;
    getList()
  }
}
const getList = () => {
  qualityInspectParamInfo(currentId.value).then(res => {
    tableData.value = res.data;
  })
}
// è¡¨æ ¼é€‰æ‹©æ•°æ®
const handleSelectionChange = (selection) => {
  selectedRows.value = selection;
};
// æäº¤äº§å“è¡¨å•
const submitForm = () => {
  qualityInspectParamUpdate(tableData.value).then(res => {
    proxy.$modal.msgSuccess("提交成功");
    closeDia();
  })
}
// å…³é—­å¼¹æ¡†
const closeDia = () => {
  dialogFormVisible.value = false;
  emit('close')
};
// åˆ é™¤
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(() => {
        qualityInspectParamDel(ids).then((res) => {
          proxy.$modal.msgSuccess("删除成功");
          getList();
        });
      })
      .catch(() => {
        proxy.$modal.msg("已取消");
      });
};
defineExpose({
  openDialog,
});
</script>
<style scoped>
</style>
src/views/qualityManagement/rawMaterialInspection/index.vue
@@ -2,11 +2,11 @@
  <div class="app-container">
    <div class="search_form">
      <div>
        <span class="search_title">姓名:</span>
        <span class="search_title">供应商:</span>
        <el-input
            v-model="searchForm.staffName"
            v-model="searchForm.supplier"
            style="width: 240px"
            placeholder="请输入姓名搜索"
            placeholder="请输入供应商搜索"
            @change="handleQuery"
            clearable
            :prefix-icon="Search"
@@ -34,76 +34,73 @@
          :total="page.total"
      ></PIMTable>
    </div>
    <form-dia ref="formDia" @close="handleQuery"></form-dia>
    <InspectionFormDia ref="inspectionFormDia" @close="handleQuery"></InspectionFormDia>
    <FormDia ref="formDia" @close="handleQuery"></FormDia>
    <files-dia ref="filesDia" @close="handleQuery"></files-dia>
  </div>
</template>
<script setup>
import { Search } from "@element-plus/icons-vue";
import {onMounted, ref} from "vue";
import InspectionFormDia from "@/views/qualityManagement/rawMaterialInspection/components/inspectionFormDia.vue";
import FormDia from "@/views/qualityManagement/rawMaterialInspection/components/formDia.vue";
import {staffJoinDel, staffJoinListPage} from "@/api/personnelManagement/onboarding.js";
import {ElMessageBox} from "element-plus";
import {qualityInspectDel, qualityInspectListPage} from "@/api/qualityManagement/rawMaterialInspection.js";
import FilesDia from "@/views/qualityManagement/rawMaterialInspection/components/filesDia.vue";
const data = reactive({
  searchForm: {
    staffName: "",
    supplier: "",
  },
});
const { searchForm } = toRefs(data);
const tableColumn = ref([
  {
    label: "检测日期",
    prop: "staffNo",
    prop: "checkTime",
    width: 120
  },
  {
    label: "供应商",
    prop: "staffName",
    prop: "supplier",
    width: 230
  },
  {
    label: "检验员",
    prop: "sex",
    prop: "checkName",
  },
  {
    label: "产品名称",
    prop: "nativePlace",
    prop: "productName",
  },
  {
    label: "规格型号",
    prop: "nativePlace",
    prop: "model",
  },
  {
    label: "单位",
    prop: "nativePlace",
    prop: "unit",
  },
  {
    label: "数量",
    prop: "contractStartTime",
    prop: "quantity",
    width: 120
  },
  {
    label: "检测单位",
    prop: "contractEndTime",
    prop: "checkCompany",
    width: 120
  },
  {
    label: "检测结果",
    prop: "staffState",
    prop: "checkResult",
    dataType: "tag",
    formatData: (params) => {
      if (params == 0) {
        return "离职";
      } else if (params == 1) {
        return "在职";
      } else {
        return null;
      }
    },
    formatType: (params) => {
      if (params == 0) {
      if (params == '不合格') {
        return "danger";
      } else if (params == 1) {
        return "primary";
      } else if (params == '合格') {
        return "success";
      } else {
        return null;
      }
@@ -114,20 +111,27 @@
    label: "操作",
    align: "center",
    fixed: "right",
    width: 160,
    width: 190,
    operation: [
      {
        name: "新增检验记录",
        name: "编辑",
        type: "text",
        clickFun: (row) => {
          openForm("edit", row);
        },
      },
      {
        name: "新增检验记录",
        type: "text",
        clickFun: (row) => {
          openInspectionForm("edit", row);
        },
      },
      {
        name: "附件",
        type: "text",
        clickFun: (row) => {
          openForm("edit", row);
          openFilesFormDia(row);
        },
      },
    ],
@@ -142,6 +146,8 @@
  total: 0
});
const formDia = ref()
const filesDia = ref()
const inspectionFormDia = ref()
const { proxy } = getCurrentInstance()
// æŸ¥è¯¢åˆ—表
@@ -157,11 +163,10 @@
};
const getList = () => {
  tableLoading.value = true;
  staffJoinListPage({...page, ...searchForm.value, staffState: 0}).then(res => {
  qualityInspectListPage({...page, ...searchForm.value, inspectType: 0}).then(res => {
    tableLoading.value = false;
    tableData.value = res.data.records
    page.total = res.data.total;
    console.log(page)
  }).catch(err => {
    tableLoading.value = false;
  })
@@ -175,6 +180,18 @@
const openForm = (type, row) => {
  nextTick(() => {
    formDia.value?.openDialog(type, row)
  })
};
// æ‰“开新增检验弹框
const openInspectionForm = (type, row) => {
  nextTick(() => {
    inspectionFormDia.value?.openDialog(type, row)
  })
};
// æ‰“开附件弹框
const openFilesFormDia = (type, row) => {
  nextTick(() => {
    filesDia.value?.openDialog(type, row)
  })
};
@@ -193,7 +210,7 @@
    type: "warning",
  })
      .then(() => {
        staffJoinDel(ids).then((res) => {
        qualityInspectDel(ids).then((res) => {
          proxy.$modal.msgSuccess("删除成功");
          getList();
        });
@@ -210,7 +227,7 @@
    type: "warning",
  })
      .then(() => {
        proxy.download("/staff/staffJoinLeaveRecord/export", {staffState: 0}, "人员离职.xlsx");
        proxy.download("/quality/qualityInspect/export", {inspectType: 0}, "原材料检验.xlsx");
      })
      .catch(() => {
        proxy.$modal.msg("已取消");