<template>
|
<view class="equipment-management">
|
<!-- 页面头部 -->
|
<PageHeader title="设备管理" @back="goBack"/>
|
|
<!-- 搜索区域 -->
|
<view class="search-section" v-if="shouldShowSearch">
|
<view class="search-bar">
|
<view class="search-input">
|
<up-input
|
class="search-text"
|
:placeholder="searchPlaceholder"
|
v-model="queryParams.searchAll"
|
clearable
|
/>
|
</view>
|
<view class="filter-button" @click="search">
|
<up-icon name="search" size="24" color="#999"></up-icon>
|
</view>
|
</view>
|
</view>
|
|
<!-- 标签页 -->
|
<!-- <view class="tabs-section">
|
<u-tabs
|
:list="tabs"
|
:current="activeTabIndex"
|
@change="handleTabChange"
|
:scrollable="false"
|
lineWidth="30"
|
lineColor="#2979ff"
|
:activeStyle="{
|
color: '#2979ff',
|
fontWeight: 'bold'
|
}"
|
/>
|
</view> -->
|
|
<!-- 列表区域 -->
|
<scroll-view
|
class="list-container"
|
scroll-y
|
refresher-enabled
|
:refresher-triggered="refreshing"
|
@refresherrefresh="onRefresh"
|
>
|
<!-- 加载状态 -->
|
<view v-if="loading" class="loading-container">
|
<u-loading-icon text="加载中..." />
|
</view>
|
|
<!-- 设备列表 -->
|
<view v-else-if="!loading && tableData.length > 0" class="ledger-list">
|
<view v-for="(item, index) in tableData" :key="item.id || index">
|
<view class="ledger-item">
|
<view class="item-header">
|
<view class="item-left">
|
<view class="document-icon">
|
<up-icon name="file-text" size="16" color="#ffffff"></up-icon>
|
</view>
|
<text class="item-id">{{ item.equipmentNo || '未编号' }}</text>
|
</view>
|
</view>
|
<up-divider></up-divider>
|
|
<view class="item-details">
|
<!-- 设备列表页面 -->
|
<!-- <template v-if="activeTab === 'management'"> -->
|
<view class="detail-row">
|
<text class="detail-label">设备名称</text>
|
<text class="detail-value">{{ item.equipmentName || '-' }}</text>
|
</view>
|
<view class="detail-row">
|
<text class="detail-label">耗材</text>
|
<text class="detail-value">{{ (item.consumables !== undefined ? item.consumables : item.isConsumables) ? '是' : '否' }}</text>
|
</view>
|
<view class="detail-row">
|
<text class="detail-label">总数量</text>
|
<text class="detail-value highlight">{{ item.quantity || 0 }}</text>
|
</view>
|
<view class="detail-row">
|
<text class="detail-label">已使用数量</text>
|
<text class="detail-value">{{ item.usedNo || 0 }}</text>
|
</view>
|
<view class="detail-row">
|
<text class="detail-label">规格型号</text>
|
<text class="detail-value">{{ item.specification || '-' }}</text>
|
</view>
|
<view class="detail-row">
|
<text class="detail-label">采购日期</text>
|
<text class="detail-value">{{ item.purchaseDate || '-' }}</text>
|
</view>
|
<view class="detail-row">
|
<text class="detail-label">采购价格</text>
|
<text class="detail-value">{{ item.purchasePrice ? `¥${item.purchasePrice}` : '-' }}</text>
|
</view>
|
<!-- </template> -->
|
|
<!-- 设备领用页面 -->
|
<!-- <template v-else-if="activeTab === 'equipmentRequisition'">
|
<view class="detail-row">
|
<text class="detail-label">领用人</text>
|
<text class="detail-value">{{ item.userName || '-' }}</text>
|
</view>
|
<view class="detail-row">
|
<text class="detail-label">设备名称</text>
|
<text class="detail-value">{{ item.equipmentName || '-' }}</text>
|
</view>
|
<view class="detail-row">
|
<text class="detail-label">领用数量</text>
|
<text class="detail-value highlight">{{ item.usageQuantity || 0 }}</text>
|
</view>
|
<view class="detail-row">
|
<text class="detail-label">归还数量</text>
|
<text class="detail-value">{{ item.returnQuantity || 0 }}</text>
|
</view>
|
<view class="detail-row">
|
<text class="detail-label">使用状态</text>
|
<text class="detail-value" :style="{ color: getStatusColor(item.equipmentStatus) }">
|
{{ getStatusText(item.equipmentStatus) }}
|
</text>
|
</view>
|
<view class="detail-row">
|
<text class="detail-label">使用开始时间</text>
|
<text class="detail-value">{{ item.usageStartTime || '-' }}</text>
|
</view>
|
<view class="detail-row">
|
<text class="detail-label">使用结束时间</text>
|
<text class="detail-value">{{ item.usageEndTime || '-' }}</text>
|
</view>
|
<view class="detail-row" v-if="item.remarks">
|
<text class="detail-label">备注</text>
|
<text class="detail-value">{{ item.remarks }}</text>
|
</view>
|
</template> -->
|
</view>
|
|
<!-- 操作按钮 - 只在设备领用页面显示 -->
|
<!-- <template v-if="activeTab === 'equipmentRequisition'">
|
<up-divider></up-divider>
|
<view class="action-buttons">
|
<u-button
|
type="info"
|
size="small"
|
class="action-btn"
|
@click.stop="handleView(item)"
|
>
|
查看
|
</u-button>
|
<u-button
|
v-if="shouldShowReturnButton(item)"
|
type="success"
|
size="small"
|
class="action-btn"
|
:disabled="item.equipmentStatus === EQUIPMENT_STATUS.RETURNED"
|
@click.stop="handleReturn(item)"
|
>
|
归还
|
</u-button>
|
</view>
|
</template> -->
|
</view>
|
</view>
|
</view>
|
|
<!-- 空状态 -->
|
<view v-else-if="!loading && tableData.length === 0" class="no-data">
|
<text>暂无{{ currentTabConfig?.label || '' }}数据</text>
|
</view>
|
</scroll-view>
|
|
<!-- 浮动操作按钮 - 设备领用页面显示领用按钮 -->
|
<!-- <view
|
v-if="activeTab === 'equipmentRequisition'"
|
class="fab-button"
|
@tap="handleAdd"
|
>
|
<up-icon name="plus" size="24" color="#ffffff"></up-icon>
|
</view> -->
|
|
<!-- 弹窗组件 -->
|
<!-- <managementDialog
|
v-if="activeTab == 'management'"
|
v-model:copyForm="copyForm"
|
v-model:managementFormDialog="manaDialog"
|
:addOrEdit="addOrEdit"
|
:form="form"
|
@submit="getList"
|
/> -->
|
<!-- <EquipmentRequisition
|
v-model="equipmentRequisitionDialog"
|
:formData="form"
|
:maxQuantity="getMaxQuantity()"
|
:addOrEdit="addOrEdit"
|
:equipmentStatus="form.equipmentStatus"
|
@submit="onEquipmentRequisitionSubmit"
|
/> -->
|
|
<!-- 查看详情弹窗 -->
|
<!-- <u-popup
|
v-model="dialogTableVisible"
|
:title="dialogTableTitle"
|
mode="center"
|
:closeable="true"
|
>
|
<view class="dialog-content">
|
<u-table
|
:data="dialogTableData"
|
:columns="dialogTableColumns"
|
height="400px"
|
/>
|
</view>
|
</u-popup> -->
|
</view>
|
</template>
|
|
<script setup>
|
import { computed, onMounted, reactive, ref, nextTick, toRefs } from "vue";
|
|
// uviewplus组件导入
|
import { useToast } from '@/utils/uviewplus'
|
const { showToast } = useToast()
|
|
// 组件导入
|
import PageHeader from "@/components/PageHeader.vue";
|
// import managementDialog from "./mould/managementDialog.vue";
|
// import EquipmentRequisition from "./mould/equipmentRequisitionDialog.vue";
|
|
// API 服务导入
|
import {
|
getManagementList,
|
} 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",
|
tableData: [],
|
// 分页状态(保留用于API调用,但不显示分页组件)
|
pageNum: 1,
|
pageSize: 20,
|
total: 0,
|
// 下拉刷新状态
|
refreshing: false,
|
// 查询参数
|
queryParams: {
|
searchAll: "",
|
},
|
});
|
|
// 使用解构简化访问
|
const {
|
form,
|
title,
|
copyForm,
|
addOrEdit,
|
loading,
|
activeTab,
|
tableData,
|
pageNum,
|
pageSize,
|
total,
|
queryParams,
|
refreshing,
|
} = 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,
|
columns: [
|
{ prop: "equipmentNo", label: "设备编号", minWidth: 100 },
|
{ prop: "equipmentName", label: "设备名称", minWidth: 100 },
|
{ prop: "consumables", label: "耗材",
|
formatter: (row) => {
|
const value = row.consumables !== undefined ? row.consumables : row.isConsumables;
|
return value ? "是" : "否";
|
}, 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,
|
// 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 },
|
// ],
|
// },
|
};
|
|
// 标签页数据 - u-tabs需要name作为显示文本
|
// const tabs = computed(() =>
|
// Object.entries(tabsConfig).map(([name, config]) => ({
|
// name: config.label, // 使用label作为显示文本
|
// value: name, // 保存原始name值
|
// }))
|
// );
|
const tabs = computed(() => [
|
{
|
name: tabsConfig.management.label,
|
value: 'management'
|
}
|
]);
|
|
// 当前标签页索引 - 使用ref而不是computed,确保响应式更新
|
const activeTabIndex = ref(0);
|
|
// 当前标签页配置
|
const currentTabConfig = computed(() => tabsConfig[activeTab.value]);
|
|
// 计算属性
|
const searchPlaceholder = computed(
|
() => currentTabConfig.value?.searchPlaceholder || "请输入搜索信息"
|
);
|
const shouldShowSearch = computed(
|
() => currentTabConfig.value?.showSearch || false
|
);
|
|
// 判断是否显示归还按钮
|
// const shouldShowReturnButton = (item) => {
|
// if (activeTab.value !== 'equipmentRequisition') {
|
// return false;
|
// }
|
// // 如果设备状态是已归还,不显示归还按钮
|
// if (item.equipmentStatus === EQUIPMENT_STATUS.RETURNED) {
|
// return false;
|
// }
|
// // 其他状态都显示归还按钮(使用中、部分归还、或者没有状态)
|
// return true;
|
// };
|
|
// 动态获取自定义按钮配置(保留用于其他用途)
|
// const getCustomButtons = () => {
|
// const buttons = [];
|
//
|
// // 在设备领用页面添加归还按钮
|
// if (activeTab.value === 'equipmentRequisition') {
|
// buttons.push({
|
// name: 'return',
|
// label: '归还',
|
// type: 'success',
|
// size: 'small',
|
// link: true,
|
// show: (row) => shouldShowReturnButton(row),
|
// 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) {
|
// showToast('该设备已归还完成,无需再次归还', 'warning');
|
// return;
|
// }
|
//
|
// if (row.equipmentStatus !== EQUIPMENT_STATUS.USING && row.equipmentStatus !== EQUIPMENT_STATUS.PARTIAL_RETURN) {
|
// showToast('该设备当前状态不支持归还操作', 'warning');
|
// return;
|
// }
|
//
|
// form.value = { ...row };
|
// addOrEdit.value = "return"; // 设置为归还模式
|
// title.value = `归还设备 - ${row.equipmentName || ''}`;
|
// copyForm.value = { ...row };
|
// equipmentRequisitionDialog.value = true;
|
// console.log("归还设备:", row);
|
// };
|
// 标签页切换处理 - u-tabs的@change事件传递的是对象 { index: number }
|
const handleTabChange = (e) => {
|
const index = typeof e === 'object' && e.index !== undefined ? e.index : e;
|
console.log('handleTabChange:', e, 'index:', index, 'tabs:', tabs.value);
|
const selectedTab = tabs.value[index];
|
if (selectedTab && selectedTab.value !== activeTab.value) {
|
activeTab.value = selectedTab.value;
|
activeTabIndex.value = index;
|
resetState();
|
getList();
|
}
|
};
|
|
|
const resetState = () => {
|
form.value = {
|
consumables: false,
|
};
|
addOrEdit.value = "add";
|
loading.value = true;
|
tableData.value = [];
|
pageNum.value = 1;
|
pageSize.value = 20;
|
total.value = 0;
|
queryParams.value.searchAll = "";
|
refreshing.value = false;
|
};
|
|
const resetQuery = () => {
|
queryParams.value.searchAll = "";
|
pageNum.value = 1;
|
getList();
|
};
|
|
const search = () => {
|
pageNum.value = 1;
|
getList();
|
};
|
|
// 处理新增领用
|
// const handleAdd = () => {
|
// console.log('handleAdd 被调用', 'activeTab:', activeTab.value, 'activeTabIndex:', activeTabIndex.value);
|
// addOrEdit.value = "add";
|
// form.value = {};
|
// title.value = `新增${currentTabConfig.value?.label || '设备领用'}`;
|
// copyForm.value = {};
|
// console.log('准备打开弹窗,equipmentRequisitionDialog当前值:', equipmentRequisitionDialog.value);
|
// equipmentRequisitionDialog.value = true;
|
// console.log('弹窗已打开,equipmentRequisitionDialog新值:', equipmentRequisitionDialog.value);
|
// };
|
|
// const handleView = async (row) => {
|
// // 只处理设备领用页面的查看功能
|
// 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) {
|
// // 处理数组数据,直接显示操作记录列表
|
// if (Array.isArray(data)) {
|
// dialogTableData.value = data;
|
// 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 {
|
// showToast('暂无操作记录', 'warning');
|
// }
|
// } else {
|
// showToast('获取详情数据失败', 'error');
|
// dialogTableVisible.value = false;
|
// }
|
//
|
// } catch (error) {
|
// console.error('获取详情失败:', error);
|
// showToast('获取详情数据失败', 'error');
|
// dialogTableVisible.value = false;
|
// }
|
// }
|
// };
|
|
// 下拉刷新
|
const onRefresh = async () => {
|
refreshing.value = true;
|
pageNum.value = 1;
|
await getList();
|
refreshing.value = false;
|
};
|
|
// 获取设备最大可领用数量
|
// 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) {
|
// showToast("设备已完全归还", 'success');
|
// } else if (formData.equipmentStatus === EQUIPMENT_STATUS.PARTIAL_RETURN) {
|
// } else if (formData.equipmentStatus === EQUIPMENT_STATUS.USING) {
|
// showToast("设备领用成功", 'success');
|
// } else {
|
// showToast("操作成功", 'success');
|
// }
|
// equipmentRequisitionDialog.value = false;
|
// nextTick(() => {
|
// form.value = {};
|
// getList();
|
// });
|
// };
|
|
// 数据获取
|
const getList = async () => {
|
try {
|
if (!refreshing.value) {
|
loading.value = true;
|
}
|
const apiParams = {
|
current: pageNum.value,
|
pageSize: pageSize.value,
|
searchAll: queryParams.value.searchAll,
|
};
|
|
const response = await currentTabConfig.value.api(apiParams);
|
console.log('API响应:', response);
|
|
// request工具返回的是 { code, data, msg } 结构
|
const { data, code } = response;
|
|
if (code !== 200) {
|
showToast("获取数据失败:" + (response?.msg || "未知错误"), 'error');
|
return;
|
}
|
|
// data 是 { records: [...], total: 3, ... } 结构
|
const records = data?.records || data?.rows || [];
|
console.log('解析后的数据:', records);
|
|
// 数据字段映射:将 isConsumables 映射为 consumables
|
const mappedRecords = records.map(item => ({
|
...item,
|
consumables: item.isConsumables !== undefined ? item.isConsumables : item.consumables
|
}));
|
|
// 如果是下拉刷新,重置数据;否则追加数据(用于上拉加载更多,但当前不实现)
|
if (pageNum.value === 1) {
|
tableData.value = mappedRecords;
|
} else {
|
tableData.value = [...tableData.value, ...mappedRecords];
|
}
|
total.value = data?.total || 0;
|
console.log('最终表格数据:', tableData.value);
|
} catch (error) {
|
console.error('获取数据失败:', error);
|
showToast("获取数据失败,请稍后再试", 'error');
|
} finally {
|
loading.value = false;
|
}
|
};
|
|
// 组件挂载
|
onMounted(() => {
|
activeTab.value = "management";
|
activeTabIndex.value = 0;
|
// 不重置搜索条件,直接加载数据
|
loading.value = true;
|
getList();
|
});
|
// 返回上一页
|
const goBack = () => {
|
uni.navigateBack();
|
};
|
</script>
|
|
<style scoped lang="scss">
|
@import '@/styles/sales-common.scss';
|
|
.equipment-management {
|
min-height: 100vh;
|
background: #f8f9fa;
|
position: relative;
|
}
|
|
.tabs-section {
|
background: #ffffff;
|
padding: 0 20px;
|
}
|
|
.list-container {
|
flex: 1;
|
height: calc(100vh - 200px);
|
}
|
|
.loading-container {
|
display: flex;
|
justify-content: center;
|
align-items: center;
|
padding: 40px;
|
color: #999;
|
}
|
|
.no-data {
|
padding: 40px 0;
|
text-align: center;
|
color: #999;
|
font-size: 14px;
|
}
|
</style>
|