5a5f5d467e3dad72d60633af683c5543110ea680..21b1ac28713ee23484e7c89d568c7e27e4f77196
2026-02-03 gongchunyi
Merge branch 'dev_New' of http://114.132.189.42:9002/r/product-inventory-ma...
21b1ac 对比 | 目录
2026-02-03 gongchunyi
fix: 备注字段名与后端不不一致
b086dc 对比 | 目录
2026-02-03 huminmin
原材料检验增加采购订单号;过程检验和出厂检验增加生产工单号
31529c 对比 | 目录
2026-02-03 gongchunyi
fix: 销售报价中规格型号、单位、单价改为必填项校验
789c3a 对比 | 目录
2026-02-03 gongchunyi
feat: 添加备注列
119731 对比 | 目录
2026-02-03 gongchunyi
Merge branch 'dev_New' of http://114.132.189.42:9002/r/product-inventory-ma...
d1a90b 对比 | 目录
2026-02-03 gongchunyi
fix: 输入框输入位数长度、滑动条
649cf9 对比 | 目录
2026-02-03 gaoluyang
Merge remote-tracking branch 'origin/dev_New' into dev_New
4657a2 对比 | 目录
2026-02-03 gaoluyang
进销存升级 1.先查看规章制度管理条数为3条,后查看用印管理页面记录,由原来6条变为3条 2.用印管理分页bug
b3f818 对比 | 目录
2026-02-03 gongchunyi
Merge branch 'dev_New' of http://114.132.189.42:9002/r/product-inventory-ma...
a42d42 对比 | 目录
2026-02-03 gongchunyi
fix: 工单执行效率分析接口错误
dc7ead 对比 | 目录
2026-02-03 gaoluyang
Merge remote-tracking branch 'origin/dev_New' into dev_New
07a33c 对比 | 目录
2026-02-03 gaoluyang
进销存升级 1.协同办公—知识库,知识库点击第二页还是展示第一页
c7836a 对比 | 目录
2026-02-03 zss
Merge remote-tracking branch 'origin/dev_New' into dev_New
0cac9f 对比 | 目录
2026-02-03 zss
调整隐患上报的整改与验收权限
d9746b 对比 | 目录
2026-02-03 gaoluyang
进销存升级 1.生产报工带出来的出厂检数据编辑时,规格型号回显还是有问题 2.用印管理分页数字展示有误
f54d7f 对比 | 目录
2026-02-03 gaoluyang
进销存升级 1.首页应付应收不要筛选类型
c2a4ff 对比 | 目录
2026-02-03 huminmin
根据是否发货,展示销售台账,生产订单列表表格颜色
a34001 对比 | 目录
已修改16个文件
1102 ■■■■■ 文件已修改
src/api/viewIndex.js 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicData/product/index.vue 54 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/knowledgeBase/index.vue 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/rulesRegulationsManagement/index.vue 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/sealManagement/index.vue 589 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/index.vue 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/procurementLedger/index.vue 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productionOrder/index.vue 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/finalInspection/components/formDia.vue 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/finalInspection/index.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/processInspection/index.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/rawMaterialInspection/index.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/reportAnalysis/productionAnalysis/components/right-top.vue 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/safeProduction/dangerInvestigation/index.vue 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/salesLedger/index.vue 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/salesQuotation/index.vue 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/viewIndex.js
@@ -1,6 +1,15 @@
// 首页接口
import request from "@/utils/request";
//  工单执行效率分析
export const workOrderEfficiencyAnalysis = (query) => {
  return request({
    url: "/home/workOrderEfficiencyAnalysis",
    method: "get",
    params: query,
  });
};
//  原材料检测
export const rawMaterialDetection = (query) => {
  return request({
src/views/basicData/product/index.vue
@@ -30,11 +30,8 @@
          :props="{ children: 'children', label: 'label' }"
          highlight-current
          node-key="id"
          style="
            height: calc(100vh - 190px);
            overflow-y: scroll;
            scrollbar-width: none;
          "
          class="product-tree-scroll"
          style="height: calc(100vh - 190px); overflow-y: auto"
        >
          <template #default="{ node, data }">
            <div class="custom-tree-node">
@@ -43,7 +40,7 @@
                  <component :is="data.children && data.children.length > 0
                  ? node.expanded ? 'FolderOpened' : 'Folder' : 'Tickets'" />
                </el-icon>
                {{ data.label }}
                <span class="tree-node-label">{{ data.label }}</span>
              </span>
              <div>
                <el-button
@@ -111,6 +108,8 @@
              <el-input
                v-model="form.productName"
                placeholder="请输入产品名称"
                maxlength="20"
                show-word-limit
                clearable
                @keydown.enter.prevent
              />
@@ -239,7 +238,10 @@
    productName: "",
  },
  rules: {
    productName: [{ required: true, message: "请输入", trigger: "blur" }],
    productName: [
      { required: true, message: "请输入", trigger: "blur" },
      { max: 20, message: "产品名称不能超过20个字符", trigger: "blur" },
    ],
  },
  modelForm: {
    model: "",
@@ -467,18 +469,21 @@
  display: flex;
}
.left {
  width: 380px;
  width: 450px;
  min-width: 450px;
  padding: 16px;
  background: #ffffff;
}
.right {
  width: calc(100% - 380px);
  flex: 1;
  min-width: 0;
  padding: 16px;
  margin-left: 20px;
  background: #ffffff;
}
.custom-tree-node {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
@@ -486,13 +491,42 @@
  padding-right: 8px;
}
.tree-node-content {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center; /* 垂直居中 */
  align-items: center;
  height: 100%;
  overflow: hidden;
}
.tree-node-content .orange-icon {
  flex-shrink: 0;
}
.tree-node-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.orange-icon {
  color: orange;
  font-size: 18px;
  margin-right: 8px; /* 图标与文字之间加点间距 */
}
.product-tree-scroll {
  scrollbar-width: thin;
  scrollbar-color: #c0c4cc #f5f7fa;
}
.product-tree-scroll::-webkit-scrollbar {
  width: 8px;
}
.product-tree-scroll::-webkit-scrollbar-track {
  background: #f5f7fa;
  border-radius: 4px;
}
.product-tree-scroll::-webkit-scrollbar-thumb {
  background: #c0c4cc;
  border-radius: 4px;
}
.product-tree-scroll::-webkit-scrollbar-thumb:hover {
  background: #909399;
}
</style>
src/views/collaborativeApproval/knowledgeBase/index.vue
@@ -425,8 +425,15 @@
  listKnowledgeBase({...page.value, ...searchForm.value})
  .then(res => {
    tableLoading.value = false;
    tableData.value = res.data.records
    page.value.total = res.data.total;
    // 如果当前页数超过总页数,重置到第1页并重新查询
    const maxPage = Math.ceil(res.data.total / page.value.size) || 1;
    if (page.value.current > maxPage && maxPage > 0) {
      page.value.current = 1;
      // 重新查询第1页数据
      return getList();
    }
    tableData.value = res.data.records;
  }).catch(err => {
    tableLoading.value = false;
  })
@@ -434,9 +441,14 @@
// 分页处理
const pagination = (obj) => {
  const oldSize = page.value.size;
  page.value.current = obj.page;
  page.value.size = obj.limit;
  handleQuery();
  // 如果 size 改变了,重置到第1页,避免当前页超出范围
  if (oldSize !== obj.limit) {
    page.value.current = 1;
  }
  getList();
};
// 选择变化处理
src/views/collaborativeApproval/rulesRegulationsManagement/index.vue
@@ -42,68 +42,15 @@
            </el-button>
          </el-col>
        </el-row>
        <el-table :data="regulations"
                  border
                  v-loading="tableLoading"
                  style="width: 100%">
          <el-table-column prop="regulationNum"
                           label="制度编号"
                           width="120" />
          <el-table-column prop="title"
                           label="制度标题"
                           min-width="150" />
          <el-table-column prop="category"
                           label="分类"
                           width="120">
            <template #default="scope">
              <el-tag>{{ getCategoryText(scope.row.category) }}</el-tag>
            </template>
          </el-table-column>
          <el-table-column prop="version"
                           label="版本"
                           width="120" />
          <el-table-column prop="createUserName"
                           label="发布人"
                           width="120" />
          <el-table-column prop="createTime"
                           label="发布时间"
                           width="180" />
          <el-table-column prop="status"
                           label="状态"
                           width="100">
            <template #default="scope">
              <el-tag :type="scope.row.status === 'active' ? 'success' : 'info'">
                {{ scope.row.status === 'active' ? '生效中' : '已废止' }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column prop="readCount"
                           label="已读人数"
                           width="100" />
          <el-table-column label="操作"
                           width="320"
                           fixed="right">
            <template #default="scope">
              <el-button link
                         @click="viewRegulation(scope.row)">查看</el-button>
              <el-button link
                         type="primary"
                         @click="handleEdit(scope.row)">编辑</el-button>
              <el-button link
                         type="danger"
                         @click="repealEdit(scope.row)">废弃</el-button>
              <el-button link
                         type="success"
                         @click="viewVersionHistory(scope.row)">版本历史</el-button>
              <!-- <el-button link type="warning" @click="viewReadStatus(scope.row)">阅读状态</el-button> -->
              <el-button link
                         type="primary"
                         @click="openFileDialog(scope.row)">附件</el-button>
            </template>
          </el-table-column>
        </el-table>
        <pagination v-show="page.total > 0" :total="page.total" layout="total, sizes, prev, pager, next, jumper"
                    :page="page.current" :limit="page.size" @pagination="paginationChange" />
        <PIMTable
          rowKey="id"
          :column="regulationTableColumn"
          :tableData="regulations"
          :tableLoading="tableLoading"
          :page="page"
          :isShowPagination="true"
          @pagination="paginationChange"
        />
      </div>
    </el-card>
    <!-- 用印申请对话框(已移除) -->
@@ -295,6 +242,7 @@
    delRuleFile,
    addRuleFile,
  } from "@/api/collaborativeApproval/rulesRegulationsManagementFile.js";
  import PIMTable from "@/components/PIMTable/PIMTable.vue";
  // 响应式数据
  const operationType = ref("add");
@@ -363,6 +311,45 @@
  const regulations = ref([]);
  // 表格列配置
  const regulationTableColumn = ref([
    { label: "制度编号", prop: "regulationNum"},
    { label: "制度标题", prop: "title" },
    {
      label: "分类",
      prop: "category",
      dataType: "tag",
      formatData: (v) => getCategoryText(v),
      formatType: () => "info",
    },
    { label: "版本", prop: "version", width: 120 },
    { label: "发布人", prop: "createUserName", width: 120 },
    { label: "发布时间", prop: "createTime", width: 180 },
    {
      label: "状态",
      prop: "status",
      width: 100,
      dataType: "tag",
      formatData: (v) => (v === "active" ? "生效中" : "已废止"),
      formatType: (v) => (v === "active" ? "success" : "info"),
    },
    { label: "已读人数", prop: "readCount", width: 100 },
    {
      dataType: "action",
      label: "操作",
      width: 320,
      fixed: "right",
      align: "center",
      operation: [
        { name: "查看", clickFun: (row) => viewRegulation(row) },
        { name: "编辑", clickFun: (row) => handleEdit(row) },
        { name: "废弃", clickFun: (row) => repealEdit(row) },
        { name: "版本历史", clickFun: (row) => viewVersionHistory(row) },
        { name: "附件", clickFun: (row) => openFileDialog(row) },
      ],
    },
  ]);
  const versionHistory = ref([]);
  const readStatusList = ref([]);
src/views/collaborativeApproval/sealManagement/index.vue
@@ -36,48 +36,15 @@
              </el-col>
            </el-row>
            <el-table :data="sealApplications" border v-loading="tableLoading" style="width: 100%">
              <el-table-column prop="applicationNum" label="申请编号" width="120" />
              <el-table-column prop="title" label="申请标题" min-width="200" />
              <el-table-column prop="createUserName" label="申请人" width="120" />
              <el-table-column prop="department" label="所属部门" width="150" />
              <el-table-column prop="sealType" label="用印类型" width="120">
                <template #default="scope">
                  {{ getSealTypeText(scope.row.sealType) }}
                </template>
              </el-table-column>
              <el-table-column prop="createTime" label="申请时间" width="180" />
              <el-table-column prop="status" label="状态" width="100">
                <template #default="scope">
                  <el-tag :type="getStatusType(scope.row.status)">
                    {{ getStatusText(scope.row.status) }}
                  </el-tag>
                </template>
              </el-table-column>
              <el-table-column label="操作" width="200" fixed="right">
                <template #default="scope">
                  <el-button link @click="viewSealDetail(scope.row)">查看</el-button>
                  <el-button
                    v-if="scope.row.status === 'pending'"
                                        link
                    type="primary"
                    @click="approveSeal(scope.row)"
                  >
                    审批
                  </el-button>
                  <el-button
                    v-if="scope.row.status === 'pending'"
                                        link
                    type="danger"
                    @click="rejectSeal(scope.row)"
                  >
                    拒绝
                  </el-button>
                </template>
              </el-table-column>
            </el-table>
                    <pagination v-show="page.total > 0" :total="page.total" layout="total, sizes, prev, pager, next, jumper"
                                            :page="page.current" :limit="page.size" @pagination="paginationChange" />
            <PIMTable
              rowKey="id"
              :column="sealTableColumn"
              :tableData="sealApplications"
              :tableLoading="tableLoading"
              :page="page"
              :isShowPagination="true"
              @pagination="paginationChange"
            />
        </div> 
    </el-card>
@@ -128,55 +95,6 @@
      </el-form>
    </FormDialog>
    <!-- 规章制度发布对话框 -->
    <!-- <el-dialog v-model="showRegulationDialog" :title="operationType === 'add' ? '发布制度' : '编辑制度'" width="800px">
      <el-form :model="regulationForm" :rules="regulationRules" ref="regulationFormRef" label-width="100px">
        <el-form-item label="制度编号" prop="regulationNum">
          <el-input v-model="regulationForm.regulationNum" placeholder="请输入制度编号" />
        </el-form-item>
        <el-form-item label="制度标题" prop="title">
          <el-input v-model="regulationForm.title" placeholder="请输入制度标题" />
        </el-form-item>
        <el-form-item label="制度分类" prop="category">
          <el-select v-model="regulationForm.category" placeholder="请选择制度分类" style="width: 100%">
            <el-option label="人事制度" value="hr" />
            <el-option label="财务制度" value="finance" />
            <el-option label="安全制度" value="safety" />
            <el-option label="技术制度" value="tech" />
          </el-select>
        </el-form-item>
        <el-form-item label="制度内容" prop="content">
          <el-input v-model="regulationForm.content" type="textarea" :rows="10" placeholder="请输入制度详细内容" />
        </el-form-item>
        <el-form-item label="制度版本" prop="version">
          <el-input v-model="regulationForm.version" placeholder="请输入制度版本" />
        </el-form-item>
        <el-form-item label="生效时间" prop="effectiveTime">
          <el-date-picker v-model="regulationForm.effectiveTime" type="datetime" format="YYYY-MM-DD HH:mm:ss"
             value-format="YYYY-MM-DD HH:mm:ss" placeholder="选择生效时间" style="width: 100%" />
        </el-form-item>
        <el-form-item label="适用范围" prop="scope">
          <el-checkbox-group v-model="regulationForm.scope">
            <el-checkbox label="all">全体员工</el-checkbox>
            <el-checkbox label="manager">管理层</el-checkbox>
            <el-checkbox label="hr">人事部门</el-checkbox>
            <el-checkbox label="finance">财务部门</el-checkbox>
            <el-checkbox label="tech">技术部门</el-checkbox>
          </el-checkbox-group>
        </el-form-item>
        <el-form-item label="是否需要确认" prop="requireConfirm">
          <el-switch v-model="regulationForm.requireConfirm" />
          <span class="ml-10">开启后员工需要阅读确认</span>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="showRegulationDialog = false">取消</el-button>
          <el-button type="primary" @click="submitRegulation">发布制度</el-button>
        </span>
      </template>
    </el-dialog> -->
    <!-- 用印详情对话框 -->
    <FormDialog
      v-model="showSealDetailDialog"
@@ -204,81 +122,6 @@
      </div>
    </FormDialog>
    <!-- 规章制度详情对话框 -->
    <FormDialog
      v-model="showRegulationDetailDialog"
      title="规章制度详情"
      :width="'800px'"
      @close="closeRegulationDetailDialog"
      @confirm="handleRegulationDetailConfirm"
      @cancel="closeRegulationDetailDialog"
    >
      <div v-if="currentRegulationDetail">
        <el-descriptions :column="2" border>
          <el-descriptions-item label="制度编号">{{ currentRegulationDetail.id }}</el-descriptions-item>
          <el-descriptions-item label="制度标题">{{ currentRegulationDetail.title }}</el-descriptions-item>
          <el-descriptions-item label="分类">{{ getCategoryText(currentRegulationDetail.category) }}</el-descriptions-item>
          <el-descriptions-item label="版本">{{ currentRegulationDetail.version }}</el-descriptions-item>
          <el-descriptions-item label="发布人">{{ currentRegulationDetail.createUserName }}</el-descriptions-item>
          <el-descriptions-item label="发布时间">{{ currentRegulationDetail.createTime }}</el-descriptions-item>
        </el-descriptions>
        <div class="mt-20">
          <h4>制度内容</h4>
          <div class="regulation-content">{{ currentRegulationDetail.content }}</div>
        </div>
        <!-- 如果tableData>0 显示 -->
        <div style="margin: 10px 0;" v-if="tableData && tableData.length > 0" >
          <el-button type="success" @click="resetForm(currentRegulationDetail)">确认查看</el-button>
        </div>
      </div>
    </FormDialog>
    <!-- 版本历史对话框 -->
    <FormDialog
      v-model="showVersionHistoryDialog"
      title="版本历史"
      :width="'800px'"
      @close="closeVersionHistoryDialog"
      @confirm="closeVersionHistoryDialog"
      @cancel="closeVersionHistoryDialog"
    >
      <el-table :data="versionHistory" style="width: 100%;margin-bottom: 10px">
        <el-table-column prop="version" label="版本号" width="100" />
        <el-table-column prop="updateTime" label="更新时间" width="180" />
        <el-table-column prop="createUserName" label="更新人" width="120" />
        <el-table-column prop="changeLog" label="变更说明">
          <template #default="scope">
            <el-tag :type="scope.row.status === 'active' ? 'success' : 'info'">
              {{ scope.row.status === 'active' ? '生效中' : '已废止' }}
            </el-tag>
          </template>
        </el-table-column>
      </el-table>
    </FormDialog>
    <!-- 阅读状态对话框 -->
    <FormDialog
      v-model="showReadStatusDialog"
      title="阅读状态"
      :width="'800px'"
      @close="closeReadStatusDialog"
      @confirm="closeReadStatusDialog"
      @cancel="closeReadStatusDialog"
    >
      <el-table :data="readStatusList" style="width: 100%;margin-bottom: 10px">
        <el-table-column prop="employee" label="员工姓名" width="120" />
        <el-table-column prop="department" label="所属部门" width="150" />
        <el-table-column prop="createTime" label="阅读时间" width="180" />
        <el-table-column prop="confirmTime" label="确认时间" width="180" />
        <el-table-column prop="status" label="状态" width="100">
          <template #default="scope">
            <el-tag :type="scope.row.status === 'confirmed' ? 'success' : 'warning'">
              {{ scope.row.status === 'confirmed' ? '已确认' : '未确认' }}
            </el-tag>
          </template>
        </el-table-column>
      </el-table>
    </FormDialog>
  </div>
</template>
@@ -286,20 +129,13 @@
import { ref, reactive, onMounted, getCurrentInstance, watch } from 'vue'
import { useRoute } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus } from '@element-plus/icons-vue'
import { listSealApplication, addSealApplication, updateSealApplication,listRuleManagement,addRuleManagement,updateRuleManagement,delRuleManagement,getReadingStatusByRuleId,getReadingStatusList,addReadingStatus,updateReadingStatus  } from '@/api/collaborativeApproval/sealManagement.js'
import { el } from 'element-plus/es/locales.mjs'
import { getUserProfile, userListNoPageByTenantId } from '@/api/system/user.js'
import { listSealApplication, addSealApplication, updateSealApplication } from '@/api/collaborativeApproval/sealManagement.js'
import { userListNoPageByTenantId } from '@/api/system/user.js'
import useUserStore from '@/store/modules/user'
import { userLoginFacotryList } from "@/api/system/user.js"
import {staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js"
import FormDialog from '@/components/Dialog/FormDialog.vue'
import PIMTable from '@/components/PIMTable/PIMTable.vue'
// 响应式数据
const currentUser = ref(null)
const activeTab = ref('seal')
const operationType = ref('add')
const tableData = ref([])
// 用印申请相关
const userStore = useUserStore()
const route = useRoute()
@@ -335,64 +171,11 @@
// 分页参数
const page = reactive({
  current: 1,
  size: 100,
  size: 10,
  total: 0
})
// 规章制度相关
const showRegulationDialog = ref(false)
const showRegulationDetailDialog = ref(false)
const showVersionHistoryDialog = ref(false)
const showReadStatusDialog = ref(false)
const currentRegulationDetail = ref(null)
const regulationFormRef = ref()
const regulationForm = reactive({
  id: '',
  regulationNum: '',
  title: '',
  category: '',
  content: '',
  version: '',
  status: 'active',
  readCount: 0,
  effectiveTime: '',
  scope: [],
  requireConfirm: false
})
const readStatus = ref({
  id: '',
  ruleId: '',
  employee: '',
  department: '',
  createTime: '',
  confirmTime: '',
  status: 'unconfirmed'
})
const regulationRules = {
  title: [{ required: true, message: '请输入制度标题', trigger: 'blur' }],
  category: [{ required: true, message: '请选择制度分类', trigger: 'change' }],
  content: [{ required: true, message: '请输入制度内容', trigger: 'blur' }],
  effectiveTime: [{ required: true, message: '请选择生效时间', trigger: 'change' }],
  scope: [{ required: true, message: '请选择适用范围', trigger: 'change' }]
}
const regulationSearchForm = reactive({
  title: '',
  category: ''
})
// 假数据
const sealApplications = ref([])
const regulations = ref([])
const versionHistory = ref([])
const readStatusList = ref([])
  // { employee: '陈志强', department: '销售部', readTime: '2025-01-11 10:30:00', confirmTime: '2025-01-11 10:35:00', status: 'confirmed' },
  // { employee: '刘雅婷', department: '技术部', readTime: '2025-01-11 14:20:00', confirmTime: '', status: 'unconfirmed' },
  // { employee: '王建国', department: '财务部', readTime: '2025-01-12 09:15:00', confirmTime: '2025-01-12 09:20:00', status: 'confirmed' }
// 用印申请状态
const getStatusType = (status) => {
@@ -403,7 +186,7 @@
  }
  return statusMap[status] || 'info'
}
// 制度状态
// 用印申请状态文本
const getStatusText = (status) => {
  const statusMap = {
    pending: '待审批',
@@ -418,20 +201,56 @@
    official: '公章',
    contract: '合同专用章',
    finance: '财务专用章',
    legal: '法人章',
    tegal: '技术专用章'
  }
  return sealTypeMap[sealType] || '未知'
}
// 制度分类
const getCategoryText = (category) => {
  const categoryMap = {
    hr: '人事制度',
    finance: '财务制度',
    safety: '安全制度',
    tech: '技术制度'
// 用印申请表格列配置(需在 getStatusText/getSealTypeText 等之后定义)
const sealTableColumn = ref([
  { label: '申请编号', prop: 'applicationNum',},
  { label: '申请标题', prop: 'title', showOverflowTooltip: true },
  { label: '申请人', prop: 'createUserName', },
  { label: '所属部门', prop: 'department', width: 150 },
  {
    label: '用印类型',
    prop: 'sealType',
    dataType: 'tag',
    formatData: (v) => getSealTypeText(v),
    formatType: () => 'info'
  },
  { label: '申请时间', prop: 'createTime', width: 180 },
  {
    label: '状态',
    prop: 'status',
    width: 100,
    dataType: 'tag',
    formatData: (v) => getStatusText(v),
    formatType: (v) => getStatusType(v)
  },
  {
    dataType: 'action',
    label: '操作',
    width: 200,
    fixed: 'right',
    align: 'center',
    operation: [
      { name: '查看', clickFun: (row) => viewSealDetail(row) },
      {
        name: '审批',
        clickFun: (row) => approveSeal(row),
        showHide: (row) => row.status === 'pending'
      },
      {
        name: '拒绝',
        clickFun: (row) => rejectSeal(row),
        showHide: (row) => row.status === 'pending'
      }
    ]
  }
  return categoryMap[category] || '未知'
}
])
// 搜索印章申请
const searchSealApplications = () => {
  page.current=1
@@ -445,17 +264,6 @@
  sealSearchForm.status = ''
  sealSearchForm.applicationNum = ''
  searchSealApplications()
}
// 搜索制度
const searchRegulations = () => {
  page.current=1
  getRegulationList()
}
// 重置制度搜索
const resetRegulationSearch = () => {
  regulationSearchForm.title = ''
  regulationSearchForm.category = ''
  searchRegulations()
}
// 提交用印申请
const submitSealApplication = async () => {
@@ -505,106 +313,6 @@
const closeSealDetailDialog = () => {
  showSealDetailDialog.value = false
}
// 关闭规章制度详情对话框
const closeRegulationDetailDialog = () => {
  showRegulationDetailDialog.value = false
}
// 处理规章制度详情确认
const handleRegulationDetailConfirm = () => {
  // 如果tableData>0,执行确认查看操作
  if (currentRegulationDetail.value && tableData.value && tableData.value.length > 0) {
    resetForm(currentRegulationDetail.value)
  }
  closeRegulationDetailDialog()
}
// 关闭版本历史对话框
const closeVersionHistoryDialog = () => {
  showVersionHistoryDialog.value = false
}
// 关闭阅读状态对话框
const closeReadStatusDialog = () => {
  showReadStatusDialog.value = false
}
// 新增
const handleAdd = () => {
  operationType.value = 'add'
  resetRegulationForm()
  showRegulationDialog.value = true
}
// 编辑
const handleEdit = (row) => {
  operationType.value = 'edit'
  Object.assign(regulationForm, row)
  showRegulationDialog.value = true
}
// 废弃
const repealEdit = (row) => {
  operationType.value = 'edit'
  Object.assign(regulationForm, row)
  regulationForm.status = 'repealed'
  ElMessageBox.confirm('确认废弃该制度?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    updateRuleManagement(regulationForm).then(res => {
      if(res.code == 200){
        ElMessage.success('制度废弃成功')
        // showRegulationDialog.value = false
        getRegulationList()
        resetRegulationForm()
      }
    })
  }).catch(() => {
    ElMessage({
      type: 'info',
      message: '已取消废弃'
    })
  })
}
// 发布制度
const submitRegulation = async () => {
  try {
    await regulationFormRef.value.validate()
    if(operationType.value == 'add'){
      addRuleManagement(regulationForm).then(res => {
        if(res.code == 200){
          ElMessage.success('制度发布成功')
          showRegulationDialog.value = false
          getRegulationList()
          resetRegulationForm()
        }
      })
    }else{
      updateRuleManagement(regulationForm).then(res => {
        if(res.code == 200){
          ElMessage.success('制度编辑成功')
          showRegulationDialog.value = false
          resetRegulationForm()
          getRegulationList()
      }})}
  }catch(err){
    ElMessage.error(err.msg)
  }
}
//重置制度表单
const resetRegulationForm = () => {
  Object.assign(regulationForm, {
    id: '',
    regulationNum: '',
    title: '',
    category: '',
    content: '',
    version: '',
    status: 'active',
    readCount: 0,
    effectiveTime: '',
    scope: [],
    requireConfirm: false
})
}
// 查看用印申请详情
const viewSealDetail = (row) => {
@@ -613,7 +321,6 @@
}
// 审批用印申请
const approveSeal = (row) => {
  console.log(row)
  ElMessageBox.confirm('确认通过该用印申请?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
@@ -623,6 +330,7 @@
    updateSealApplication(row).then(res => {
      if(res.code == 200){
        ElMessage.success('审批通过')
        getSealApplicationList()
      }
    })
  })
