buhuazhen
5 天以前 d0b2606e410257ebb73c05aeaeac079dc5db81f0
Merge remote-tracking branch 'origin/dev_NEW_pro' into dev_NEW_pro
已添加15个文件
已修改13个文件
816 ■■■■ 文件已修改
multiple/assets/favicon/HYJCfavicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/favicon/HYLQfavicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/favicon/JXJHfavicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/favicon/QXYfavicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/favicon/XSWHfavicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/favicon/YTJZfavicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/favicon/ZQSYfavicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/logo/HYJCLogo.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/logo/HYLQLogo.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/logo/JXJHLogo.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/logo/QXYLogo.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/logo/XSWHLogo.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/logo/YTJZLogo.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/logo/ZQSYLogo.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/config.json 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/inventoryManagement/stockInventory.js 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicData/supplierManage/components/BlacklistTab.vue 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicData/supplierManage/components/HomeTab.vue 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/approvalProcess/index.vue 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/inspectionManagement/components/formDia.vue 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/inspectionManagement/index.vue 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/measurementEquipment/index.vue 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/repair/Modal/MaintainModal.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/stockManagement/BatchNoQtyDetail.vue 227 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/stockManagement/Record.vue 354 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/safeProduction/safeWorkApproval/components/infoFormDia.vue 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/salesLedger/index.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/favicon/HYJCfavicon.ico
multiple/assets/favicon/HYLQfavicon.ico
multiple/assets/favicon/JXJHfavicon.ico
multiple/assets/favicon/QXYfavicon.ico
multiple/assets/favicon/XSWHfavicon.ico
multiple/assets/favicon/YTJZfavicon.ico
multiple/assets/favicon/ZQSYfavicon.ico
multiple/assets/logo/HYJCLogo.png
multiple/assets/logo/HYLQLogo.png
multiple/assets/logo/JXJHLogo.png
multiple/assets/logo/QXYLogo.png
multiple/assets/logo/XSWHLogo.png
multiple/assets/logo/YTJZLogo.png
multiple/assets/logo/ZQSYLogo.png
multiple/config.json
@@ -96,6 +96,60 @@
    "logo": "logo/DYKJLogo.png",
    "favicon": "favicon/DYKJfavicon.ico"
  },
  "ZQSY": {
    "env": {
      "VITE_APP_TITLE": "泽淇实业",
      "VITE_BASE_API": "http://36.213.128.159:9000",
      "VITE_JAVA_API": "http://36.213.128.159:9001"
    },
    "logo": "logo/ZQSYLogo.png",
    "favicon": "favicon/ZQSYfavicon.ico"
  },
  "JXJH": {
    "env": {
      "VITE_APP_TITLE": "浚县江海水泥制品有限公司",
      "VITE_BASE_API": "http://36.139.201.20:9000",
      "VITE_JAVA_API": "http://36.139.201.20:9001"
    },
    "logo": "logo/JXJHLogo.png",
    "favicon": "favicon/JXJHfavicon.ico"
  },
  "YTJZ": {
    "env": {
      "VITE_APP_TITLE": "豫泰建筑材料有限公司",
      "VITE_BASE_API": "http://36.139.201.181:9000",
      "VITE_JAVA_API": "http://36.139.201.181:9001"
    },
    "logo": "logo/YTJZLogo.png",
    "favicon": "favicon/YTJZfavicon.ico"
  },
  "HYLQ": {
    "env": {
      "VITE_APP_TITLE": "航逸路桥工程有限公司",
      "VITE_BASE_API": "http://36.139.202.111:9000",
      "VITE_JAVA_API": "http://36.139.202.111:9001"
    },
    "logo": "logo/HYLQLogo.png",
    "favicon": "favicon/HYLQfavicon.ico"
  },
  "QXY": {
    "env": {
      "VITE_APP_TITLE": "强信宇电器云主机",
      "VITE_BASE_API": "http://36.134.154.10:9000",
      "VITE_JAVA_API": "http://36.134.154.10:9001"
    },
    "logo": "logo/QXYLogo.png",
    "favicon": "favicon/QXYfavicon.ico"
  },
  "HYJC": {
    "env": {
      "VITE_APP_TITLE": "恒洋建材",
      "VITE_BASE_API": "http://36.138.94.178:9000",
      "VITE_JAVA_API": "http://36.138.94.178:9001"
    },
    "logo": "logo/HYJCLogo.png",
    "favicon": "favicon/HYJCfavicon.ico"
  },
  "logo": "/src/assets/logo/logo.png",
  "favicon": "/public/favicon.ico"
}
src/api/inventoryManagement/stockInventory.js
@@ -17,6 +17,14 @@
    });
};
export const getStockInventoryBatchNoQty = (params) => {
    return request({
        url: "/stockInventory/getBatchNoQty",
        method: "get",
        params,
    });
};
// åˆ›å»ºåº“存记录
export const createStockInventory = (params) => {
    return request({
src/views/basicData/supplierManage/components/BlacklistTab.vue
@@ -231,7 +231,10 @@
        </div>
      </template>
    </el-dialog>
    <files-dia ref="filesDia"></files-dia>
    <FileList v-if="fileListDialogVisible"
              v-model:visible="fileListDialogVisible"
              record-type="supplier_manage"
              :record-id="recordId" />
  </div>
</template>
@@ -249,7 +252,9 @@
} from "@/api/basicData/supplierManageFile.js";
import useUserStore from "@/store/modules/user";
import { getToken } from "@/utils/auth.js";
import FilesDia from "../filesDia.vue";
const FileList = defineAsyncComponent(() =>
    import("@/components/Dialog/FileList.vue")
);
const { proxy } = getCurrentInstance();
const userStore = useUserStore();
@@ -327,7 +332,7 @@
        name: "资质文件",
        type: "text",
        clickFun: (row) => {
          openFilesFormDia(row)
          openFileDialog(row)
        }
      }
    ],
