已修改18个文件
1118 ■■■■■ 文件已修改
src/api/qualityManagement/rawMaterialInspection.js 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/stockManagement/New.vue 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/stockManagement/Qualified.vue 137 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/stockManagement/Unqualified.vue 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/procurementLedger/index.vue 40 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productionOrder/New.vue 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/finalInspection/components/formDia.vue 189 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/finalInspection/index.vue 34 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/nonconformingManagement/components/formDia.vue 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/nonconformingManagement/components/inspectionFormDia.vue 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/nonconformingManagement/index.vue 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/processInspection/components/formDia.vue 143 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/processInspection/index.vue 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/rawMaterialInspection/components/formDia.vue 146 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/rawMaterialInspection/index.vue 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/returnOrder/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/salesLedger/index.vue 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/salesQuotation/index.vue 200 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/qualityManagement/rawMaterialInspection.js
@@ -55,3 +55,12 @@
    })
}
// 下载出库检验报告
export function downloadOutReport(data) {
    return request({
        url: '/quality/qualityInspect/downOutReport',
        method: 'post',
        data: data,
        responseType: "blob",
    })
}
src/views/inventoryManagement/stockManagement/New.vue
@@ -42,6 +42,20 @@
        </el-form-item>
        <el-form-item
          label="生产日期"
          prop="productionDate"
        >
          <el-date-picker
            v-model="formState.productionDate"
            type="date"
            placeholder="请选择生产日期"
            value-format="YYYY-MM-DD"
            format="YYYY-MM-DD"
            style="width: 100%"
          />
        </el-form-item>
        <el-form-item
          label="供应商"
          prop="customer"
          :rules="[{ required: true, message: '请选择供应商', trigger: 'change' }]"
@@ -132,6 +146,7 @@
  productModelName: "",
  unit: "",
  batchNo: "",
  productionDate: "",
  customer: "",
  qualitity: 0,
  warnNum: 0,
@@ -160,6 +175,7 @@
    productModelName: "",
    unit: "",
    batchNo: "",
    productionDate: "",
    customer: "",
    qualitity: 0,
    warnNum: 0,
src/views/inventoryManagement/stockManagement/Qualified.vue
@@ -1,31 +1,52 @@
<template>
  <div class="app-container">
    <div class="search_form">
      <div>
        <span class="search_title ml10">产品大类:</span>
        <el-input v-model="searchForm.productName"
                  style="width: 240px"
                  placeholder="请输入"
                  clearable/>
        <span class="search_title ml10" style="margin-left: 20px">规格型号:</span>
        <el-input v-model="searchForm.model"
                  style="width: 240px"
                  placeholder="请输入"
                  clearable/>
        <span class="search_title ml10" style="margin-left: 20px">UID码:</span>
        <el-input v-model="searchForm.uidNo"
                  style="width: 200px"
                  placeholder="请输入"
                  clearable/>
        <span class="search_title ml10" style="margin-left: 20px">批次号:</span>
        <el-input v-model="searchForm.batchNo"
                  style="width: 200px"
                  placeholder="请输入"
                  clearable/>
        <el-button type="primary" @click="handleQuery" style="margin-left: 10px">搜索</el-button>
    <div class="search_form search_form--wrap">
      <div class="search-field">
        <span class="search_title">产品类型:</span>
        <el-radio-group v-model="productScope" class="qualified-product-scope" @change="onProductScopeChange">
          <el-radio-button label="成品">成品</el-radio-button>
          <el-radio-button label="其他产品">其他产品</el-radio-button>
        </el-radio-group>
      </div>
      <div>
         <el-button type="primary" @click="isShowNewModal = true">新增库存</el-button>
      <div class="search-field">
        <span class="search_title">产品名称:</span>
        <el-input
          v-model="searchForm.productName"
          class="search-input"
          placeholder="请输入"
          clearable
        />
      </div>
      <div class="search-field">
        <span class="search_title">规格型号:</span>
        <el-input
          v-model="searchForm.model"
          class="search-input"
          placeholder="请输入"
          clearable
        />
      </div>
      <div class="search-field">
        <span class="search_title">UID码:</span>
        <el-input
          v-model="searchForm.uidNo"
          class="search-input"
          placeholder="请输入"
          clearable
        />
      </div>
      <div class="search-field">
        <span class="search_title">批次号:</span>
        <el-input
          v-model="searchForm.batchNo"
          class="search-input"
          placeholder="请输入"
          clearable
        />
      </div>
      <div class="search-field search-field--actions">
        <el-button type="primary" @click="handleQuery">搜索</el-button>
        <el-button type="primary" @click="isShowNewModal = true">新增库存</el-button>
        <el-button type="info" plain icon="Upload" @click="isShowImportModal = true">
          导入库存
        </el-button>
@@ -35,7 +56,7 @@
    <div class="table_list">
      <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange"
        :expand-row-keys="expandedRowKeys" :row-key="row => row.id" style="width: 100%"
        :row-class-name="tableRowClassName" height="calc(100vh - 18.5em)">
        :row-class-name="tableRowClassName" height="calc(100vh - 26.5em)">
        <el-table-column align="center" type="selection" width="55" />
        <el-table-column align="center" label="序号" type="index" width="60" />
        <el-table-column label="产品大类" prop="productName" show-overflow-tooltip />
@@ -46,10 +67,11 @@
        <el-table-column label="单位" prop="unit" show-overflow-tooltip />
        <el-table-column label="库存数量" prop="qualitity" show-overflow-tooltip />
        <el-table-column label="冻结数量" prop="lockedQuantity" show-overflow-tooltip />
        <el-table-column label="库存预警数量" prop="warnNum"  show-overflow-tooltip />
        <el-table-column label="库存预警数量" width="120" prop="warnNum"  show-overflow-tooltip />
        <el-table-column label="生产日期" prop="productionDate" show-overflow-tooltip />
        <el-table-column label="备注" prop="remark"  show-overflow-tooltip />
        <el-table-column label="最近更新时间" prop="updateTime" show-overflow-tooltip />
        <el-table-column fixed="right" label="操作" min-width="60" align="center">
        <el-table-column label="最近更新时间" width="120" prop="updateTime" show-overflow-tooltip />
        <el-table-column fixed="right" label="操作" min-width="100" align="center">
          <template #default="scope">
            <el-button link type="primary" size="small" @click="showSubtractModal(scope.row)" :disabled="scope.row.unLockedQuantity === 0">领用</el-button>
            <el-button link type="primary" size="small" v-if="scope.row.unLockedQuantity > 0" @click="showFrozenModal(scope.row)">冻结</el-button>