@@ -638,122 +346,10 @@
    row.status = 'rejected'
    updateSealApplication(row).then(res => {
      if(res.code == 200){
        ElMessage.success('审批拒绝')
        ElMessage.success('已拒绝申请')
        getSealApplicationList()
      }
    })
    ElMessage.success('已拒绝申请')
  })
}
// 获取在职员工列表
const getList = () => {
  tableLoading.value = true;
      //获取当前登录用户信息
  getUserProfile().then(res => {
    if(res.code == 200){
      console.log(res.data.userName)
      currentUser.value = res.data.userName
    }
  })
  staffOnJobListPage({staffState: 1, ...page}).then(res => {
    tableLoading.value = false;
    // tableData.value = res.data.records
    // //筛选出和currentUser同名的人员
    tableData.value = res.data.records.filter(item => item.staffName === currentUser.value)
    page.total = res.data.total;
    if(tableData.value.length == 0){
    ElMessage.error('当前用户未加入任何部门')
    }
  }).catch(err => {
    tableLoading.value = false;
  })
};
// 查看制度版本历史
const viewVersionHistory = (row) => {
  showVersionHistoryDialog.value = true
  const params = {
    category: row.category
  }
  listRuleManagement(page,params).then(res => {
    if(res.code == 200){
      versionHistory.value = res.data.records
    }
  })
}
// 查看制度详情
const viewRegulation = (row) => {
  getList()
  currentRegulationDetail.value = row
  showRegulationDetailDialog.value = true
  getReadingStatusByRuleId(row.id).then(res => {
    if(res.code == 200){
      readStatusList.value = res.data
      if(readStatusList.value.length==0 && tableData.value.length>0){
          const params = {
          ruleId: row.id,
          employee: tableData.value[0].staffName,
          department: tableData.value[0].postJob,
          status: 'unconfirmed'
        }
        addReadingStatus(params).then(res => {
          if(res.code == 200){
            ElMessage.success('制度阅读成功')
          }
        })
      }
    }
  })
}
// 查看制度阅读状态
const viewReadStatus = (row) => {
  showReadStatusDialog.value = true
  //查看阅读状态列表
  getReadingStatusByRuleId(row.id).then(res => {
    if(res.code == 200){
      readStatusList.value = res.data
    }
  })
}
//确认查看
const resetForm = (row) => {
  console.log("row",row)
  row.readCount = row.readCount + 1
  updateRuleManagement(row).then(res => {
    if(res.code == 200){
      ElMessage.success('查看数量修改成功')
      //修改阅读状态
      //根据制度id和当前登录的员工得到阅读状态
      // let item = readStatusList.value.filter(item => item.employee == tableData.value[0].staffName )
      // if(item.length>0){
      //   item[0].status = 'confirmed',
      //   item[0].confirmTime = new Date().toISOString().replace('T', ' ').split('.')[0];
      // }
      // 筛选当前员工对应该制度的阅读状态记录
      let statusItem = readStatusList.value.find(item => item.employee === tableData.value[0].staffName && item.ruleId === row.id);
      if (statusItem) {
        // 如果找到记录,更新状态和确认时间
        statusItem.status = 'confirmed';
        // 格式化时间为"YYYY-MM-DD HH:mm:ss"格式
        const now = new Date();
        statusItem.confirmTime = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}:${String(now.getSeconds()).padStart(2, '0')}`;
        // statusItem.confirmTime = new Date().toISOString().replace('T', ' ').split('.')[0];
        updateReadingStatus(statusItem).then(res => {
          if(res.code == 200){
            ElMessage.success('制度阅读状态修改成功')
          }
        })
      }
    }
  })
}
@@ -766,46 +362,15 @@
// 获取印章申请列表数据
const getSealApplicationList = async () => {
  tableLoading.value = true
  listSealApplication(page,sealSearchForm)
  listSealApplication(page, sealSearchForm)
  .then(res => {
    //获取当前登录的部门信息
// 获取当前登录的部门信息并过滤数据
    const currentFactoryName = userStore.currentFactoryName
    if (currentFactoryName) {
      // 根据currentFactoryName过滤出department相同的数据
      sealApplications.value = res.data.records.filter(item => item.department === currentFactoryName)
      // 更新过滤后的总数
      page.total = sealApplications.value.length
    } else {
      // 如果没有currentFactoryName,则显示所有数据
      sealApplications.value = res.data.records
      page.total = res.data.total
    }
    // sealApplications.value = res.data.records
    // page.value.total = res.data.total;
    tableLoading.value = false;
    sealApplications.value = res.data.records
    page.total = res.data.total
    tableLoading.value = false
  }).catch(err => {
    tableLoading.value = false;
    tableLoading.value = false
  })
}
// 获取规章制度列表数据
const getRegulationList = async () => {
  tableLoading.value = true
  listRuleManagement(page,regulationSearchForm)
  .then(res => {
    regulations.value = res.data.records
    // 过滤掉已废弃的制度
    // regulations.value = res.data.records.filter(item => item.status !== 'repealed')
    page.total = res.data.total;
    tableLoading.value = false;
  }).catch(err => {
    tableLoading.value = false;
  })
}
// 分页变化处理
const paginationChange = (obj) => {
  page.current = obj.page;
@@ -831,7 +396,6 @@
  } else {
    getSealApplicationList()
  }
  getRegulationList()
})
</script>
@@ -854,26 +418,7 @@
  margin-bottom: 20px;
}
.mt-20 {
  margin-top: 20px;
}
.ml-10 {
  margin-left: 10px;
}
.regulation-content {
  background-color: #f5f5f5;
  padding: 15px;
  border-radius: 4px;
  line-height: 1.6;
  white-space: pre-wrap;
  height: 200px;
}
.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}
</style>
src/views/index.vue
@@ -118,11 +118,11 @@
            <div class="main-panel">
                <div style="display: flex;justify-content: space-between;">
                    <div class="section-title">应收应付统计</div>
                    <el-radio-group v-model="radio1" size="large" @change="statisticsReceivable">
                        <el-radio-button label="按周" :value="1" />
                        <el-radio-button label="按月" :value="2" />
                        <el-radio-button label="按季度" :value="3" />
                    </el-radio-group>
<!--                    <el-radio-group v-model="radio1" size="large" @change="statisticsReceivable">-->
<!--                        <el-radio-button label="按周" :value="1" />-->
<!--                        <el-radio-button label="按月" :value="2" />-->
<!--                        <el-radio-button label="按季度" :value="3" />-->
<!--                    </el-radio-group>-->
                </div>
                <Echarts ref="chart"
                                 :color="barColors2"
src/views/procurementManagement/procurementLedger/index.vue
@@ -157,6 +157,10 @@
                         prop="entryDate"
                         width="100"
                         show-overflow-tooltip />
        <el-table-column label="备注"
                         prop="remarks"
                         width="200"
                         show-overflow-tooltip />
        <el-table-column fixed="right"
                         label="操作"
                         width="120"
@@ -450,8 +454,8 @@
        <el-row :gutter="30">
          <el-col :span="24">
            <el-form-item label="备注·:"
                          prop="remark">
              <el-input v-model="form.remark"
                          prop="remarks">
              <el-input v-model="form.remarks"
                        placeholder="请输入"
                        clearable
                        type="textarea"
@@ -462,7 +466,7 @@
        <el-row :gutter="30">
          <el-col :span="24">
            <el-form-item label="附件材料:"
                          prop="remark">
                          prop="purchaseLedgerFiles">
              <el-upload v-model:file-list="fileList"
                         :action="upload.url"
                         multiple
src/views/productionManagement/productionOrder/index.vue
@@ -239,8 +239,9 @@
  // 添加表行类名方法
  const tableRowClassName = ({ row }) => {
    const diff = row.deliveryDaysDiff;
    if (row.isFh) return '';
    const diff = row.deliveryDaysDiff;
    if (diff === 15) {
      return 'yellow';
    } else if (diff === 10) {
src/views/qualityManagement/finalInspection/components/formDia.vue
@@ -201,64 +201,91 @@
const openDialog = async (type, row) => {
  operationType.value = type;
  dialogFormVisible.value = true;
  getOptions().then((res) => {
    supplierList.value = res.data;
  });
    let userLists = await userListNoPage();
    userList.value = userLists.data;
    form.value = {}
  // 先清空表单验证状态,避免闪烁
  await nextTick();
  proxy.$refs.formRef?.clearValidate();
  // 并行加载基础数据
  const [userListsRes] = await Promise.all([
    userListNoPage(),
    getProductOptions(),
    getOptions().then((res) => {
      supplierList.value = res.data;
    })
  ]);
  userList.value = userListsRes.data;
  form.value = {}
  testStandardOptions.value = [];
  tableData.value = [];
  getProductOptions();
  if (operationType.value === 'edit') {
    // 先保存 testStandardId,避免被清空
    const savedTestStandardId = row.testStandardId;
    // 先设置表单数据,但暂时清空 testStandardId,等选项加载完成后再设置
    form.value = {...row, testStandardId: ''}
        currentProductId.value = row.productId || 0
        // 编辑模式下,先加载指标选项,然后加载参数列表
        if (currentProductId.value) {
            // 先加载指标选项
            let params = {
                productId: currentProductId.value,
                inspectType: 2
            }
            qualityInspectDetailByProductId(params).then(res => {
                testStandardOptions.value = res.data || [];
                // 使用 nextTick 和 setTimeout 确保选项已经渲染到 DOM
                nextTick(() => {
                    setTimeout(() => {
                        // 如果编辑数据中有 testStandardId,则设置并加载对应的参数
                        if (savedTestStandardId) {
                            // 确保类型匹配(item.id 可能是数字或字符串)
                            const matchedOption = testStandardOptions.value.find(item =>
                                item.id == savedTestStandardId || String(item.id) === String(savedTestStandardId)
                            );
                            if (matchedOption) {
                                // 确保使用匹配项的 id(保持类型一致)
                                form.value.testStandardId = matchedOption.id;
                                // 编辑场景保留已有检验值,直接拉取原参数数据
                                getQualityInspectParamList(row.id);
                            } else {
                                // 如果找不到匹配项,尝试直接使用原值
                                console.warn('未找到匹配的指标选项,testStandardId:', savedTestStandardId, '可用选项:', testStandardOptions.value);
                                form.value.testStandardId = savedTestStandardId;
                                getQualityInspectParamList(row.id);
                            }
                        } else {
                            // 否则使用旧的逻辑
                            getQualityInspectParamList(row.id);
                        }
                    }, 100);
                });
            });
        } else {
            getQualityInspectParamList(row.id);
        }
    currentProductId.value = row.productId || 0
    // 清空验证状态,避免数据加载过程中的校验闪烁
    nextTick(() => {
      proxy.$refs.formRef?.clearValidate();
    });
    // 编辑模式下,并行加载规格型号和指标选项
    if (currentProductId.value) {
      // 设置产品名称
      form.value.productName = findNodeById(productOptions.value, currentProductId.value);
      // 并行加载规格型号和指标选项
      const params = {
        productId: currentProductId.value,
        inspectType: 2
      };
      Promise.all([
        modelList({ id: currentProductId.value }),
        qualityInspectDetailByProductId(params)
      ]).then(([modelRes, testStandardRes]) => {
        // 设置规格型号选项
        modelOptions.value = modelRes || [];
        // 如果表单中已有 productModelId,设置对应的 model 和 unit
        if (form.value.productModelId && modelOptions.value.length > 0) {
          const selectedModel = modelOptions.value.find(item => item.id == form.value.productModelId);
          if (selectedModel) {
            form.value.model = selectedModel.model || '';
            form.value.unit = selectedModel.unit || '';
          }
        }
        // 设置指标选项
        testStandardOptions.value = testStandardRes.data || [];
        // 设置 testStandardId 并加载参数列表
        nextTick(() => {
          if (savedTestStandardId) {
            // 确保类型匹配(item.id 可能是数字或字符串)
            const matchedOption = testStandardOptions.value.find(item =>
              item.id == savedTestStandardId || String(item.id) === String(savedTestStandardId)
            );
            if (matchedOption) {
              // 确保使用匹配项的 id(保持类型一致)
              form.value.testStandardId = matchedOption.id;
            } else {
              // 如果找不到匹配项,尝试直接使用原值
              console.warn('未找到匹配的指标选项,testStandardId:', savedTestStandardId, '可用选项:', testStandardOptions.value);
              form.value.testStandardId = savedTestStandardId;
            }
          }
          // 编辑场景保留已有检验值,直接拉取原参数数据
          getQualityInspectParamList(row.id);
        });
      });
    } else {
      getQualityInspectParamList(row.id);
    }
  }
}
const getProductOptions = () => {
  productTreeList().then((res) => {
  return productTreeList().then((res) => {
    productOptions.value = convertIdToValue(res);
  });
};
src/views/qualityManagement/finalInspection/index.vue
@@ -96,6 +96,11 @@
    width: 120
  },
  {
    label: "生产工单号",
    prop: "workOrderNo",
    width: 120
  },
  {
    label: "检验员",
    prop: "checkName",
  },
src/views/qualityManagement/processInspection/index.vue
@@ -96,6 +96,11 @@
    width: 120
  },
  {
    label: "生产工单号",
    prop: "workOrderNo",
    width: 120
  },
  {
    label: "工序",
    prop: "process",
    width: 230
src/views/qualityManagement/rawMaterialInspection/index.vue
@@ -98,6 +98,11 @@
    width: 120
  },
  {
    label: "采购订单号",
    prop: "purchaseContractNo",
    width: 120
  },
  {
    label: "供应商",
    prop: "supplier",
    width: 230
src/views/reportAnalysis/productionAnalysis/components/right-top.vue
@@ -2,25 +2,16 @@
  <div>
    <PanelHeader title="工单执行效率分析" />
    <div class="main-panel panel-item-customers">
      <Echarts
        ref="chart"
        :chartStyle="chartStyle"
        :grid="grid"
        :legend="barLegend"
        :series="chartSeries"
        :tooltip="tooltip"
        :xAxis="xAxis1"
        :yAxis="yAxis1"
        :options="{ backgroundColor: 'transparent', textStyle: { color: '#B8C8E0' } }"
        style="height: 260px"
      />
      <Echarts ref="chart" :chartStyle="chartStyle" :grid="grid" :legend="barLegend" :series="chartSeries"
        :tooltip="tooltip" :xAxis="xAxis1" :yAxis="yAxis1"
        :options="{ backgroundColor: 'transparent', textStyle: { color: '#B8C8E0' } }" style="height: 260px" />
    </div>
  </div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { qualityStatistics } from '@/api/viewIndex.js'
import { workOrderEfficiencyAnalysis } from '@/api/viewIndex.js'
import PanelHeader from './PanelHeader.vue'
import Echarts from '@/components/Echarts/echarts.vue'
@@ -37,7 +28,6 @@
  data: ['开工', '完成', '良品率'],
}
// 柱状图:开工、完成;折线图:良品率(颜色 rgba(90, 216, 166, 1))
const chartSeries = ref([
  {
    name: '开工',
@@ -111,6 +101,7 @@
const xAxis1 = ref([
  { type: 'category', axisTick: { show: false }, axisLabel: { color: '#B8C8E0' }, data: [] },
])
const yAxis1 = [
  { type: 'value', name: '件', axisLabel: { color: '#B8C8E0' }, nameTextStyle: { color: '#B8C8E0' } },
  {
@@ -125,25 +116,23 @@
]
const fetchData = () => {
  qualityStatistics()
  workOrderEfficiencyAnalysis()
    .then((res) => {
      if (!res?.data?.item || !Array.isArray(res.data.item)) return
      const items = res.data.item
      xAxis1.value[0].data = items.map((d) => d.date)
      // 开工:过程检验数
      chartSeries.value[0].data = items.map((d) => Number(d.processNum) || 0)
      // 完成:出厂数
      chartSeries.value[1].data = items.map((d) => Number(d.factoryNum) || 0)
      // 良品率:出厂数/过程数*100(无单独接口时用此占位)
      chartSeries.value[2].data = items.map((d) => {
        const processNum = Number(d.processNum) || 0
        const factoryNum = Number(d.factoryNum) || 0
        if (processNum <= 0) return 0
        return Math.min(100, Math.round((factoryNum / processNum) * 100))
      })
      // 根据你的结构,数据直接在 res.data 中
      if (!res?.data || !Array.isArray(res.data)) return
      const list = res.data
      xAxis1.value[0].data = list.map((item) => item.date)
      chartSeries.value[0].data = list.map((item) => Number(item.startQuantity) || 0)
      chartSeries.value[1].data = list.map((item) => Number(item.finishQuantity) || 0)
      chartSeries.value[2].data = list.map((item) => Number(item.yieldRate) || 0)
    })
    .catch((err) => {
      console.error('获取开工与良品率数据失败:', err)
      console.error('获取工单效率数据失败:', err)
    })
}
src/views/safeProduction/dangerInvestigation/index.vue
@@ -111,13 +111,13 @@
        </el-table-column>
        <el-table-column fixed="right"
                         label="操作"
                         min-width="250"
                         min-width="150"
                         align="center">
          <template #default="scope">
            <el-button link
            <!-- <el-button link
                       type="primary"
                       size="small"
                       @click="openForm('edit', scope.row)">编辑</el-button>
                       @click="openForm('edit', scope.row)">编辑</el-button> -->
            <el-button link
                       type="primary"
                       size="small"
@@ -125,12 +125,12 @@
            <el-button link
                       type="primary"
                       size="small"
                       :disabled="scope.row.isRectify"
                       :disabled="scope.row.isRectify || scope.row.rectifyActualTime"
                       @click="openForm('edit2', scope.row)">整改</el-button>
            <el-button link
                       type="primary"
                       size="small"
                       :disabled="!scope.row.rectifyActualTime"
                       :disabled="!scope.row.rectifyActualTime || scope.row.verifyTime"
                       @click="openForm('edit3', scope.row)">验收</el-button>
          </template>
        </el-table-column>
src/views/salesManagement/salesLedger/index.vue
@@ -118,6 +118,7 @@
        <el-table-column label="录入日期" prop="entryDate" width="120" show-overflow-tooltip />
        <el-table-column label="签订日期" prop="executionDate" width="120" show-overflow-tooltip />
        <el-table-column label="交付日期" prop="deliveryDate" width="120" show-overflow-tooltip />
        <el-table-column label="备注" prop="remarks" width="200" 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="openForm('edit', scope.row)">编辑</el-button>
@@ -242,14 +243,14 @@
                </el-table>
                <el-row :gutter="30">
                    <el-col :span="24">
                        <el-form-item label="备注·:" prop="remark">
                            <el-input v-model="form.remark" placeholder="请输入" clearable type="textarea" :rows="2" :disabled="operationType === 'view'" />
                        <el-form-item label="备注:" prop="remarks">
                            <el-input v-model="form.remarks" placeholder="请输入" clearable type="textarea" :rows="2" :disabled="operationType === 'view'" />
                        </el-form-item>
                    </el-col>
                </el-row>
                <el-row :gutter="30">
                    <el-col :span="24">
                        <el-form-item label="附件材料:" prop="remark">
                        <el-form-item label="附件材料:" prop="salesLedgerFiles">
                            <el-upload v-model:file-list="fileList" :action="upload.url" multiple ref="fileUpload" auto-upload
                                                 :headers="upload.headers" :before-upload="handleBeforeUpload" :on-error="handleUploadError"
                                                 :on-success="handleUploadSuccess" :on-remove="handleRemove">
@@ -1004,8 +1005,9 @@
// 添加表行类名方法
const tableRowClassName = ({ row }) => {
  const diff = row.deliveryDaysDiff;
  if (row.isFh) return '';
  const diff = row.deliveryDaysDiff;
  if (diff === 15) {
    return 'yellow';
  } else if (diff === 10) {
src/views/salesManagement/salesQuotation/index.vue
@@ -231,43 +231,52 @@
            <el-table :data="form.products" border style="width: 100%" class="product-table" v-if="form.products.length > 0">
            <el-table-column prop="product" label="产品名称" width="200">
              <template #default="scope">
                                <el-tree-select
                                    v-model="scope.row.productId"
                                    placeholder="请选择"
                                    clearable
                                    check-strictly
                                    @change="getModels($event, scope.row)"
                                    :data="productOptions"
                                    :render-after-expand="false"
                                    style="width: 100%"
                                />
                <el-form-item :prop="`products.${scope.$index}.productId`" class="product-table-form-item">
                  <el-tree-select
                    v-model="scope.row.productId"
                    placeholder="请选择"
                    clearable
                    check-strictly
                    @change="getModels($event, scope.row)"
                    :data="productOptions"
                    :render-after-expand="false"
                    style="width: 100%"
                  />
                </el-form-item>
              </template>
            </el-table-column>
            <el-table-column prop="specification" label="规格型号" width="150">
            <el-table-column prop="specification" label="规格型号" width="200">
              <template #default="scope">
                                <el-select
                                    v-model="scope.row.specificationId"
                                    placeholder="请选择"
                                    clearable
                                    @change="getProductModel($event, scope.row)"
                                >
                                    <el-option
                                        v-for="item in scope.row.modelOptions || []"
                                        :key="item.id"
                                        :label="item.model"
                                        :value="item.id"
                                    />
                                </el-select>
                <el-form-item :prop="`products.${scope.$index}.specificationId`" class="product-table-form-item">
                  <el-select
                    v-model="scope.row.specificationId"
                    placeholder="请选择"
                    clearable
                    @change="getProductModel($event, scope.row)"
                    style="width: 100%"
                  >
                    <el-option
                      v-for="item in scope.row.modelOptions || []"
                      :key="item.id"
                      :label="item.model"
                      :value="item.id"
                    />
                  </el-select>
                </el-form-item>
              </template>
            </el-table-column>
            <el-table-column prop="unit" label="单位">
              <template #default="scope">
                <el-input v-model="scope.row.unit" placeholder="单位" />
                <el-form-item :prop="`products.${scope.$index}.unit`" class="product-table-form-item">
                  <el-input v-model="scope.row.unit" placeholder="单位" clearable/>
                </el-form-item>
              </template>
            </el-table-column>
            <el-table-column prop="unitPrice" label="单价">
              <template #default="scope">
                <el-input-number v-model="scope.row.unitPrice" :min="0" :precision="2" style="width: 100%" />
                <el-form-item :prop="`products.${scope.$index}.unitPrice`" class="product-table-form-item">
                  <el-input-number v-model="scope.row.unitPrice" :min="0" :precision="2" style="width: 100%" />
                </el-form-item>
              </template>
            </el-table-column>
            <el-table-column label="操作" width="80" align="center">
@@ -393,13 +402,30 @@
  totalAmount: 0
})
const rules = {
const baseRules = {
  customer: [{ required: true, message: '请选择客户', trigger: 'change' }],
  salesperson: [{ required: true, message: '请选择业务员', trigger: 'change' }],
  quotationDate: [{ required: true, message: '请选择报价日期', trigger: 'change' }],
  validDate: [{ required: true, message: '请选择有效期', trigger: 'change' }],
  paymentMethod: [{ required: true, message: '请输入付款方式', trigger: 'blur' }]
}
const productRowRules = {
  productId: [{ required: true, message: '请选择产品名称', trigger: 'change' }],
  specificationId: [{ required: true, message: '请选择规格型号', trigger: 'change' }],
  unit: [{ required: true, message: '请填写单位', trigger: 'blur' }],
  unitPrice: [{ required: true, message: '请填写单价', trigger: 'change' }]
}
const rules = computed(() => {
  const r = { ...baseRules }
  ;(form.products || []).forEach((_, i) => {
    r[`products.${i}.productId`] = productRowRules.productId
    r[`products.${i}.specificationId`] = productRowRules.specificationId
    r[`products.${i}.unit`] = productRowRules.unit
    r[`products.${i}.unitPrice`] = productRowRules.unitPrice
  })
  return r
})
const userList = ref([]);
const customerOption = ref([]);
@@ -774,7 +800,7 @@
        ElMessage.warning('请至少添加一个产品')
        return
      }
      // 审批人必填校验
      const hasEmptyApprover = approverNodes.value.some(node => !node.userId)
      if (hasEmptyApprover) {
@@ -956,6 +982,17 @@
  padding: 8px 0;
}
.product-table-form-item {
  margin-bottom: 0;
  :deep(.el-form-item__content) {
    margin-left: 0 !important;
  }
  :deep(.el-form-item__label) {
    width: auto;
    min-width: auto;
  }
}
.approver-nodes-container {
  display: flex;
  flex-wrap: wrap;