@@ -342,7 +347,8 @@
  size: 100,
  total: 0,
});
const filesDia = ref()
const fileListDialogVisible = ref(false);
const recordId = ref();
// ç”¨æˆ·ä¿¡æ¯è¡¨å•弹框数据
const operationType = ref("");
const dialogFormVisible = ref(false);
@@ -567,10 +573,9 @@
  return `${year}-${month}-${day}`;
}
// æ‰“开附件弹框
const openFilesFormDia = (row) => {
  nextTick(() => {
    filesDia.value?.openDialog(row)
  })
const openFileDialog = async row => {
  recordId.value = row.id;
  fileListDialogVisible.value = true;
};
onMounted(() => {
src/views/basicData/supplierManage/components/HomeTab.vue
@@ -237,7 +237,10 @@
        </div>
      </template>
    </el-dialog>
    <files-dia ref="filesDia"></files-dia>
    <FileList v-if="fileListDialogVisible"
              v-model:visible="fileListDialogVisible"
              record-type="supplier_manage"
              :record-id="recordId" />
  </div>
</template>
@@ -255,7 +258,9 @@
} from "@/api/basicData/supplierManageFile.js";
import useUserStore from "@/store/modules/user";
import { getToken } from "@/utils/auth.js";
import FilesDia from "../filesDia.vue";
const FileList = defineAsyncComponent(() =>
    import("@/components/Dialog/FileList.vue")
);
const { proxy } = getCurrentInstance();
const userStore = useUserStore();
@@ -333,7 +338,7 @@
        name: "资质文件",
        type: "text",
        clickFun: (row) => {
          openFilesFormDia(row)
          openFileDialog(row)
        }
      }
    ],