@@ -87,7 +109,7 @@
<script setup>
import pagination from '@/components/PIMTable/Pagination.vue'
import { ref, reactive, toRefs, onMounted, getCurrentInstance } from 'vue'
import { ref, reactive, toRefs, onMounted, getCurrentInstance, defineAsyncComponent } from 'vue'
import {ElMessage, ElMessageBox} from "element-plus";
import { getStockInventoryListPage } from "@/api/inventoryManagement/stockInventory.js";
const NewStockInventory = defineAsyncComponent(() => import("@/views/inventoryManagement/stockManagement/New.vue"));
@@ -124,6 +146,18 @@
})
const { searchForm } = toRefs(data)
// 成品(2) / 其他产品(原材料1、半成品3),与产品类型字典一致;分页接口需支持 productType 或 productTypes
const productScope = ref('成品')
const getProductScopeParams = () => {
  return { productScope: productScope.value }
}
const onProductScopeChange = () => {
  page.current = 1
  getList()
}
// 查询列表
/** 搜索按钮操作 */
const handleQuery = () => {
@@ -137,7 +171,7 @@
}
const getList = () => {
  tableLoading.value = true
  getStockInventoryListPage({ ...searchForm.value, ...page }).then(res => {
  getStockInventoryListPage({ ...searchForm.value, ...page, ...getProductScopeParams() }).then(res => {
    tableLoading.value = false
    tableData.value = res.data.records
    total.value = res.data.total
@@ -207,7 +241,7 @@
    type: 'warning',
  }
  ).then(() => {
    proxy.download("/stockInventory/exportStockInventory", {}, '合格库存信息.xlsx')
    proxy.download("/stockInventory/exportStockInventory", { ...searchForm.value, ...getProductScopeParams() }, '合格库存信息.xlsx')
  }).catch(() => {
    proxy.$modal.msg("已取消")
  })
@@ -219,6 +253,45 @@
</script>
<style scoped lang="scss">
.search_form--wrap {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 16px;
}
.search-field {
  display: inline-flex;
  align-items: center;
  flex: 0 1 auto;
  min-width: 0;
  gap: 8px;
  .search_title {
    flex-shrink: 0;
    white-space: nowrap;
    text-align: right;
    min-width: 4.5em;
  }
  .search-input {
    width: 200px;
  }
  .qualified-product-scope {
    flex-shrink: 0;
  }
}
.search-field--actions {
  flex-wrap: wrap;
  gap: 8px;
}
.qualified-product-scope {
  vertical-align: middle;
}
:deep(.row-low-stock td) {
  background-color: #fde2e2;
  color: #c45656;
src/views/inventoryManagement/stockManagement/Unqualified.vue
@@ -1,31 +1,45 @@
<template>
  <div class="app-container">
    <div class="search_form">
      <div>
        <span class="search_title ml10">产品大类:</span>
        <el-input v-model="searchForm.productName"
                  style="width: 240px"
                  placeholder="请输入"
                  clearable/>
        <span class="search_title ml10" style="margin-left: 20px">规格型号:</span>
        <el-input v-model="searchForm.model"
                  style="width: 240px"
                  placeholder="请输入"
                  clearable/>
        <span class="search_title ml10" style="margin-left: 20px">UID码:</span>
        <el-input v-model="searchForm.uidNo"
                  style="width: 200px"
                  placeholder="请输入"
                  clearable/>
        <span class="search_title ml10" style="margin-left: 20px">批次号:</span>
        <el-input v-model="searchForm.batchNo"
                  style="width: 200px"
                  placeholder="请输入"
                  clearable/>
        <el-button type="primary" @click="handleQuery" style="margin-left: 10px">搜索</el-button>
    <div class="search_form search_form--wrap">
      <div class="search-field">
        <span class="search_title">产品名称:</span>
        <el-input
          v-model="searchForm.productName"
          class="search-input"
          placeholder="请输入"
          clearable
        />
      </div>
      <div>
         <el-button type="primary" @click="isShowNewModal = true">新增库存</el-button>
      <div class="search-field">
        <span class="search_title">规格型号:</span>
        <el-input
          v-model="searchForm.model"
          class="search-input"
          placeholder="请输入"
          clearable
        />
      </div>
      <div class="search-field">
        <span class="search_title">UID码:</span>
        <el-input
          v-model="searchForm.uidNo"
          class="search-input"
          placeholder="请输入"
          clearable
        />
      </div>
      <div class="search-field">
        <span class="search_title">批次号:</span>
        <el-input
          v-model="searchForm.batchNo"
          class="search-input"
          placeholder="请输入"
          clearable
        />
      </div>
      <div class="search-field search-field--actions">
        <el-button type="primary" @click="handleQuery">搜索</el-button>
        <el-button type="primary" @click="isShowNewModal = true">新增库存</el-button>
        <el-button @click="handleOut">导出</el-button>
      </div>
    </div>
@@ -45,7 +59,7 @@
        <el-table-column label="冻结数量" prop="lockedQuantity" show-overflow-tooltip />
        <el-table-column label="备注" prop="remark"  show-overflow-tooltip />
        <el-table-column label="最近更新时间" prop="updateTime" show-overflow-tooltip />
        <el-table-column fixed="right" label="操作" min-width="60" align="center">
        <el-table-column fixed="right" label="操作" min-width="120" align="center">
          <template #default="scope">
            <el-button link type="primary" size="small" @click="showSubtractModal(scope.row)" :disabled="scope.row.unLockedQuantity === 0">领用</el-button>
            <el-button link type="primary" size="small" v-if="scope.row.unLockedQuantity > 0" @click="showFrozenModal(scope.row)">冻结</el-button>
@@ -78,7 +92,7 @@
<script setup>
import pagination from '@/components/PIMTable/Pagination.vue'
import { ref, reactive, toRefs, onMounted, getCurrentInstance } from 'vue'
import { ref, reactive, toRefs, onMounted, getCurrentInstance, defineAsyncComponent } from 'vue'
import { ElMessageBox } from "element-plus";
import { getStockUninventoryListPage } from "@/api/inventoryManagement/stockUninventory.js";
const NewStockInventory = defineAsyncComponent(() => import("@/views/inventoryManagement/stockManagement/New.vue"));
@@ -166,13 +180,8 @@
const expandedRowKeys = ref([])
// 表格行类名
const tableRowClassName = ({ row }) => {
  // const stock = Number(row?.unLockedQuantity ?? 0);
  // const warn = Number(row?.warnNum ?? 0);
  // if (!Number.isFinite(stock) || !Number.isFinite(warn)) {
  //   return '';
  // }
  // return stock < warn ? 'row-low-stock' : '';
const tableRowClassName = () => {
  return '';
};
// 导出
@@ -185,7 +194,7 @@
    type: 'warning',
  }
  ).then(() => {
    proxy.download("/stockUninventory/exportStockUninventory", {}, '不合格库存信息.xlsx')
    proxy.download("/stockUninventory/exportStockUninventory", { ...searchForm.value }, '不合格库存信息.xlsx')
  }).catch(() => {
    proxy.$modal.msg("已取消")
  })
@@ -197,6 +206,37 @@
</script>
<style scoped lang="scss">
.search_form--wrap {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 16px;
}
.search-field {
  display: inline-flex;
  align-items: center;
  flex: 0 1 auto;
  min-width: 0;
  gap: 8px;
  .search_title {
    flex-shrink: 0;
    white-space: nowrap;
    text-align: right;
    min-width: 4.5em;
  }
  .search-input {
    width: 200px;
  }
}
.search-field--actions {
  flex-wrap: wrap;
  gap: 8px;
}
:deep(.row-low-stock td) {
  background-color: #fde2e2;
  color: #c45656;
src/views/procurementManagement/procurementLedger/index.vue
@@ -121,10 +121,10 @@
                         prop="supplierName"
                          width="160"
                         show-overflow-tooltip />
        <el-table-column label="项目名称"
        <!-- <el-table-column label="项目名称"
                         prop="projectName"
                         width="320"
                         show-overflow-tooltip />
                         show-overflow-tooltip /> -->
        <el-table-column label="审批状态"
                         prop="approvalStatus"
                         width="100"
@@ -239,23 +239,6 @@
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="项目名称"
                          prop="projectName">
              <el-input v-model="form.projectName"
                        placeholder="请输入"
                        clearable />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="付款方式">
              <el-input v-model="form.paymentMethod"
                        placeholder="请输入"
                        clearable />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="签订日期:"
                          prop="executionDate">
              <el-date-picker style="width: 100%"
@@ -267,6 +250,24 @@
                              clearable />
            </el-form-item>
          </el-col>
          <!-- <el-col :span="12">
            <el-form-item label="项目名称"
                          prop="projectName">
              <el-input v-model="form.projectName"
                        placeholder="请输入"
                        clearable />
            </el-form-item>
          </el-col> -->
        </el-row>
        <el-row :gutter="30">
          <!-- <el-col :span="12">
            <el-form-item label="付款方式">
              <el-input v-model="form.paymentMethod"
                        placeholder="请输入"
                        clearable />
            </el-form-item>
          </el-col> -->
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
@@ -991,6 +992,7 @@
    productRules: {
      productId: [{ required: true, message: "请选择", trigger: "change" }],
      productModelId: [{ required: true, message: "请选择", trigger: "change" }],
      batchNo: [{ required: true, message: "请输入批次号", trigger: "blur" }],
      unit: [{ required: true, message: "请输入", trigger: "blur" }],
      quantity: [{ required: true, message: "请输入", trigger: "blur" }],
      taxInclusiveUnitPrice: [
src/views/productionManagement/productionOrder/New.vue
@@ -166,9 +166,7 @@
    const product = products[0];
    formState.value.productId = product.productId;
    formState.value.productName = product.productName;
    if (product.parentName === '一类产品') {
      formState.value.manufacturingTeam = product.parentName.charAt(0) + '类车间';
    }
    formState.value.manufacturingTeam = product.parentName.charAt(0) + '类车间';
    formState.value.productModelName = product.model;
    formState.value.productModelId = product.id;
src/views/qualityManagement/finalInspection/components/formDia.vue
@@ -49,11 +49,21 @@
              </el-select>
            </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="请输入" disabled/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="批号:" prop="batchNo">
              <el-input
                v-model="form.batchNo"
                placeholder="请输入"
                clearable
                :disabled="operationType === 'edit'"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
@@ -61,6 +71,8 @@
              <el-input v-model="form.uidNo" placeholder="请输入" disabled/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="检品数量:" prop="inspectedQuantity">
              <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="form.inspectedQuantity" placeholder="请输入" clearable :precision="2"/>
@@ -69,6 +81,53 @@
          <el-col :span="12">
            <el-form-item label="总数量:" prop="quantity">
              <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="form.quantity" placeholder="请输入" clearable :precision="2" :disabled="quantityDisabled"/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="检品数量:" prop="inspectedQuantity">
              <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="form.inspectedQuantity" placeholder="请输入,不大于总数量" clearable :precision="2" :disabled="quantityDisabled"/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="检验用粉剂/液情况:" prop="inspectMaterialCondition">
              <el-radio-group v-model="form.inspectMaterialCondition">
                <el-radio label="检验用粉剂情况">检验用粉剂情况</el-radio>
                <el-radio label="检验用液剂情况">检验用液剂情况</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="生产日期:" prop="productionDate">
              <el-date-picker
                  v-model="form.productionDate"
                  type="date"
                  placeholder="请选择日期"
                  value-format="YYYY-MM-DD"
                  format="YYYY-MM-DD"
                  clearable
                  style="width: 100%"
                  @change="calculateValidityDate"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="有效期:" prop="validityDate">
              <el-date-picker
                  v-model="form.validityDate"
                  type="date"
                  placeholder="自动计算或手动选择"
                  value-format="YYYY-MM-DD"
                  format="YYYY-MM-DD"
                  clearable
                  style="width: 100%"
              />
            </el-form-item>
          </el-col>
        </el-row>
@@ -139,10 +198,19 @@
          </el-select>
        </template>
        <template #deviceStatus="{ row }">
          <el-tag v-if="row.deviceStatus" :type="getDeviceStatusType(row.deviceStatus)">
            {{ row.deviceStatus }}
          </el-tag>
          <span v-else style="color: #999">-</span>
          <el-select
              v-model="row.deviceStatus"
              placeholder="请选择"
              default-first-option
              clearable
              style="width: 100%"
          >
            <el-option label="正常" value="正常" />
            <el-option label="停机" value="停机" />
            <el-option label="运行" value="运行" />
            <el-option label="维修" value="维修" />
            <el-option label="/" value="/" />
          </el-select>
        </template>
        <template #result="{ row }">
          <el-input v-model="row.result" placeholder="请输入" clearable />
@@ -179,6 +247,15 @@
const dialogFormVisible = ref(false);
const operationType = ref('')
const validateBatchNo = (rule, value, callback) => {
  if (value === undefined || value === null || String(value).trim() === '') {
    callback(new Error('请输入批号'));
    return;
  }
  callback();
};
const data = reactive({
  form: {
    checkTime: "",
@@ -191,8 +268,13 @@
    testStandardId: "",
    unit: "",
    uidNo: "",
    batchNo: "",
    inspectedQuantity: "",
    quantity: "",
    inspectedQuantity: "",
    inspectMaterialCondition: "",
    productionDate: "",
    validityDate: "",
    checkCompany: "",
    checkResult: "",
  },
@@ -206,7 +288,27 @@
    unit: [{ required: false, message: "请输入", trigger: "blur" }],
    inspectedQuantity: [{ required: true, message: "请输入", trigger: "blur" }],
    quantity: [{ required: true, message: "请输入", trigger: "blur" }],
    inspectedQuantity: [
      { required: true, message: "请输入检品数量", trigger: "blur" },
      {
        validator: (rule, value, callback) => {
          if (value !== '' && value !== null && value !== undefined) {
            const qty = Number(form.value.quantity);
            const inspectedQty = Number(value);
            if (!isNaN(qty) && !isNaN(inspectedQty) && inspectedQty > qty) {
              callback(new Error("检品数量不能大于总数量"));
            } else {
              callback();
            }
          } else {
            callback();
          }
        },
        trigger: "blur"
      }
    ],
    checkCompany: [{ required: false, message: "请输入", trigger: "blur" }],
    batchNo: [{ required: true, validator: validateBatchNo, trigger: "blur" }],
    checkResult: [{ required: true, message: "请输入", trigger: "change" }],
  },
});
@@ -229,32 +331,32 @@
        prop: "standardValue",
        width: 180
    },
    {
        label: "单位",
        prop: "unit",
        width: 80
    },
    {
        label: "检测器具",
        prop: "instrument",
        dataType: 'slot',
        slot: 'instrument',
        width: 220
    },
    {
        label: "设备状态",
        prop: "deviceStatus",
        dataType: 'slot',
        slot: 'deviceStatus',
        width: 120
    },
    {
        label: "检测结果",
        prop: "result",
        dataType: 'slot',
        slot: 'result',
        minWidth: 150
    },
  {
    label: "单位",
    prop: "unit",
    width: 70
  },
  {
    label: "检测器具",
    prop: "instrument",
    dataType: 'slot',
    slot: 'instrument',
    width: 220
  },
  {
    label: "设备状态",
    prop: "deviceStatus",
    dataType: 'slot',
    slot: 'deviceStatus',
    width: 120
  },
  {
    label: "检测结果",
    prop: "result",
    dataType: 'slot',
    slot: 'result',
    width: 150
  },
    {
        label: "结果判断",
        prop: "resultJudgment",
@@ -370,6 +472,7 @@
  form.value.productModelId = undefined;
  form.value.unit = undefined;
  form.value.uidNo = undefined;
  form.value.batchNo = "";
  modelOptions.value = [];
  currentProductId.value = value
  form.value.productName = findNodeById(productOptions.value, value);
@@ -385,6 +488,10 @@
  form.value.model = modelOptions.value.find(item => item.id == value)?.model || '';
  form.value.unit = modelOptions.value.find(item => item.id == value)?.unit || '';
  form.value.uidNo = modelOptions.value.find(item => item.id == value)?.uidNo || '';
  // 选择规格型号后,如果已有生产日期则重新计算有效期
  if (form.value.productionDate) {
    calculateValidityDate();
  }
}
const findNodeById = (nodes, productId) => {
@@ -482,6 +589,24 @@
    })
}
// 计算有效期(生产日期 + 规格型号中的有效期)
const calculateValidityDate = async () => {
  if (!form.value.productionDate) {
    form.value.validityDate = '';
    return;
  }
  // 获取规格型号的有效期
  const selectedModel = modelOptions.value.find(item => item.id == form.value.productModelId);
  if (selectedModel && selectedModel.validityPeriod) {
    const productionDate = new Date(form.value.productionDate);
    const validityPeriod = parseFloat(selectedModel.validityPeriod);
    const validityDate = new Date(productionDate);
    validityDate.setFullYear(validityDate.getFullYear() + Math.floor(validityPeriod));
    validityDate.setMonth(validityDate.getMonth() + Math.round((validityPeriod % 1) * 12));
    form.value.validityDate = validityDate.toISOString().split('T')[0];
  }
};
// 获取设备台账列表
const loadDeviceList = () => {
    qualityInspectParamDeviceList().then(res => {
src/views/qualityManagement/finalInspection/index.vue
@@ -68,6 +68,7 @@
import {ElMessageBox} from "element-plus";
import {
    downloadQualityInspect,
    downloadOutReport,
    qualityInspectDel,
    qualityInspectListPage, qualityInspectUpdate,
    submitQualityInspect
@@ -190,7 +191,7 @@
                    return false;
                }
      },
      {
      /*{
        name: "填写检验记录",
        type: "text",
        clickFun: (row) => {
@@ -203,7 +204,7 @@
                    }
                    return false;
                }
      },
      },*/
      {
        name: "附件",
        type: "text",
@@ -246,6 +247,13 @@
                type: "text",
                clickFun: (row) => {
                    downLoadFile(row);
                },
            },
            {
                name: "报告",
                type: "text",
                clickFun: (row) => {
                    downloadReport(row);
                },
            },
    ],
@@ -408,13 +416,31 @@
            type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
        })
        const downloadUrl = window.URL.createObjectURL(blob)
        const link = document.createElement('a')
        link.href = downloadUrl
        link.download = '原材料检验报告.docx'
        document.body.appendChild(link)
        link.click()
        document.body.removeChild(link)
        window.URL.revokeObjectURL(downloadUrl)
    })
};
const downloadReport = (row) => {
    downloadOutReport({ id: row.id }).then((blobData) => {
        const blob = new Blob([blobData], {
            type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
        })
        const downloadUrl = window.URL.createObjectURL(blob)
        const link = document.createElement('a')
        link.href = downloadUrl
        link.download = '出库检验报告.docx'
        document.body.appendChild(link)
        link.click()
        document.body.removeChild(link)
        window.URL.revokeObjectURL(downloadUrl)
    })
src/views/qualityManagement/nonconformingManagement/components/formDia.vue
@@ -49,6 +49,18 @@
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="批号:" prop="batchNo" :required="operationType === 'add'">
              <el-input
                v-model="form.batchNo"
                placeholder="请输入"
                clearable
                :disabled="operationType === 'edit'"
              />
            </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="请输入" disabled/>
            </el-form-item>
@@ -125,7 +137,7 @@
</template>
<script setup>
import {ref, reactive, toRefs} from "vue";
import {ref, reactive, toRefs, getCurrentInstance} from "vue";
import {modelList, productTreeList} from "@/api/basicData/product.js";
import {
  getQualityUnqualifiedInfo,
@@ -140,6 +152,19 @@
const dialogFormVisible = ref(false);
const operationType = ref('')
const validateBatchNo = (rule, value, callback) => {
  if (operationType.value !== 'add') {
    callback();
    return;
  }
  if (value === undefined || value === null || String(value).trim() === '') {
    callback(new Error('请输入批号'));
    return;
  }
  callback();
};
const { rejection_handling } = proxy.useDict("rejection_handling")
const data = reactive({
  form: {
@@ -150,6 +175,7 @@
    productId: "",
    model: "",
    uidNo: "",
    batchNo: "",
    unit: "",
    quantity: "",
    checkCompany: "",
@@ -171,6 +197,7 @@
    checkCompany: [{ required: false, message: "请输入", trigger: "blur" }],
    checkResult: [{ required: false, message: "请输入", trigger: "blur" }],
    dealName: [{ required: true, message: "请选择处理人", trigger: "change" }],
    batchNo: [{ validator: validateBatchNo, trigger: "blur" }],
  },
});
const { form, rules } = toRefs(data);
@@ -201,6 +228,7 @@
      productId: '',
      model: '',
      uidNo: '',
      batchNo: '',
      unit: '',
      quantity: '',
      productName: '',
@@ -233,6 +261,7 @@
  form.value.model = undefined;
  form.value.unit = undefined;
  form.value.uidNo = undefined;
  form.value.batchNo = "";
  modelOptions.value = [];
  form.value.productName = findNodeById(productOptions.value, value);
  modelList({ id: value }).then((res) => {
src/views/qualityManagement/nonconformingManagement/components/inspectionFormDia.vue
@@ -54,6 +54,13 @@
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="批号:" prop="batchNo">
              <el-input v-model="form.batchNo" placeholder="—" 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>
@@ -121,7 +128,7 @@
</template>
<script setup>
import {ref, reactive, toRefs, computed} from "vue";
import {ref, reactive, toRefs, computed, getCurrentInstance} from "vue";
import {productTreeList} from "@/api/basicData/product.js";
import {
  getQualityUnqualifiedInfo,
@@ -142,6 +149,7 @@
    productName: "",
    productId: "",
    model: "",
    batchNo: "",
    unit: "",
    quantity: "",
    checkCompany: "",
src/views/qualityManagement/nonconformingManagement/index.vue
@@ -22,8 +22,6 @@
          <el-input
              v-model="searchForm.productName"
              style="width: 200px"
              placeholder="请输入产品名称搜索"
              @change="handleQuery"
              clearable
              :prefix-icon="Search"
          />
@@ -35,8 +33,8 @@
        <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="primary" @click="openForm('add')">新增</el-button> -->
        <!-- <el-button @click="handleOut">导出</el-button> -->
        <el-button type="danger" plain @click="handleDelete">删除</el-button>
      </div>
    </div>
@@ -148,6 +146,11 @@
    prop: "uidNo",
  },
  {
    label: "批号",
    prop: "batchNo",
    width: 140,
  },
  {
    label: "单位",
    prop: "unit",
  },
src/views/qualityManagement/processInspection/components/formDia.vue
@@ -66,8 +66,52 @@
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="数量:" prop="quantity">
            <el-form-item label="总数量:" prop="quantity">
              <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="form.quantity" placeholder="请输入" clearable :precision="2" :disabled="processQuantityDisabled"/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="检品数量:" prop="inspectedQuantity">
              <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="form.inspectedQuantity" placeholder="请输入,不大于总数量" clearable :precision="2" :disabled="processQuantityDisabled"/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="检验用粉剂/液情况:" prop="inspectMaterialCondition">
              <el-radio-group v-model="form.inspectMaterialCondition">
                <el-radio label="粉剂">粉剂</el-radio>
                <el-radio label="液体">液体</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="生产日期:" prop="productionDate">
              <el-date-picker
                  v-model="form.productionDate"
                  type="date"
                  placeholder="请选择日期"
                  value-format="YYYY-MM-DD"
                  format="YYYY-MM-DD"
                  clearable
                  style="width: 100%"
                  @change="calculateValidityDate"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="有效期:" prop="validityDate">
              <el-date-picker
                  v-model="form.validityDate"
                  type="date"
                  placeholder="自动计算或手动选择"
                  value-format="YYYY-MM-DD"
                  format="YYYY-MM-DD"
                  clearable
                  style="width: 100%"
              />
            </el-form-item>
          </el-col>
        </el-row>
@@ -77,6 +121,18 @@
              <el-input v-model="form.uidNo" placeholder="请输入" disabled/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="批号:" prop="batchNo">
              <el-input
                v-model="form.batchNo"
                placeholder="请输入"
                clearable
                :disabled="operationType === 'edit'"
              />
            </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/>
@@ -90,6 +146,8 @@
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="检验员:" prop="checkName">
              <el-select v-model="form.checkName" placeholder="请选择" clearable>
@@ -141,10 +199,19 @@
          </el-select>
        </template>
        <template #deviceStatus="{ row }">
          <el-tag v-if="row.deviceStatus" :type="getDeviceStatusType(row.deviceStatus)">
            {{ row.deviceStatus }}
          </el-tag>
          <span v-else style="color: #999">-</span>
          <el-select
              v-model="row.deviceStatus"
              placeholder="请选择"
              default-first-option
              clearable
              style="width: 100%"
          >
            <el-option label="正常" value="正常" />
            <el-option label="停机" value="停机" />
            <el-option label="运行" value="运行" />
            <el-option label="维修" value="维修" />
            <el-option label="/" value="/" />
          </el-select>
        </template>
        <template #result="{ row }">
          <el-input v-model="row.result" placeholder="请输入" clearable />
@@ -184,6 +251,15 @@
const dialogFormVisible = ref(false);
const operationType = ref('')
const validateBatchNo = (rule, value, callback) => {
  if (value === undefined || value === null || String(value).trim() === '') {
    callback(new Error('请输入批号'));
    return;
  }
  callback();
};
const data = reactive({
  form: {
    checkTime: "",
@@ -194,9 +270,14 @@
    productModelId: "",
    model: "",
    uidNo: "",
    batchNo: "",
    testStandardId: "",
    unit: "",
    quantity: "",
    inspectedQuantity: "",
    inspectMaterialCondition: "",
    productionDate: "",
    validityDate: "",
    checkCompany: "",
    checkResult: "",
  },
@@ -209,7 +290,27 @@
    testStandardId: [{required: false, message: "请选择指标", trigger: "change"}],
    unit: [{ required: false, message: "请输入", trigger: "blur" }],
    quantity: [{ required: true, message: "请输入", trigger: "blur" }],
    inspectedQuantity: [
      { required: true, message: "请输入检品数量", trigger: "blur" },
      {
        validator: (rule, value, callback) => {
          if (value !== '' && value !== null && value !== undefined) {
            const qty = Number(form.value.quantity);
            const inspectedQty = Number(value);
            if (!isNaN(qty) && !isNaN(inspectedQty) && inspectedQty > qty) {
              callback(new Error("检品数量不能大于总数量"));
            } else {
              callback();
            }
          } else {
            callback();
          }
        },
        trigger: "blur"
      }
    ],
    checkCompany: [{ required: false, message: "请输入", trigger: "blur" }],
    batchNo: [{ required: true, validator: validateBatchNo, trigger: "blur" }],
    checkResult: [{ required: true, message: "请输入", trigger: "change" }],
  },
});
@@ -237,7 +338,7 @@
    {
        label: "单位",
        prop: "unit",
        width: 80
        width: 70
    },
    {
        label: "检测器具",
@@ -258,7 +359,7 @@
        prop: "result",
        dataType: 'slot',
        slot: 'result',
        minWidth: 150
    width: 150
    },
    {
        label: "结果判断",
@@ -305,7 +406,12 @@
        testStandardId: "",
        unit: "",
        uidNo: "",
        batchNo: "",
        quantity: "",
        inspectedQuantity: "",
        inspectMaterialCondition: "",
        productionDate: "",
        validityDate: "",
        checkCompany: "",
        checkResult: "",
    }
@@ -390,6 +496,7 @@
  form.value.productModelId = undefined;
  form.value.unit = undefined;
  form.value.uidNo = undefined;
  form.value.batchNo = "";
  modelOptions.value = [];
  currentProductId.value = value
  form.value.productName = findNodeById(productOptions.value, value);
@@ -405,6 +512,10 @@
  form.value.model = modelOptions.value.find(item => item.id == value)?.model || '';
  form.value.unit = modelOptions.value.find(item => item.id == value)?.unit || '';
  form.value.uidNo = modelOptions.value.find(item => item.id == value)?.uidNo || '';
  // 选择规格型号后,如果已有生产日期则重新计算有效期
  if (form.value.productionDate) {
    calculateValidityDate();
  }
}
const findNodeById = (nodes, productId) => {
@@ -548,6 +659,24 @@
    }
};
// 计算有效期(生产日期 + 规格型号中的有效期)
const calculateValidityDate = async () => {
  if (!form.value.productionDate) {
    form.value.validityDate = '';
    return;
  }
  // 获取规格型号的有效期
  const selectedModel = modelOptions.value.find(item => item.id == form.value.productModelId);
  if (selectedModel && selectedModel.validityPeriod) {
    const productionDate = new Date(form.value.productionDate);
    const validityPeriod = parseFloat(selectedModel.validityPeriod);
    const validityDate = new Date(productionDate);
    validityDate.setFullYear(validityDate.getFullYear() + Math.floor(validityPeriod));
    validityDate.setMonth(validityDate.getMonth() + Math.round((validityPeriod % 1) * 12));
    form.value.validityDate = validityDate.toISOString().split('T')[0];
  }
};
// 关闭弹框
const closeDia = () => {
  proxy.resetForm("formRef");
src/views/qualityManagement/processInspection/index.vue
@@ -122,6 +122,11 @@
    prop: "uidNo",
  },
  {
    label: "批号",
    prop: "batchNo",
    width: 140,
  },
  {
    label: "单位",
    prop: "unit",
  },
@@ -183,7 +188,7 @@
                    return false;
                }
      },
      {
      /*{
        name: "填写检验记录",
        type: "text",
        clickFun: (row) => {
@@ -196,7 +201,7 @@
                    }
                    return false;
                }
      },
      },*/
      {
        name: "附件",
        type: "text",
src/views/qualityManagement/rawMaterialInspection/components/formDia.vue
@@ -76,9 +76,54 @@
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="数量:" prop="quantity">
            <el-form-item label="总数量:" prop="quantity">
              <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="form.quantity" placeholder="请输入"
                               clearable :precision="2" :disabled="supplierQuantityDisabled"/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="检品数量:" prop="inspectedQuantity">
              <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="form.inspectedQuantity" placeholder="请输入,不大于总数量"
                               clearable :precision="2" :disabled="supplierQuantityDisabled"/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="检验用粉剂/液情况:" prop="inspectMaterialCondition">
              <el-radio-group v-model="form.inspectMaterialCondition">
                <el-radio label="粉剂">粉剂</el-radio>
                <el-radio label="液体">液体</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="生产日期:" prop="productionDate">
              <el-date-picker
                  v-model="form.productionDate"
                  type="date"
                  placeholder="请选择日期"
                  value-format="YYYY-MM-DD"
                  format="YYYY-MM-DD"
                  clearable
                  style="width: 100%"
                  @change="calculateValidityDate"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="有效期:" prop="validityDate">
              <el-date-picker
                  v-model="form.validityDate"
                  type="date"
                  placeholder="自动计算或手动选择"
                  value-format="YYYY-MM-DD"
                  format="YYYY-MM-DD"
                  clearable
                  style="width: 100%"
              />
            </el-form-item>
          </el-col>
        </el-row>
@@ -89,12 +134,22 @@
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="检测单位:" prop="checkCompany">
              <el-input v-model="form.checkCompany" placeholder="请输入" clearable/>
            <el-form-item label="批号:" prop="batchNo">
              <el-input
                v-model="form.batchNo"
                placeholder="请输入"
                clearable
                :disabled="operationType === 'edit'"
              />
            </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">
@@ -103,6 +158,8 @@
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="检验员:" prop="checkName">
              <el-select v-model="form.checkName" placeholder="请选择" clearable style="width: 100%">
@@ -156,10 +213,19 @@
          </el-select>
        </template>
        <template #deviceStatus="{ row }">
          <el-tag v-if="row.deviceStatus" :type="getDeviceStatusType(row.deviceStatus)">
            {{ row.deviceStatus }}
          </el-tag>
          <span v-else style="color: #999">-</span>
          <el-select
              v-model="row.deviceStatus"
              placeholder="请选择"
              default-first-option
              clearable
              style="width: 100%"
          >
            <el-option label="正常" value="正常" />
            <el-option label="停机" value="停机" />
            <el-option label="运行" value="运行" />
            <el-option label="维修" value="维修" />
            <el-option label="/" value="/" />
          </el-select>
        </template>
        <template #result="{ row }">
          <el-input v-model="row.result" placeholder="请输入" clearable />
@@ -197,6 +263,15 @@
const dialogFormVisible = ref(false);
const operationType = ref('')
const validateBatchNo = (rule, value, callback) => {
  if (value === undefined || value === null || String(value).trim() === '') {
    callback(new Error('请输入批号'));
    return;
  }
  callback();
};
const data = reactive({
  form: {
    checkTime: "",
@@ -207,9 +282,14 @@
    productModelId: "",
    model: "",
    uidNo: "",
    batchNo: "",
    testStandardId: "",
    unit: "",
    quantity: "",
    inspectedQuantity: "",
    inspectMaterialCondition: "",
    productionDate: "",
    validityDate: "",
    checkCompany: "",
    checkResult: "",
  },
@@ -222,7 +302,27 @@
    testStandardId: [{required: false, message: "请选择指标", trigger: "change"}],
    unit: [{required: false, message: "请输入", trigger: "blur"}],
    quantity: [{required: true, message: "请输入", trigger: "blur"}],
    inspectedQuantity: [
      {required: true, message: "请输入检品数量", trigger: "blur"},
      {
        validator: (rule, value, callback) => {
          if (value !== '' && value !== null && value !== undefined) {
            const qty = Number(form.value.quantity);
            const inspectedQty = Number(value);
            if (!isNaN(qty) && !isNaN(inspectedQty) && inspectedQty > qty) {
              callback(new Error("检品数量不能大于总数量"));
            } else {
              callback();
            }
          } else {
            callback();
          }
        },
        trigger: "blur"
      }
    ],
    checkCompany: [{required: false, message: "请输入", trigger: "blur"}],
    batchNo: [{ required: true, validator: validateBatchNo, trigger: "blur" }],
    checkResult: [{required: true, message: "请选择检测结果", trigger: "change"}],
  },
});
@@ -240,7 +340,7 @@
  {
    label: "单位",
    prop: "unit",
    width: 80
    width: 70
  },
  {
    label: "检测器具",
@@ -261,7 +361,7 @@
    prop: "result",
    dataType: 'slot',
    slot: 'result',
    minWidth: 150
    width: 150
  },
  {
    label: "结果判断",
@@ -316,9 +416,14 @@
    productModelId: "",
    model: "",
    uidNo: "",
    batchNo: "",
    testStandardId: "",
    unit: "",
    quantity: "",
    inspectedQuantity: "",
    inspectMaterialCondition: "",
    productionDate: "",
    validityDate: "",
    checkCompany: "",
    checkResult: "",
  }
@@ -401,6 +506,7 @@
  form.value.productModelId = undefined;
  form.value.unit = undefined;
  form.value.uidNo = undefined;
  form.value.batchNo = "";
  modelOptions.value = [];
  currentProductId.value = value
  form.value.productName = findNodeById(productOptions.value, value);
@@ -416,6 +522,10 @@
  form.value.model = modelOptions.value.find(item => item.id == value)?.model || '';
  form.value.unit = modelOptions.value.find(item => item.id == value)?.unit || '';
  form.value.uidNo = modelOptions.value.find(item => item.id == value)?.uidNo || '';
  // 选择规格型号后,如果已有生产日期则重新计算有效期
  if (form.value.productionDate) {
    calculateValidityDate();
  }
}
const findNodeById = (nodes, productId) => {
@@ -555,6 +665,24 @@
  }
};
// 计算有效期(生产日期 + 规格型号中的有效期)
const calculateValidityDate = async () => {
  if (!form.value.productionDate) {
    form.value.validityDate = '';
    return;
  }
  // 获取规格型号的有效期
  const selectedModel = modelOptions.value.find(item => item.id == form.value.productModelId);
  if (selectedModel && selectedModel.validityPeriod) {
    const productionDate = new Date(form.value.productionDate);
    const validityPeriod = parseFloat(selectedModel.validityPeriod);
    const validityDate = new Date(productionDate);
    validityDate.setFullYear(validityDate.getFullYear() + Math.floor(validityPeriod));
    validityDate.setMonth(validityDate.getMonth() + Math.round((validityPeriod % 1) * 12));
    form.value.validityDate = validityDate.toISOString().split('T')[0];
  }
};
// 关闭弹框
const closeDia = () => {
  proxy.resetForm("formRef");
src/views/qualityManagement/rawMaterialInspection/index.vue
@@ -124,6 +124,11 @@
    prop: "uidNo",
  },
  {
    label: "批号",
    prop: "batchNo",
    width: 140,
  },
  {
    label: "单位",
    prop: "unit",
  },
