<template>
|
<div class="app-container">
|
<el-form :inline="true" :model="queryParams" class="search-form">
|
<el-form-item v-if="shouldShowSearch" label="搜索">
|
<el-input
|
v-model="queryParams.searchAll"
|
:placeholder="searchPlaceholder"
|
clearable
|
/>
|
</el-form-item>
|
<el-form-item>
|
<el-button type="primary" @click="search">查询</el-button>
|
<el-button @click="resetQuery">重置</el-button>
|
</el-form-item>
|
</el-form>
|
<el-card>
|
<!-- 标签页 -->
|
<el-tabs
|
v-model="activeTab"
|
class="info-tabs"
|
@tab-click="handleTabClick"
|
>
|
<el-tab-pane
|
v-for="tab in tabs"
|
:key="tab.name"
|
:label="tab.label"
|
:name="tab.name"
|
/>
|
</el-tabs>
|
|
<!-- 操作按钮区 -->
|
<el-row :gutter="24" class="table-toolbar">
|
<el-button
|
:icon="Plus"
|
type="primary"
|
v-show="activeTab === 'management'"
|
@click="handleAdd"
|
>设备新增</el-button
|
>
|
<el-button
|
:icon="Plus"
|
type="primary"
|
v-show="activeTab === 'equipmentRequisition'"
|
@click="handleAdd"
|
>领用</el-button
|
>
|
<el-button
|
:icon="Delete"
|
type="danger"
|
v-show="activeTab === 'management'"
|
@click="handleDelete"
|
:disabled="selectedCount === 0"
|
>删除 {{ selectedCount > 0 ? `(${selectedCount})` : '' }}</el-button
|
>
|
</el-row>
|
<!-- 表格组件 -->
|
<div class="table-container">
|
<!-- 加载状态 -->
|
<el-skeleton v-if="loading" animated>
|
<template #template>
|
<el-skeleton-item variant="h1" style="width: 40%" />
|
<div style="padding: 14px;">
|
<el-skeleton-item variant="text" />
|
<el-skeleton-item variant="text" />
|
<el-skeleton-item variant="text" />
|
</div>
|
</template>
|
</el-skeleton>
|
|
<!-- 数据表格 -->
|
<data-table
|
v-else
|
:showOverflowTooltip="false"
|
:border="true"
|
:columns="columns"
|
:loading="loading"
|
style="width: 100%; height: calc(100vh - 29em)"
|
:show-selection="activeTab === 'management'"
|
:table-data="tableData"
|
@edit="handleEdit"
|
@viewRow="handleView"
|
@selection-change="handleSelectionChange"
|
@custom-click="handleCustomButtonClick"
|
:operations="getTableOperations()"
|
:operationsWidth="getOperationsWidth()"
|
:customButtons="getCustomButtons()"
|
>
|
<!-- 空状态插槽 -->
|
<template #empty>
|
<el-empty
|
:description="`暂无${currentTabConfig?.label || ''}数据`"
|
:image-size="120"
|
>
|
<template #description>
|
<p>暂无{{ currentTabConfig?.label || '' }}数据</p>
|
<p v-if="queryParams.searchAll" class="text-secondary">
|
尝试调整搜索条件或
|
<el-button type="primary" link @click="resetQuery">清空搜索</el-button>
|
</p>
|
</template>
|
</el-empty>
|
</template>
|
</data-table>
|
</div>
|
<pagination
|
v-if="total > 0"
|
:layout="'total, prev, pager, next, jumper'"
|
:limit="pageSize"
|
:page="pageNum"
|
:total="total"
|
@pagination="handPagination"
|
/>
|
<managementDialog
|
v-if="activeTab == 'management'"
|
v-model:copyForm="copyForm"
|
v-model:managementFormDialog="manaDialog"
|
:addOrEdit="addOrEdit"
|
:form="form"
|
@submit="getList"
|
></managementDialog>
|
<EquipmentRequisition
|
v-if="activeTab == 'equipmentRequisition'"
|
v-model="equipmentRequisitionDialog"
|
:formData="form"
|
:maxQuantity="getMaxQuantity()"
|
:addOrEdit="addOrEdit"
|
:equipmentStatus="form.equipmentStatus"
|
@submit="onEquipmentRequisitionSubmit"
|
/>
|
<!-- <UsageRecord
|
v-if="activeTab == 'usageRecord'"
|
v-model:copyForm="copyForm"
|
v-model:usageRecordDialog="usageRecordDialog"
|
:addOrEdit="addOrEdit"
|
:form="form"
|
@submit="getList"
|
/> -->
|
|
<!-- 查看详情弹窗 -->
|
<DilogTable
|
v-model="dialogTableVisible"
|
:title="dialogTableTitle"
|
:table-data="dialogTableData"
|
:columns="dialogTableColumns"
|
width="60%"
|
/>
|
</el-card>
|
</div>
|
</template>
|
|
<script setup>
|
import { computed, onMounted, reactive, ref, nextTick, toRefs } from "vue";
|
import { ElMessage } from "element-plus";
|
import { Delete, Plus } from "@element-plus/icons-vue";
|
|
// 组件导入
|
import DataTable from "@/components/Table/ETable.vue";
|
import Pagination from "@/components/Pagination";
|
import managementDialog from "./mould/managementDialog.vue";
|
import EquipmentRequisition from "./mould/equipmentRequisitionDialog.vue";
|
import DilogTable from "@/components/dialog/DilogTable.vue";
|
|
// API 服务导入
|
import { useDelete } from "@/hooks/useDelete.js";
|
import {
|
getManagementList,
|
delEquipment,
|
} from "@/api/equipment/management/index.js";
|
import { getUsageRecordList, getUsageDetailList } from "@/api/equipment/requisition/index.js";
|
|
// 设备状态枚举
|
const EQUIPMENT_STATUS = {
|
USING: 1, // 使用中
|
PARTIAL_RETURN: 2, // 部分归还
|
RETURNED: 3 // 已归还
|
};
|
|
// 获取状态文本
|
const getStatusText = (status) => {
|
switch(status) {
|
case EQUIPMENT_STATUS.USING: return "使用中";
|
case EQUIPMENT_STATUS.PARTIAL_RETURN: return "部分归还";
|
case EQUIPMENT_STATUS.RETURNED: return "已归还";
|
default: return "未知状态";
|
}
|
};
|
|
// 获取状态颜色
|
const getStatusColor = (status) => {
|
switch(status) {
|
case EQUIPMENT_STATUS.USING: return '#409eff'; // 蓝色
|
case EQUIPMENT_STATUS.PARTIAL_RETURN: return '#e6a23c'; // 橙色
|
case EQUIPMENT_STATUS.RETURNED: return '#67c23a'; // 绿色
|
default: return '#909399'; // 灰色
|
}
|
};
|
|
// 响应式状态管理 - 使用解构和默认值
|
const initFormState = () => ({ consumables: false });
|
|
const state = reactive({
|
form: initFormState(),
|
title: "",
|
copyForm: {},
|
addOrEdit: "add",
|
loading: false,
|
activeTab: "management",
|
selectedRows: [],
|
tableData: [],
|
// 分页状态
|
pageNum: 1,
|
pageSize: 10,
|
total: 0,
|
// 查询参数
|
queryParams: {
|
searchAll: "",
|
},
|
});
|
|
// 使用解构简化访问
|
const {
|
form,
|
title,
|
copyForm,
|
addOrEdit,
|
loading,
|
activeTab,
|
selectedRows,
|
tableData,
|
pageNum,
|
pageSize,
|
total,
|
queryParams,
|
} = toRefs(state);
|
|
// 添加缺失的响应式变量
|
const manaDialog = ref(false);
|
const equipmentRequisitionDialog = ref(false);
|
const usageRecordDialog = ref(false);
|
const dialogTableVisible = ref(false);
|
const dialogTableTitle = ref('');
|
const dialogTableData = ref([]);
|
const dialogTableColumns = ref([]);
|
|
// 标签页配置 - 便于后续扩展
|
const tabsConfig = {
|
management: {
|
label: "设备列表",
|
searchPlaceholder: "设备编号/设备名称/规格型号",
|
showSearch: true,
|
api: getManagementList,
|
deleteApi: delEquipment,
|
columns: [
|
{ prop: "equipmentNo", label: "设备编号", minWidth: 100 },
|
{ prop: "equipmentName", label: "设备名称", minWidth: 100 },
|
{ prop: "consumables", label: "耗材",
|
formatter: (row) => (row.consumables ? "是" : "否"), minWidth: 100 },
|
{ prop: "quantity", label: "总数量", minWidth: 100 },
|
{ prop: "usedNo", label: "已使用数量", minWidth: 100 },
|
{ prop: "specification", label: "规格型号", minWidth: 100 },
|
{ prop: "purchaseDate", label: "采购日期", minWidth: 100 },
|
{ prop: "purchasePrice", label: "采购价格", minWidth: 100 },
|
],
|
},
|
equipmentRequisition: {
|
label: "设备领用",
|
searchPlaceholder: "设备编号/设备名称/规格型号",
|
showSearch: true,
|
api: getUsageRecordList,
|
deleteApi: null,
|
columns: [
|
{ prop: "userName", label: "领用人", minWidth: 100 },
|
{ prop: "equipmentNo", label: "设备编号", minWidth: 100 },
|
{ prop: "equipmentName", label: "设备名称", minWidth: 100 },
|
{ prop: "usageQuantity", label: "领用数量", minWidth: 100 },
|
{prop: "returnQuantity" , label: "归还数量", minWidth: 100,
|
formatter: (row) => row.returnQuantity || 0
|
},
|
{
|
prop: "equipmentStatus",
|
label: "使用状态",
|
minWidth: 100,
|
formatter: (row) => getStatusText(row.equipmentStatus),
|
cellStyle: (row) => ({ color: getStatusColor(row.equipmentStatus) }),
|
},
|
{ prop: "usageStartTime", label: "使用开始时间", minWidth: 100 },
|
{ prop: "usageEndTime", label: "使用结束时间", minWidth: 100 },
|
{ prop: "remarks", label: "备注", minWidth: 100 },
|
],
|
},
|
};
|
|
// 标签页数据
|
const tabs = reactive(
|
Object.entries(tabsConfig).map(([name, config]) => ({
|
name,
|
label: config.label,
|
}))
|
);
|
|
// 当前标签页配置
|
const currentTabConfig = computed(() => tabsConfig[activeTab.value]);
|
|
// 计算属性
|
const searchPlaceholder = computed(
|
() => currentTabConfig.value?.searchPlaceholder || "请输入搜索信息"
|
);
|
const shouldShowSearch = computed(
|
() => currentTabConfig.value?.showSearch || false
|
);
|
const columns = computed(() => currentTabConfig.value?.columns || []);
|
const selectedCount = computed(() => selectedRows.value.length);
|
|
// 动态获取表格操作配置
|
const getTableOperations = () => {
|
if (activeTab.value === 'equipmentRequisition') {
|
return [ 'viewRow']; // 设备领用页面只显示编辑和查看
|
}
|
return ['edit', 'viewRow']; // 默认操作
|
};
|
|
// 动态获取操作列宽度
|
const getOperationsWidth = () => {
|
if (activeTab.value === 'equipmentRequisition') {
|
return 250; // 为归还按钮预留更多空间
|
}
|
return 200; // 默认宽度
|
};
|
|
// 动态获取自定义按钮配置
|
const getCustomButtons = () => {
|
const buttons = [];
|
|
// 在设备领用页面添加归还按钮
|
if (activeTab.value === 'equipmentRequisition') {
|
buttons.push({
|
name: 'return',
|
label: '归还',
|
type: 'success',
|
size: 'small',
|
link: true,
|
show: (row) => row.equipmentStatus === EQUIPMENT_STATUS.USING || row.equipmentStatus === EQUIPMENT_STATUS.PARTIAL_RETURN,
|
disabled: (row) => row.equipmentStatus === EQUIPMENT_STATUS.RETURNED,
|
});
|
}
|
|
return buttons;
|
};
|
|
// 处理自定义按钮点击事件
|
const handleCustomButtonClick = ({ buttonName, row }) => {
|
switch (buttonName) {
|
case 'return':
|
handleReturn(row);
|
break;
|
// 可以在这里添加更多自定义按钮的处理逻辑
|
default:
|
console.warn(`未处理的自定义按钮: ${buttonName}`);
|
}
|
};
|
const handleReturn = (row) => {
|
// 检查设备状态
|
if (row.equipmentStatus === EQUIPMENT_STATUS.RETURNED) {
|
ElMessage.warning('该设备已归还完成,无需再次归还');
|
return;
|
}
|
|
if (row.equipmentStatus !== EQUIPMENT_STATUS.USING && row.equipmentStatus !== EQUIPMENT_STATUS.PARTIAL_RETURN) {
|
ElMessage.warning('该设备当前状态不支持归还操作');
|
return;
|
}
|
|
form.value = { ...row };
|
addOrEdit.value = "return"; // 设置为归还模式
|
title.value = `归还设备 - ${row.equipmentName || ''}`;
|
copyForm.value = { ...row };
|
equipmentRequisitionDialog.value = true;
|
console.log("归还设备:", row);
|
};
|
// 事件处理函数
|
const handleTabClick = (tab) => {
|
activeTab.value = tab.props.name;
|
resetState();
|
getList();
|
};
|
|
const resetState = () => {
|
form.value = {
|
consumables: false,
|
};
|
addOrEdit.value = "add";
|
loading.value = true;
|
tableData.value = [];
|
pageNum.value = 1;
|
pageSize.value = 10;
|
total.value = 0;
|
queryParams.value.searchAll = "";
|
};
|
|
const resetQuery = () => {
|
queryParams.value.searchAll = "";
|
pageNum.value = 1;
|
getList();
|
};
|
|
const search = () => {
|
pageNum.value = 1;
|
getList();
|
};
|
|
const handleAdd = () => {
|
addOrEdit.value = "add";
|
form.value = {
|
consumables: false,
|
};
|
title.value = `新增${currentTabConfig.value.label}`;
|
// 通用的
|
copyForm.value = {};
|
if (activeTab.value === "equipmentRequisition") {
|
equipmentRequisitionDialog.value = true;
|
} else if (activeTab.value === "usageRecord") {
|
usageRecordDialog.value = true;
|
} else {
|
manaDialog.value = true;
|
}
|
};
|
|
const handleEdit = (row) => {
|
form.value = { ...row };
|
addOrEdit.value = "edit";
|
title.value = `编辑${currentTabConfig.value.label}`;
|
copyForm.value = { ...row };
|
if (activeTab.value === "equipmentRequisition") {
|
equipmentRequisitionDialog.value = true;
|
} else if (activeTab.value === "usageRecord") {
|
usageRecordDialog.value = true;
|
} else {
|
manaDialog.value = true;
|
}
|
};
|
|
const handleView = async (row) => {
|
// 针对设备管理页面:直接打开编辑弹窗查看
|
if (activeTab.value === 'management') {
|
form.value = { ...row };
|
addOrEdit.value = "viewRow";
|
title.value = `查看${currentTabConfig.value.label}`;
|
copyForm.value = { ...row };
|
manaDialog.value = true;
|
return;
|
}
|
|
// 针对设备领用页面:打开详情记录表格
|
if (activeTab.value === 'equipmentRequisition') {
|
try {
|
dialogTableTitle.value = `${row.equipmentName || '设备'} - 操作记录详情`;
|
|
// 显示加载状态
|
dialogTableVisible.value = true;
|
dialogTableData.value = [];
|
|
// 调用详情接口获取数据
|
const { data, code } = await getUsageDetailList(row.id);
|
|
if (code === 200 && data) {
|
console.log('设备操作记录:', data);
|
|
// 处理数组数据,直接显示操作记录列表
|
if (Array.isArray(data.records)) {
|
dialogTableData.value = data.records;
|
dialogTableColumns.value = [
|
{ prop: 'equipmentNo', label: '设备编号', minWidth: 100 },
|
{ prop: 'equipmentName', label: '设备名称', minWidth: 120 },
|
{ prop: 'specification', label: '规格型号', minWidth: 100 },
|
{
|
prop: 'operationType',
|
label: '操作类型',
|
minWidth: 80,
|
formatter: (row) => row.operationType === 1 ? '领用' : '归还'
|
},
|
{ prop: 'quantity', label: '操作数量', minWidth: 80 },
|
{ prop: 'operator', label: '操作人', minWidth: 80 },
|
{ prop: 'remark', label: '备注', minWidth: 150, showOverflowTooltip: true },
|
{ prop: 'createTime', label: '操作时间', minWidth: 150 }
|
];
|
} else {
|
ElMessage.warning('暂无操作记录');
|
dialogTableVisible.value = false;
|
}
|
} else {
|
ElMessage.error('获取详情数据失败');
|
dialogTableVisible.value = false;
|
}
|
|
} catch (error) {
|
console.error('获取详情失败:', error);
|
ElMessage.error('获取详情数据失败');
|
dialogTableVisible.value = false;
|
}
|
return;
|
}
|
|
// 其他页面的默认处理
|
form.value = { ...row };
|
addOrEdit.value = "viewRow";
|
title.value = `查看${currentTabConfig.value.label}`;
|
copyForm.value = { ...row };
|
|
if (activeTab.value === "usageRecord") {
|
usageRecordDialog.value = true;
|
} else {
|
manaDialog.value = true;
|
}
|
};
|
|
const handPagination = (val) => {
|
pageNum.value = val.page;
|
pageSize.value = val.limit;
|
getList();
|
};
|
|
const handleSelectionChange = (selection) => {
|
selectedRows.value = selection;
|
};
|
|
// 删除处理
|
const { handleDeleteBatch: handleDelete } = useDelete({
|
deleteApi: () => currentTabConfig.value.deleteApi,
|
selectedRows: selectedRows,
|
getList: () => getList(),
|
tableData,
|
total,
|
confirmText: "确认删除选中的数据吗?",
|
successText: "删除成功",
|
});
|
|
// 获取设备最大可领用数量
|
const getMaxQuantity = () => {
|
if (form.value.equipmentId) {
|
const equipment = tableData.value.find(
|
(item) => item.equipmentId === form.value.equipmentId
|
);
|
return equipment ? equipment.quantity : null;
|
}
|
return null;
|
};
|
|
// 设备领用弹窗提交处理
|
const onEquipmentRequisitionSubmit = (formData) => {
|
if (formData.equipmentStatus === EQUIPMENT_STATUS.RETURNED) {
|
ElMessage.success("设备已完全归还");
|
} else if (formData.equipmentStatus === EQUIPMENT_STATUS.PARTIAL_RETURN) {
|
ElMessage.success("设备部分归还成功");
|
} else if (formData.equipmentStatus === EQUIPMENT_STATUS.USING) {
|
ElMessage.success("设备领用成功");
|
} else {
|
ElMessage.success("操作成功");
|
}
|
equipmentRequisitionDialog.value = false;
|
nextTick(() => {
|
form.value = {};
|
getList();
|
});
|
};
|
|
// 数据获取
|
const getList = async () => {
|
try {
|
loading.value = true;
|
const apiParams = {
|
current: pageNum.value,
|
pageSize: pageSize.value,
|
searchAll: queryParams.value.searchAll,
|
};
|
|
const { data, code } = await currentTabConfig.value.api(apiParams);
|
|
if (code !== 200) {
|
// ElMessage.error("获取数据失败:" + (data?.msg || "未知错误"));
|
return;
|
}
|
|
tableData.value = data.records || [];
|
total.value = data.total || 0;
|
} catch (error) {
|
ElMessage.error("获取数据失败,请稍后再试");
|
} finally {
|
loading.value = false;
|
}
|
};
|
|
// 组件挂载
|
onMounted(() => {
|
handleTabClick({ props: { name: "management" } });
|
});
|
</script>
|
|
<style scoped>
|
/* 响应式布局 */
|
@media screen and (min-width: 768px) {
|
.search-form :deep(.el-form-item) {
|
width: 50%;
|
}
|
}
|
|
@media screen and (min-width: 1200px) {
|
.search-form :deep(.el-form-item) {
|
width: 16%;
|
}
|
}
|
|
.table-toolbar {
|
margin-bottom: 20px;
|
display: flex;
|
flex-wrap: wrap;
|
gap: 10px;
|
}
|
.app-container {
|
padding: 18px !important;
|
}
|
/* 响应式表格 */
|
@media screen and (max-width: 768px) {
|
.table-toolbar {
|
flex-direction: column;
|
}
|
|
.table-toolbar .el-button {
|
width: 100%;
|
}
|
}
|
|
/* 表格工具栏 */
|
.table-toolbar,
|
.table-toolbar > * {
|
margin: 0 0 0 0 !important;
|
}
|
|
.table-toolbar {
|
margin-bottom: 20px !important;
|
}
|
|
.el-form--inline .el-form-item {
|
margin-right: 25px;
|
}
|
|
.main-container {
|
background: red !important;
|
}
|
|
/* 设备状态样式 */
|
.status-using {
|
color: #409eff;
|
font-weight: 500;
|
}
|
|
.status-partial-return {
|
color: #e6a23c;
|
font-weight: 500;
|
}
|
|
.status-returned {
|
color: #67c23a;
|
font-weight: 500;
|
}
|
|
.status-unknown {
|
color: #909399;
|
font-weight: 500;
|
}
|
|
/* 状态标签样式 */
|
:deep(.el-table .cell .status-tag) {
|
font-size: 12px;
|
padding: 2px 6px;
|
border-radius: 4px;
|
white-space: nowrap;
|
}
|
</style>
|