@@ -343,12 +348,13 @@
const selectedRows = ref([]);
const userList = ref([]);
const tableLoading = ref(false);
const fileListDialogVisible = ref(false);
const recordId = ref();
const page = reactive({
  current: 1,
  size: 100,
  total: 0,
});
const filesDia = ref()
// ç”¨æˆ·ä¿¡æ¯è¡¨å•弹框数据
const operationType = ref("");
const dialogFormVisible = ref(false);
@@ -573,10 +579,9 @@
  return `${year}-${month}-${day}`;
}
// æ‰“开附件弹框
const openFilesFormDia = (row) => {
  nextTick(() => {
    filesDia.value?.openDialog(row)
  })
const openFileDialog = async row => {
  recordId.value = row.id;
  fileListDialogVisible.value = true;
};
onMounted(() => {
src/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue
@@ -152,7 +152,8 @@
    startDate: "", // è¯·å‡å¼€å§‹æ—¶é—´
    endDate: "", // è¯·å‡ç»“束时间
    price: null, // æŠ¥é”€é‡‘额
    location: "" // å‡ºå·®åœ°ç‚¹
    location: "", // å‡ºå·®åœ°ç‚¹
    storageBlobDTOS: []
  },
  rules: {
    approveId: [{ required: false, message: "请输入", trigger: "blur" }],
@@ -270,7 +271,7 @@
      return
    }
  }
  form.value.storageBlobDTOList = fileList.value
  form.value.storageBlobDTOS = fileList.value
  proxy.$refs.formRef.validate(valid => {
    if (valid) {
src/views/collaborativeApproval/approvalProcess/index.vue
@@ -126,20 +126,23 @@
    <!-- å¼¹çª—组件 -->
    <info-form-dia ref="infoFormDia" @close="handleQuery" :approveType="currentApproveType"></info-form-dia>
    <approval-dia ref="approvalDia" @close="handleQuery" :approveType="currentApproveType"></approval-dia>
    <FileList ref="fileListRef" />
    <FileList v-if="fileDialogVisible"
              v-model:visible="fileDialogVisible"
              record-type="approve_process"
              :record-id="recordId" />
  </div>
</template>
<script setup>
import FileList from "./fileList.vue";
import { Search, Plus, Delete, Download, RefreshRight, DocumentChecked } from "@element-plus/icons-vue";
import {onMounted, ref, computed, reactive, toRefs, nextTick, getCurrentInstance} from "vue";
import {onMounted, ref, computed, reactive, toRefs, nextTick, getCurrentInstance, defineAsyncComponent} from "vue";
import {ElMessageBox} from "element-plus";
import { useRoute } from 'vue-router';
import InfoFormDia from "@/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue";
import ApprovalDia from "@/views/collaborativeApproval/approvalProcess/components/approvalDia.vue";
import {approveProcessDelete, approveProcessListPage} from "@/api/collaborativeApproval/approvalProcess.js";
import useUserStore from "@/store/modules/user";
const FileList = defineAsyncComponent(() => import("@/components/Dialog/FileList.vue"));
const userStore = useUserStore();
const route = useRoute();
@@ -337,7 +340,7 @@
      name: "附件",
      type: "text",
      clickFun: (row) => {
        downLoadFile(row);
        openFilesFormDia(row);
      },
    });
  }
@@ -371,11 +374,17 @@
  page.current = 1;
  getList();
};
const fileListRef = ref(null)
const downLoadFile = (row) => {
  fileListRef.value.open(row.commonFileList)
// æ‰“开附件弹窗
const recordId =ref(0)
const fileDialogVisible = ref(false)
// æ‰“开附件弹框
const openFilesFormDia = async (row) => {
  recordId.value = row.id
  fileDialogVisible.value = true
}
const pagination = (obj) => {
  page.current = obj.page;
  page.size = obj.limit;
src/views/equipmentManagement/inspectionManagement/components/formDia.vue
@@ -26,6 +26,21 @@
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="巡检项目" prop="inspectionProject">
              <el-input v-model="form.inspectionProject" placeholder="请输入巡检项目" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="是否启用" prop="isEnabled">
              <el-radio-group v-model="form.isEnabled">
                <el-radio :value="1">是</el-radio>
                <el-radio :value="0">否</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="备注" prop="remarks">
              <el-input v-model="form.remarks" placeholder="请输入备注" type="textarea" />
            </el-form-item>
@@ -118,6 +133,8 @@
    taskName: undefined,
    inspector: '',
    inspectorIds: '',
    inspectionProject: '',
    isEnabled: 1,
    remarks: '',
    frequencyType: '',
    frequencyDetail: '',
@@ -245,6 +262,8 @@
    taskName: undefined,
    inspector: '',
    inspectorIds: '',
    inspectionProject: '',
    isEnabled: 1,
    remarks: '',
    frequencyType: '',
    frequencyDetail: '',
src/views/equipmentManagement/inspectionManagement/index.vue
@@ -70,6 +70,11 @@
                    class="no-data">--</span>
            </div>
          </template>
          <template #isEnabled="{ row }">
            <el-tag :type="row.isEnabled === 1 ? 'success' : 'danger'" size="small">
              {{ row.isEnabled == 1 ? '是' : '否' }}
            </el-tag>
          </template>
        </PIMTable>
      </div>
    </el-card>
@@ -126,8 +131,16 @@
  // åˆ—配置
  const columns = ref([
    { prop: "taskName", label: "巡检任务名称", minWidth: 160 },
    { prop: "inspectionProject", label: "巡检项目", minWidth: 150 },
    { prop: "remarks", label: "备注", minWidth: 150 },
    { prop: "inspector", label: "执行巡检人", minWidth: 150, slot: "inspector" },
    {
      prop: "isEnabled",
      label: "是否启用",
      minWidth: 100,
      dataType: "slot",
      slot: "isEnabled"
    },
    {
      prop: "frequencyType",
      label: "频次",
@@ -227,8 +240,10 @@
      operationsArr.value = ["edit"];
    } else if (value === "task") {
      const operationColumn = getOperationColumn(["viewFile"]);
      // å®šæ—¶ä»»åŠ¡è®°å½•ä¸å±•ç¤º"是否启用"列
      const taskColumns = columns.value.filter(col => col.prop !== "isEnabled");
      tableColumns.value = [
        ...columns.value,
        ...taskColumns,
        ...(operationColumn ? [operationColumn] : []),
      ];
      operationsArr.value = ["viewFile"];
src/views/equipmentManagement/measurementEquipment/index.vue
@@ -42,6 +42,7 @@
                :tableLoading="tableLoading"
                @pagination="pagination"
        :dbRowClick="dbRowClick"
        :rowClassName="rowClassName"
            ></PIMTable>
        </div>
        <form-dia ref="formDia" @close="handleQuery"></form-dia>
@@ -125,22 +126,6 @@
    align:"center"
    },
  {
    label: "快到期提醒",
    prop: "valid",
    width: 130,
    align: "center",
    formatData: (cell) => {
      if (!cell) return "";
      const validDate = new Date(cell);
      const now = new Date();
      const diffDays = Math.ceil((validDate - now) / (1000 * 60 * 60 * 24));
      if (diffDays <= 7 && diffDays >= 0) {
        return "⚠️ " + diffDays + "天后到期";
      }
      return "";
    }
  },
  {
    label: "状态",
    prop: "status",
    width: 130,
@@ -197,6 +182,31 @@
const dbRowClick = (row)=>{
  rowClickData.value?.openDialog(row)
}
// è¡Œæ ·å¼ï¼šå¿«åˆ°æœŸï¼ˆ7天内)或逾期标红
const rowClassName = ({ row }) => {
  console.log('rowClassName called:', row);
  // valid æ˜¯æœ‰æ•ˆå¤©æ•°ï¼ŒmostDate æ˜¯æœ€æ–°æ£€å®šæ—¥æœŸ
  if (row.valid && row.mostDate) {
    const mostDate = new Date(row.mostDate);
    // è®¡ç®—到期日期 = æ£€å®šæ—¥æœŸ + æœ‰æ•ˆå¤©æ•°
    const validDays = parseInt(row.valid) || 0;
    const expireDate = new Date(mostDate);
    expireDate.setDate(expireDate.getDate() + validDays);
    const now = new Date();
    const diffDays = Math.ceil((expireDate - now) / (1000 * 60 * 60 * 24));
    console.log('row:', row.code, 'validDays:', validDays, 'expireDate:', expireDate, 'diffDays:', diffDays);
    // 7天内到期或已逾期都标红
    if (diffDays <= 7) {
      console.log('return warning-row');
      return 'warning-row';
    }
  } else {
    console.log('row missing valid or mostDate:', row.valid, row.mostDate);
  }
  return '';
}
// è¡¨æ ¼é€‰æ‹©æ•°æ®
@@ -298,5 +308,13 @@
</script>
<style scoped>
:deep(.el-table .warning-row) {
  background-color: #fef0f0 !important;
}
:deep(.el-table .warning-row:hover > td) {
  background-color: #f9d5d5 !important;
}
:deep(.el-table .el-table__body tr.warning-row td) {
  background-color: #fef0f0 !important;
}
</style>
src/views/equipmentManagement/repair/Modal/MaintainModal.vue
@@ -16,7 +16,8 @@
      </el-form-item>
      <el-form-item label="维修状态">
        <el-select v-model="form.status">
          <el-option label="待验收" :value="3"></el-option>
          <el-option label="待报修" :value="0"></el-option>
          <el-option label="完结" :value="1"></el-option>
          <el-option label="失败" :value="2"></el-option>
        </el-select>
      </el-form-item>
@@ -117,7 +118,7 @@
    data.maintenanceTime 
      ? dayjs(data.maintenanceTime).format("YYYY-MM-DD HH:mm:ss")
      : dayjs().format("YYYY-MM-DD HH:mm:ss");
  form.status = 3; // é»˜è®¤çŠ¶æ€ä¸ºå¾…éªŒæ”¶
  form.status = 1; // é»˜è®¤çŠ¶æ€ä¸ºå®Œç»“
  // multiple é€‰æ‹©å™¨è¦æ±‚数组;后端常返回 "1,2,3"
  if (Array.isArray(data?.sparePartsIds)) {
    form.sparePartsIds = data.sparePartsIds.map((v) => Number(v)).filter((v) => Number.isFinite(v));
src/views/inventoryManagement/stockManagement/BatchNoQtyDetail.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,227 @@
<template>
  <el-dialog
    v-model="isShow"
    title="库存详情"
    width="90%"
    top="3vh"
    class="batch-no-qty-detail-dialog"
    @close="closeModal"
  >
    <div class="detail-content">
      <div class="detail-table-wrapper">
        <el-table
          :data="tableData"
          border
          v-loading="tableLoading"
          style="width: 100%"
          height="100%"
        >
          <el-table-column
            label="产品名称"
            prop="productName"
            show-overflow-tooltip
          />
          <el-table-column label="规格型号" prop="model" show-overflow-tooltip />
          <el-table-column label="单位" prop="unit" show-overflow-tooltip />
          <el-table-column label="批号" prop="batchNo" show-overflow-tooltip />
          <el-table-column
            label="合格库存数量"
            prop="qualifiedQuantity"
            show-overflow-tooltip
          />
          <el-table-column
            label="不合格库存数量"
            prop="unQualifiedQuantity"
            show-overflow-tooltip
          />
          <el-table-column
            label="合格冻结数量"
            prop="qualifiedLockedQuantity"
            show-overflow-tooltip
          />
          <el-table-column
            label="不合格冻结数量"
            prop="unQualifiedLockedQuantity"
            show-overflow-tooltip
          />
          <el-table-column
            label="库存预警数量"
            prop="warnNum"
            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="180" align="center">
            <template #default="scope">
              <el-button
                link
                type="primary"
                @click="handleSubtract(scope.row)"
                :disabled="
                  (scope.row.qualifiedUnLockedQuantity || 0) +
                    (scope.row.qualifiedPendingOutQuantity || 0) <=
                    0 &&
                  (scope.row.unQualifiedUnLockedQuantity || 0) +
                    (scope.row.unQualifiedPendingOutQuantity || 0) <=
                    0
                "
                >领用</el-button
              >
              <el-button
                link
                type="primary"
                v-if="
                  scope.row.unQualifiedUnLockedQuantity > 0 ||
                  scope.row.qualifiedUnLockedQuantity > 0
                "
                @click="handleFrozen(scope.row)"
                >冻结</el-button
              >
              <el-button
                link
                type="primary"
                v-if="
                  scope.row.qualifiedLockedQuantity > 0 ||
                  scope.row.unQualifiedLockedQuantity > 0
                "
                @click="handleThaw(scope.row)"
                >解冻</el-button
              >
            </template>
          </el-table-column>
        </el-table>
      </div>
      <pagination
        v-show="total > 0"
        :total="total"
        layout="total, sizes, prev, pager, next, jumper"
        :page="page.current"
        :limit="page.size"
        @pagination="paginationChange"
      />
    </div>
  </el-dialog>
</template>
<script setup>
import pagination from "@/components/PIMTable/Pagination.vue";
import { computed, reactive, ref, watch } from "vue";
import { getStockInventoryBatchNoQty } from "@/api/inventoryManagement/stockInventory.js";
const props = defineProps({
  visible: {
    type: Boolean,
    required: true,
  },
  record: {
    type: Object,
    default: () => ({}),
  },
});
const emit = defineEmits(["update:visible", "subtract", "frozen", "thaw"]);
const isShow = computed({
  get() {
    return props.visible;
  },
  set(val) {
    emit("update:visible", val);
  },
});
const tableData = ref([]);
const tableLoading = ref(false);
const total = ref(0);
const page = reactive({
  current: 1,
  size: 20,
});
const getList = () => {
  if (!props.record?.productId || !props.record?.productModelId) {
    tableData.value = [];
    total.value = 0;
    return;
  }
  tableLoading.value = true;
  getStockInventoryBatchNoQty({
    current: page.current,
    size: page.size,
    productId: props.record.productId,
    productModelId: props.record.productModelId,
  })
    .then((res) => {
      tableData.value = res.data?.records || [];
      total.value = res.data?.total || 0;
    })
    .finally(() => {
      tableLoading.value = false;
    });
};
const paginationChange = (obj) => {
  page.current = obj.page;
  page.size = obj.limit;
  getList();
};
const handleSubtract = (row) => {
  emit("subtract", row);
};
const handleFrozen = (row) => {
  emit("frozen", row);
};
const handleThaw = (row) => {
  emit("thaw", row);
};
const closeModal = () => {
  isShow.value = false;
  page.current = 1;
  page.size = 20;
  tableData.value = [];
  total.value = 0;
};
watch(
  () => props.visible,
  (visible) => {
    if (!visible) {
      return;
    }
    page.current = 1;
    getList();
  },
  { immediate: true }
);
</script>
<style scoped lang="scss">
.detail-content {
  display: flex;
  flex-direction: column;
  height: calc(100vh - 170px);
  min-height: 520px;
}
.detail-table-wrapper {
  flex: 1;
  min-height: 0;
}
:deep(.batch-no-qty-detail-dialog .el-dialog) {
  max-width: calc(100vw - 48px);
}
:deep(.batch-no-qty-detail-dialog .el-dialog__body) {
  padding-top: 12px;
}
</style>
src/views/inventoryManagement/stockManagement/Record.vue
@@ -3,143 +3,233 @@
    <div class="search_form mb10">
      <div>
        <span class="search_title ml10">产品大类:</span>
        <el-input v-model="searchForm.productName"
                  style="width: 240px"
                  placeholder="请输入"
                  clearable/>
        <el-button type="primary" @click="handleQuery" style="margin-left: 10px">搜索</el-button>
        <el-input
          v-model="searchForm.productName"
          style="width: 240px"
          placeholder="请输入"
          clearable
        />
        <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
          >搜索</el-button
        >
      </div>
      <div>
         <el-button type="primary" @click="isShowNewModal = true">新增库存</el-button>
        <el-button type="info" plain icon="Upload" @click="isShowImportModal = true">
        <el-button type="primary" @click="isShowNewModal = true"
          >新增库存</el-button
        >
        <el-button
          type="info"
          plain
          icon="Upload"
          @click="isShowImportModal = true"
        >
          å¯¼å…¥åº“å­˜
        </el-button>
        <el-button @click="handleOut">导出</el-button>
      </div>
    </div>
    <div class="table_list">
      <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange"
        :expand-row-keys="expandedRowKeys" :row-key="(row, index) => index" style="width: 100%"
        :row-class-name="tableRowClassName" height="calc(100vh - 18.5em)">
      <el-table
        :data="tableData"
        border
        v-loading="tableLoading"
        @selection-change="handleSelectionChange"
        :expand-row-keys="expandedRowKeys"
        :row-key="(row, index) => index"
        style="width: 100%"
        :row-class-name="tableRowClassName"
        height="calc(100vh - 18.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 />
        <el-table-column
          label="产品名称"
          prop="productName"
          show-overflow-tooltip
        />
        <el-table-column label="规格型号" prop="model" show-overflow-tooltip />
        <el-table-column label="单位" prop="unit" show-overflow-tooltip />
        <el-table-column label="批号" prop="batchNo" show-overflow-tooltip />
        <el-table-column label="合格库存数量" prop="qualifiedQuantity" show-overflow-tooltip />
        <el-table-column label="不合格库存数量" prop="unQualifiedQuantity" show-overflow-tooltip />
        <el-table-column label="合格冻结数量" prop="qualifiedLockedQuantity" show-overflow-tooltip />
        <el-table-column label="不合格冻结数量" prop="unQualifiedLockedQuantity" show-overflow-tooltip />
        <el-table-column label="库存预警数量" prop="warnNum"  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="90" align="center">
        <el-table-column
          label="合格库存数量"
          prop="qualifiedQuantity"
          show-overflow-tooltip
        />
        <el-table-column
          label="不合格库存数量"
          prop="unQualifiedQuantity"
          show-overflow-tooltip
        />
        <el-table-column
          label="合格冻结数量"
          prop="qualifiedLockedQuantity"
          show-overflow-tooltip
        />
        <el-table-column
          label="不合格冻结数量"
          prop="unQualifiedLockedQuantity"
          show-overflow-tooltip
        />
        <el-table-column
          label="库存预警数量"
          prop="warnNum"
          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="80"
          align="center"
        >
          <template #default="scope">
            <el-button link type="primary" @click="showSubtractModal(scope.row)" :disabled="((scope.row.qualifiedUnLockedQuantity || 0) + (scope.row.qualifiedPendingOutQuantity || 0) <= 0) && ((scope.row.unQualifiedUnLockedQuantity || 0) + (scope.row.unQualifiedPendingOutQuantity || 0) <= 0)">领用</el-button>
            <el-button link type="primary" v-if="scope.row.unQualifiedUnLockedQuantity > 0 || scope.row.qualifiedUnLockedQuantity > 0" @click="showFrozenModal(scope.row)">冻结</el-button>
            <el-button link type="primary" v-if="scope.row.qualifiedLockedQuantity > 0 || scope.row.unQualifiedLockedQuantity > 0" @click="showThawModal(scope.row)">解冻</el-button>
            <el-button
              link
              type="primary"
              @click="showDetailModal(scope.row)"
              >详情</el-button
            >
          </template>
        </el-table-column>
      </el-table>
      <pagination v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper"
        :page="page.current" :limit="page.size" @pagination="paginationChange" />
      <pagination
        v-show="total > 0"
        :total="total"
        layout="total, sizes, prev, pager, next, jumper"
        :page="page.current"
        :limit="page.size"
        @pagination="paginationChange"
      />
    </div>
    <new-stock-inventory v-if="isShowNewModal"
                 v-model:visible="isShowNewModal"
                 :top-product-parent-id="props.productId"
                 @completed="handleQuery" />
    <batch-no-qty-detail
      v-if="isShowDetailModal"
      v-model:visible="isShowDetailModal"
      :record="record"
      @subtract="handleDetailSubtract"
      @frozen="handleDetailFrozen"
      @thaw="handleDetailThaw"
    />
    <new-stock-inventory
      v-if="isShowNewModal"
      v-model:visible="isShowNewModal"
      :top-product-parent-id="props.productId"
      @completed="handleQuery"
    />
    <subtract-stock-inventory v-if="isShowSubtractModal"
                 v-model:visible="isShowSubtractModal"
                 :record="record"
                 :type="record.stockType"
                 @completed="handleQuery" />
    <subtract-stock-inventory
      v-if="isShowSubtractModal"
      v-model:visible="isShowSubtractModal"
      :record="record"
      :type="record.stockType"
      @completed="handleQuery"
    />
    <!-- å¯¼å…¥åº“å­˜-->
    <import-stock-inventory v-if="isShowImportModal"
                 v-model:visible="isShowImportModal"
                 type="qualified"
                 @uploadSuccess="handleQuery" />
    <import-stock-inventory
      v-if="isShowImportModal"
      v-model:visible="isShowImportModal"
      type="qualified"
      @uploadSuccess="handleQuery"
    />
    <!-- å†»ç»“/解冻库存-->
    <frozen-and-thaw-stock-inventory v-if="isShowFrozenAndThawModal"
                 v-model:visible="isShowFrozenAndThawModal"
                 :record="record"
                 :operation-type="operationType"
                 :type="record.stockType"
                 @completed="handleQuery" />
    <frozen-and-thaw-stock-inventory
      v-if="isShowFrozenAndThawModal"
      v-model:visible="isShowFrozenAndThawModal"
      :record="record"
      :operation-type="operationType"
      :type="record.stockType"
      @completed="handleQuery"
    />
  </div>
</template>
<script setup>
import pagination from '@/components/PIMTable/Pagination.vue'
import { ref, reactive, toRefs, onMounted, getCurrentInstance } from 'vue'
import {ElMessage, ElMessageBox} from "element-plus";
import {
  getStockInventoryListPageCombined
} from "@/api/inventoryManagement/stockInventory.js";
import pagination from "@/components/PIMTable/Pagination.vue";
import { ref, reactive, toRefs, onMounted, getCurrentInstance } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { getStockInventoryListPageCombined } from "@/api/inventoryManagement/stockInventory.js";
const props = defineProps({
  productId: {
    type: Number,
    required: true,
    default: 0
  }
    default: 0,
  },
});
const NewStockInventory = defineAsyncComponent(() => import("@/views/inventoryManagement/stockManagement/New.vue"));
const SubtractStockInventory = defineAsyncComponent(() => import("@/views/inventoryManagement/stockManagement/Subtract.vue"));
const ImportStockInventory = defineAsyncComponent(() => import("@/views/inventoryManagement/stockManagement/Import.vue"));
const FrozenAndThawStockInventory = defineAsyncComponent(() => import("@/views/inventoryManagement/stockManagement/FrozenAndThaw.vue"));
const { proxy } = getCurrentInstance()
const tableData = ref([])
const selectedRows = ref([])
const record = ref({})
const tableLoading = ref(false)
const NewStockInventory = defineAsyncComponent(() =>
  import("@/views/inventoryManagement/stockManagement/New.vue")
);
const SubtractStockInventory = defineAsyncComponent(() =>
  import("@/views/inventoryManagement/stockManagement/Subtract.vue")
);
const ImportStockInventory = defineAsyncComponent(() =>
  import("@/views/inventoryManagement/stockManagement/Import.vue")
);
const FrozenAndThawStockInventory = defineAsyncComponent(() =>
  import("@/views/inventoryManagement/stockManagement/FrozenAndThaw.vue")
);
const BatchNoQtyDetail = defineAsyncComponent(() =>
  import("@/views/inventoryManagement/stockManagement/BatchNoQtyDetail.vue")
);
const { proxy } = getCurrentInstance();
const tableData = ref([]);
const selectedRows = ref([]);
const record = ref({});
const tableLoading = ref(false);
const page = reactive({
  current: 1,
  size: 100,
})
const total = ref(0)
});
const total = ref(0);
// æ˜¯å¦æ˜¾ç¤ºæ–°å¢žå¼¹æ¡†
const isShowNewModal = ref(false)
const isShowNewModal = ref(false);
// æ˜¯å¦æ˜¾ç¤ºé¢†ç”¨å¼¹æ¡†
const isShowSubtractModal = ref(false)
const isShowSubtractModal = ref(false);
// æ˜¯å¦æ˜¾ç¤ºå†»ç»“/解冻弹框
const isShowFrozenAndThawModal = ref(false)
const isShowFrozenAndThawModal = ref(false);
// æ˜¯å¦æ˜¾ç¤ºè¯¦æƒ…弹框
const isShowDetailModal = ref(false);
// æ“ä½œç±»åž‹
const operationType = ref('frozen')
const operationType = ref("frozen");
// æ˜¯å¦æ˜¾ç¤ºå¯¼å…¥å¼¹æ¡†
const isShowImportModal = ref(false)
const isShowImportModal = ref(false);
const data = reactive({
  searchForm: {
    productName: '',
    productName: "",
    topParentProductId: props.productId,
  }
})
const { searchForm } = toRefs(data)
  },
});
const { searchForm } = toRefs(data);
// æŸ¥è¯¢åˆ—表
/** æœç´¢æŒ‰é’®æ“ä½œ */
const handleQuery = () => {
  page.current = 1
  getList()
}
  page.current = 1;
  getList();
};
const paginationChange = (obj) => {
  page.current = obj.page;
  page.size = obj.limit;
  getList()
}
  getList();
};
const getList = () => {
  tableLoading.value = true
  getStockInventoryListPageCombined({ ...searchForm.value, ...page }).then(res => {
    tableLoading.value = false
    tableData.value = res.data.records
    total.value = res.data.total
    // æ•°æ®åŠ è½½å®ŒæˆåŽæ£€æŸ¥åº“å­˜
    // checkStockAndCreatePurchase();
  }).catch(() => {
    tableLoading.value = false
  })
}
  tableLoading.value = true;
  getStockInventoryListPageCombined({ ...searchForm.value, ...page })
    .then((res) => {
      tableLoading.value = false;
      tableData.value = res.data.records;
      total.value = res.data.total;
      // æ•°æ®åŠ è½½å®ŒæˆåŽæ£€æŸ¥åº“å­˜
      // checkStockAndCreatePurchase();
    })
    .catch(() => {
      tableLoading.value = false;
    });
};
const handleFileSuccess = (response) => {
  const { code, msg } = response;
@@ -154,61 +244,89 @@
// ç‚¹å‡»é¢†ç”¨
const showSubtractModal = (row) => {
  record.value = row
  isShowSubtractModal.value = true
}
  record.value = row;
  isShowSubtractModal.value = true;
};
// ç‚¹å‡»è¯¦æƒ…
const showDetailModal = (row) => {
  if (!row?.productId || !row?.productModelId) {
    proxy.$modal.msgError("当前数据缺少产品ID或规格型号ID");
    return;
  }
  record.value = row;
  isShowDetailModal.value = true;
};
const handleDetailSubtract = (row) => {
  isShowDetailModal.value = false;
  showSubtractModal(row);
};
const handleDetailFrozen = (row) => {
  isShowDetailModal.value = false;
  showFrozenModal(row);
};
const handleDetailThaw = (row) => {
  isShowDetailModal.value = false;
  showThawModal(row);
};
// ç‚¹å‡»å†»ç»“
const showFrozenModal = (row) => {
  record.value = row
  isShowFrozenAndThawModal.value = true
  operationType.value = 'frozen'
}
  record.value = row;
  isShowFrozenAndThawModal.value = true;
  operationType.value = "frozen";
};
// ç‚¹å‡»è§£å†»
const showThawModal = (row) => {
  record.value = row
  isShowFrozenAndThawModal.value = true
  operationType.value = 'thaw'
}
  record.value = row;
  isShowFrozenAndThawModal.value = true;
  operationType.value = "thaw";
};
// è¡¨æ ¼é€‰æ‹©æ•°æ®
const handleSelectionChange = (selection) => {
  // è¿‡æ»¤æŽ‰å­æ•°æ®
  selectedRows.value = selection.filter(item => item.id);
  console.log('selection', selectedRows.value)
}
const expandedRowKeys = ref([])
  selectedRows.value = selection.filter((item) => item.id);
  console.log("selection", selectedRows.value);
};
const expandedRowKeys = ref([]);
// è¡¨æ ¼è¡Œç±»å
const tableRowClassName = ({ row }) => {
  const stock = Number(row?.qualifiedUnLockedQuantity ?? 0);
  const warn = Number(row?.warnNum ?? 0);
  if (!Number.isFinite(stock) || !Number.isFinite(warn)) {
    return '';
    return "";
  }
  return stock < warn ? 'row-low-stock' : '';
  return stock < warn ? "row-low-stock" : "";
};
// å¯¼å‡º
const handleOut = () => {
  ElMessageBox.confirm(
    '是否确认导出?',
    '导出', {
    confirmButtonText: '确认',
    cancelButtonText: '取消',
    type: 'warning',
  }
  ).then(() => {
    proxy.download("/stockInventory/exportStockInventory", {topParentProductId: props.productId}, '库存信息.xlsx')
  }).catch(() => {
    proxy.$modal.msg("已取消")
  ElMessageBox.confirm("是否确认导出?", "导出", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  })
}
    .then(() => {
      proxy.download(
        "/stockInventory/exportStockInventory",
        { topParentProductId: props.productId },
        "库存信息.xlsx"
      );
    })
    .catch(() => {
      proxy.$modal.msg("已取消");
    });
};
onMounted(() => {
  getList()
})
  getList();
});
</script>
<style scoped lang="scss">
src/views/safeProduction/safeWorkApproval/components/infoFormDia.vue
@@ -218,7 +218,7 @@
      approveDeptName: "",
      approveReason: "",
      checkResult: "",
      storageBlobDTOs: [],
      storageBlobDTOS: [],
      approverList: [], // æ–°å¢žå­—段,存储所有节点的审批人id
      startDate: "", // è¯·å‡å¼€å§‹æ—¶é—´
      endDate: "", // è¯·å‡ç»“束时间