@@ -185,7 +190,7 @@
                    return false;
                }
      },
      {
      /*{
        name: "填写检验记录",
        type: "text",
        clickFun: (row) => {
@@ -198,7 +203,7 @@
                    }
                    return false;
                }
      },
      },*/
      {
        name: "附件",
        type: "text",
src/views/salesManagement/returnOrder/index.vue
@@ -145,7 +145,7 @@
  { label: "销售单号", prop: "salesContractNo", minWidth: 160 },
  { label: "业务员", prop: "salesman", minWidth: 120 },
  { label: "关联出库单号", prop: "shippingNo", minWidth: 170 },
  { label: "项目名称", prop: "projectName", minWidth: 180 },
  // { label: "项目名称", prop: "projectName", minWidth: 180 },
  { label: "项目阶段", prop: "projectStage", minWidth: 120 },
  { label: "制单人", prop: "maker", minWidth: 120 },
  { label: "结算人", prop: "settler", minWidth: 120 },
src/views/salesManagement/salesLedger/index.vue
@@ -112,8 +112,8 @@
        <el-table-column label="销售合同号" prop="salesContractNo" width="180" show-overflow-tooltip />
        <el-table-column label="客户名称" prop="customerName" width="300" show-overflow-tooltip />
        <el-table-column label="业务员" prop="salesman" width="100" show-overflow-tooltip />
        <el-table-column label="项目名称" prop="projectName" width="180" show-overflow-tooltip />
        <el-table-column label="付款方式" prop="paymentMethod" show-overflow-tooltip />
        <!-- <el-table-column label="项目名称" prop="projectName" width="180" show-overflow-tooltip />
        <el-table-column label="付款方式" prop="paymentMethod" show-overflow-tooltip /> -->
        <el-table-column label="合同金额(元)" prop="contractAmount" width="220" show-overflow-tooltip
          :formatter="formattedNumber" />
        <el-table-column label="录入人" prop="entryPersonName" width="100" show-overflow-tooltip />
@@ -173,24 +173,12 @@
            </el-form-item>
          </el-col>
                    <el-col :span="12">
                        <el-form-item label="项目名称:" prop="projectName">
                            <el-input v-model="form.projectName" placeholder="请输入" clearable :disabled="operationType === 'view'" />
                        </el-form-item>
                    </el-col>
        </el-row>
        <el-row :gutter="30">
                    <el-col :span="12">
                        <el-form-item label="签订日期:" prop="executionDate">
                            <el-date-picker style="width: 100%" v-model="form.executionDate" value-format="YYYY-MM-DD"
                                                            format="YYYY-MM-DD" type="date" placeholder="请选择" clearable :disabled="operationType === 'view'" />
                        </el-form-item>
                    </el-col>
                    <el-col :span="12">
                        <el-form-item label="付款方式">
                            <el-input v-model="form.paymentMethod" placeholder="请输入" clearable :disabled="operationType === 'view'" />
                        </el-form-item>
                    </el-col>
                </el-row>
        </el-row>
                <el-row :gutter="30">
                    <el-col :span="12">
                        <el-form-item label="录入人:" prop="entryPerson">
src/views/salesManagement/salesQuotation/index.vue
@@ -56,13 +56,6 @@
        <el-table-column prop="salesperson" label="业务员" width="100" />
        <el-table-column prop="quotationDate" label="报价日期" width="120" />
        <el-table-column prop="validDate" label="有效期至" width="120" />
        <el-table-column prop="status" label="审批状态" width="120" align="center">
          <template #default="{ row }">
            <el-tag :type="getStatusType(row.status)" disable-transitions>
              {{ row.status || '--' }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="totalAmount" label="报价金额" width="120">
          <template #default="scope">
            ¥{{ scope.row.totalAmount.toFixed(2) }}
@@ -71,7 +64,7 @@
        <el-table-column label="操作" width="200" fixed="right" align="center">
          <template #default="scope">
            <el-button link type="primary" @click="handleView(scope.row)">查看</el-button>
            <el-button link type="primary" @click="handleEdit(scope.row)" :disabled="!['待审批','拒绝'].includes(scope.row.status)">编辑</el-button>
            <el-button link type="primary" @click="handleEdit(scope.row)">编辑</el-button>
            <el-button link type="danger" @click="handleDelete(scope.row)">删除</el-button>
          </template>
        </el-table-column>
@@ -149,69 +142,13 @@
                </el-form-item>
              </el-col>
            </el-row>
            <el-row :gutter="24">
            <!-- <el-row :gutter="24">
              <el-col :span="12">
                <el-form-item label="付款方式" prop="paymentMethod">
                  <el-input v-model="form.paymentMethod" placeholder="请输入付款方式" clearable />
                </el-form-item>
              </el-col>
            </el-row>
          </div>
        </el-card>
        <!-- 审批人信息 -->
        <el-card class="form-card" shadow="hover">
          <template #header>
            <div class="card-header-wrapper">
              <el-icon class="card-icon"><UserFilled /></el-icon>
              <span class="card-title">审批人选择</span>
              <el-button type="primary" size="small" @click="addApproverNode" class="header-btn">
                <el-icon><Plus /></el-icon>
                新增节点
              </el-button>
            </div>
          </template>
          <div class="form-content">
            <el-row>
              <el-col :span="24">
                <el-form-item>
                  <div class="approver-nodes-container">
                    <div
                      v-for="(node, index) in approverNodes"
                      :key="node.id"
                      class="approver-node-item"
                    >
                      <div class="approver-node-label">
                        <span class="node-step">{{ index + 1 }}</span>
                        <span class="node-text">审批人</span>
                        <el-icon class="arrow-icon"><ArrowRight /></el-icon>
                      </div>
                      <el-select
                        v-model="node.userId"
                        placeholder="选择人员"
                        class="approver-select"
                        clearable
                      >
                        <el-option
                          v-for="user in userList"
                          :key="user.userId"
                          :label="user.nickName"
                          :value="user.userId"
                        />
                      </el-select>
                      <el-button
                        type="danger"
                        size="small"
                        :icon="Delete"
                        @click="removeApproverNode(index)"
                        v-if="approverNodes.length > 1"
                        class="remove-btn"
                      >删除</el-button>
                    </div>
                  </div>
                </el-form-item>
              </el-col>
            </el-row>
            </el-row> -->
          </div>
        </el-card>
@@ -356,7 +293,7 @@
<script setup>
import { ref, reactive, computed, onMounted, markRaw, shallowRef } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Search, Document, UserFilled, Box, EditPen, Plus, ArrowRight, Delete } from '@element-plus/icons-vue'
import { Search, Document, Box, EditPen, Plus } from '@element-plus/icons-vue'
import Pagination from '@/components/PIMTable/Pagination.vue'
import FormDialog from '@/components/Dialog/FormDialog.vue'
import {getQuotationList,addQuotation,updateQuotation,deleteQuotation} from '@/api/salesManagement/salesQuotation.js'
@@ -429,26 +366,10 @@
const userList = ref([]);
const customerOption = ref([]);
// 审批人节点相关
const approverNodes = ref([
  { id: 1, userId: null }
])
let nextApproverId = 2
const isEdit = ref(false)
const editId = ref(null)
const currentQuotation = ref({})
const formRef = ref()
// 添加审批人节点
function addApproverNode() {
  approverNodes.value.push({ id: nextApproverId++, userId: null })
}
// 删除审批人节点
function removeApproverNode(index) {
  approverNodes.value.splice(index, 1)
}
// 计算属性
const filteredList = computed(() => {
@@ -457,16 +378,6 @@
})
// 方法
const getStatusType = (status) => {
  const statusMap = {
    '待审批': 'info',
    '审核中': 'primary',
    '通过': 'success',
    '拒绝': 'danger'
  }
  return statusMap[status] || 'info'
}
const resetSearch = () => {
  searchForm.quotationNo = ''
  searchForm.customer = ''
@@ -480,9 +391,6 @@
  dialogTitle.value = '新增报价'
  isEdit.value = false
  resetForm()
  // 重置审批人节点
  approverNodes.value = [{ id: 1, userId: null }]
  nextApproverId = 2
  dialogVisible.value = true
    let userLists = await userListNoPage();
    // 只复制需要的字段,避免将组件引用放入响应式对象
@@ -684,19 +592,6 @@
  form.discountAmount = row.discountAmount || 0
  form.totalAmount = row.totalAmount || 0
  
  // 反显审批人
  if (row.approveUserIds) {
    const userIds = row.approveUserIds.split(',')
    approverNodes.value = userIds.map((userId, idx) => ({
      id: idx + 1,
      userId: parseInt(userId.trim())
    }))
    nextApproverId = userIds.length + 1
  } else {
    approverNodes.value = [{ id: 1, userId: null }]
    nextApproverId = 2
  }
  // 加载用户列表
  let userLists = await userListNoPage();
  userList.value = (userLists.data || []).map(item => ({
@@ -795,16 +690,6 @@
        return
      }
      // 审批人必填校验
      const hasEmptyApprover = approverNodes.value.some(node => !node.userId)
      if (hasEmptyApprover) {
        ElMessage.error('请为所有审批节点选择审批人!')
        return
      }
      // 收集所有节点的审批人id
      form.approveUserIds = approverNodes.value.map(node => node.userId).join(',')
      // 计算所有产品的单价总和
      form.totalAmount = form.products.reduce((sum, product) => {
        const price = Number(product.unitPrice) || 0
@@ -865,8 +750,6 @@
        validDate: item.validDate || '',
        paymentMethod: item.paymentMethod || '',
        status: item.status || '草稿',
        // 审批人(用于编辑时反显)
        approveUserIds: item.approveUserIds || '',
        remark: item.remark || '',
        products: item.products ? item.products.map(product => ({
          productId: product.productId || '',
@@ -991,71 +874,6 @@
  }
}
.approver-nodes-container {
  display: flex;
  flex-wrap: wrap;
  gap: 24px;
  padding: 12px 0;
}
.approver-node-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 16px;
  background: #f8f9fa;
  border-radius: 8px;
  border: 1px solid #e4e7ed;
  transition: all 0.3s ease;
  min-width: 180px;
  &:hover {
    border-color: #409eff;
    background: #f0f7ff;
    box-shadow: 0 2px 8px rgba(64, 158, 255, 0.1);
  }
}
.approver-node-label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  color: #606266;
  .node-step {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    background: #409eff;
    color: #fff;
    border-radius: 50%;
    font-size: 12px;
    font-weight: 600;
  }
  .node-text {
    font-weight: 500;
  }
  .arrow-icon {
    color: #909399;
    font-size: 14px;
  }
}
.approver-select {
  width: 100%;
  min-width: 150px;
}
.remove-btn {
  margin-top: 4px;
}
.product-table {
  :deep(.el-table__header) {
    background-color: #f5f7fa;
@@ -1082,14 +900,4 @@
  text-align: right;
}
// 响应式优化
@media (max-width: 1200px) {
  .approver-nodes-container {
    gap: 16px;
  }
  .approver-node-item {
    min-width: 160px;
  }
}
</style>