@@ -298,7 +298,7 @@
      approveProcessGetInfo({ id: row.approveId, approveReason: "1" }).then(
        res => {
          form.value = { ...res.data };
          form.value.storageBlobDTOs = res.data.storageBlobVOS;
          form.value.storageBlobDTOS = res.data.storageBlobVOS;
          // åæ˜¾å®¡æ‰¹äºº
          if (res.data && res.data.approveUserIds) {
            const userIds = res.data.approveUserIds.split(",");
@@ -388,7 +388,7 @@
        return;
      }
    }
    form.value.storageBlobDTOs = fileList.value;
    form.value.storageBlobDTOS = fileList.value;
    proxy.$refs.formRef.validate(valid => {
      if (valid) {
        if (operationType.value === "add" || currentApproveStatus.value == 3) {
src/views/salesManagement/salesLedger/index.vue
@@ -1578,7 +1578,7 @@
    selectedQuotation.value = null;
    let userLists = await userListNoPage();
    userList.value = userLists.data;
    listCustomer({ current: -1, size: -1 }).then(res => {
    listCustomer({ current: -1, size: -1, type: 0 }).then(res => {
      customerOption.value = res.data.records;
    });
    form.value.entryPerson = userStore.id;
@@ -2654,7 +2654,7 @@
    // å‘货状态必须是"待发货"或"审核拒绝"
    const statusStr = shippingStatus ? String(shippingStatus).trim() : "";
    return statusStr === "待发货" || statusStr === "审核拒绝";
    return statusStr === "待发货" || statusStr === "审核拒绝" || statusStr === "部分发货";
  };
  // æ‰“开附件弹窗