Files
td_official/src/views/materials/usageMaterials/material/index.vue
2025-08-14 22:08:39 +08:00

627 lines
19 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="min-h-screen bg-gray-50 flex flex-col">
<!-- 主要内容区 -->
<main class="flex-1 p-6">
<!-- 操作栏 -->
<div class="bg-white rounded-lg shadow-sm p-4 mb-6 transition-all duration-300 hover:shadow-md">
<div class="flex flex-wrap items-center justify-between gap-4">
<!-- <div class="flex flex-wrap items-center gap-4">
<el-select
v-model="searchForm.findType"
placeholder="选择查询类型"
class="w-[180px]"
@change="handleSearch"
>
<el-option label="采购" value="1"></el-option>
<el-option label="材料" value="2"></el-option>
<el-option label="查询所有" value="3"></el-option>
</el-select>
<el-input
v-model="searchForm.keyword"
placeholder="输入材料名称或供应商搜索"
class="w-[250px]"
clearable
@keyup.enter="handleSearch"
>
<template #append>
<el-button icon="Search" @click="handleSearch"></el-button>
</template>
</el-input>
</div> -->
<!-- 操作按钮 -->
<div class="flex gap-2">
<el-button
type="primary"
icon="Plus"
@click="handleAdd"
class="transition-all duration-200 hover:shadow-md"
>
新增
</el-button>
<el-button
icon="Refresh"
@click="refreshData"
class="transition-all duration-200 hover:shadow-md"
>
刷新
</el-button>
</div>
</div>
</div>
<!-- 数据表格 -->
<div class="bg-white rounded-lg shadow-sm overflow-hidden transition-all duration-300 hover:shadow-md">
<el-table
v-loading="loading"
:data="tableData"
border
stripe
:header-cell-style="{ 'background-color': '#f5f7fa', 'font-weight': 'bold' }"
:row-class-name="tableRowClassName"
@row-dblclick="handleRowDblClick"
>
<el-table-column prop="id" label="ID" width="80" align="center"></el-table-column>
<el-table-column prop="name" label="材料名称" min-width="150"></el-table-column>
<el-table-column prop="specification" label="规格" min-width="120"></el-table-column>
<el-table-column prop="supplier" label="供应商" min-width="150"></el-table-column>
<el-table-column
prop="findType"
label="类型"
width="100"
align="center"
>
<template #default="scope">
<el-tag :type="scope.row.findType === '1' ? 'success' : 'info'">
{{ scope.row.findType === '1' ? '采购' : '材料' }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="installationQuantity" label="安装量" width="100" align="center"></el-table-column>
<el-table-column
prop="contractSigning"
label="合同签订时间"
width="180"
align="center"
>
<template #default="scope">
{{ formatDate(scope.row.contractSigning) }}
</template>
</el-table-column>
<el-table-column
prop="createTime"
label="创建时间"
width="180"
align="center"
>
<template #default="scope">
{{ formatDate(scope.row.createTime) }}
</template>
</el-table-column>
<el-table-column
label="操作"
width="180"
align="center"
fixed="right"
>
<template #default="scope">
<el-button
size="small"
icon="Edit"
@click="handleEdit(scope.row)"
class="text-blue-600 hover:text-blue-800 transition-colors"
></el-button>
<el-button
size="small"
icon="Delete"
@click="handleDelete(scope.row)"
class="text-red-600 hover:text-red-800 transition-colors"
></el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<div class="flex items-center justify-between p-4 border-t">
<div class="text-gray-500 text-sm">
{{ total }} 条记录当前显示第 {{ (currentPage - 1) * pageSize + 1 }} {{ Math.min(currentPage * pageSize, total) }}
</div>
<el-pagination
v-model:current-page="currentPage"
v-model:page-size="pageSize"
:page-sizes="[10, 20, 50, 100]"
:total="total"
layout="prev, pager, next, jumper, sizes"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
></el-pagination>
</div>
</div>
</main>
<!-- 底部信息 -->
<footer class="bg-white border-t border-gray-200 py-3 px-6 text-center text-gray-500 text-sm">
© 2023 材料/采购管理系统 - 版权所有
</footer>
<!-- 新增/编辑对话框 -->
<el-dialog
v-model="dialogVisible"
:title="dialogType === 'add' ? '新增记录' : '编辑记录'"
:width="dialogWidth"
:fullscreen="isFullscreen"
:before-close="handleDialogClose"
>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="120px"
class="space-y-4"
>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="材料名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入材料名称"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="规格" prop="specification">
<el-input v-model="formData.specification" placeholder="请输入规格"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="供应商" prop="supplier">
<el-input v-model="formData.supplier" placeholder="请输入供应商"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="类型" prop="findType">
<el-radio-group v-model="formData.findType">
<el-radio label="1">采购</el-radio>
<el-radio label="2">材料</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="安装量" prop="installationQuantity">
<el-input v-model="formData.installationQuantity" placeholder="请输入安装量"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="安装比例" prop="installationRatio">
<el-input v-model="formData.installationRatio" placeholder="请输入安装比例" suffix="%"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="合同签订时间" prop="contractSigning">
<el-date-picker
v-model="formData.contractSigning"
type="datetime"
placeholder="选择合同签订时间"
value-format="YYYY-MM-DD HH:mm:ss"
></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="生产周期(天)" prop="productionPhase">
<el-input v-model.number="formData.productionPhase" placeholder="请输入生产周期" type="number"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="运算周期(天)" prop="executionCycle">
<el-input v-model.number="formData.executionCycle" placeholder="请输入运算周期" type="number"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="项目ID" prop="projectId">
<el-input v-model.number="formData.projectId" placeholder="请输入项目ID" type="number"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="供货要求" prop="supplyRequirements">
<el-input
v-model="formData.supplyRequirements"
placeholder="请输入供货要求"
type="textarea"
rows="3"
></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="采购提交状态" prop="purchaseSubmission">
<el-select v-model="formData.purchaseSubmission" placeholder="请选择">
<el-option label="已提交" value="已提交"></el-option>
<el-option label="未提交" value="未提交"></el-option>
<el-option label="处理中" value="处理中"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="材料提交状态" prop="submissionMaterials">
<el-select v-model="formData.submissionMaterials" placeholder="请选择">
<el-option label="已提交" value="已提交"></el-option>
<el-option label="未提交" value="未提交"></el-option>
<el-option label="处理中" value="处理中"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="备注" prop="remark">
<el-input
v-model="formData.remark"
placeholder="请输入备注信息"
type="textarea"
rows="3"
></el-input>
</el-form-item>
</el-col>
</el-row>
<!-- 隐藏的创建和更新信息 -->
<el-form-item prop="id" class="hidden">
<el-input v-model="formData.id"></el-input>
</el-form-item>
<el-form-item prop="createTime" class="hidden">
<el-input v-model="formData.createTime"></el-input>
</el-form-item>
</el-form>
<template #footer>
<div class="flex justify-end gap-2">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button
type="primary"
@click="handleSave"
:loading="saveLoading"
>
保存
</el-button>
</div>
</template>
</el-dialog>
<!-- 删除确认对话框 -->
<el-dialog
v-model="deleteDialogVisible"
title="确认删除"
width="300px"
:show-close="false"
>
<div class="text-center py-4">
<el-icon class="text-orange-500 text-4xl mb-3"><WarningFilled /></el-icon>
<p>确定要删除这条记录吗</p>
<p class="text-gray-500 text-sm mt-2">此操作不可撤销请谨慎操作</p>
</div>
<template #footer>
<div class="flex justify-center gap-2">
<el-button @click="deleteDialogVisible = false">取消</el-button>
<el-button
type="danger"
@click="confirmDelete"
:loading="deleteLoading"
>
确认删除
</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { ref, reactive, onMounted, computed, toRaw } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { WarningFilled } from '@element-plus/icons-vue';
import { useUserStoreHook } from '@/store/modules/user';
const userStore = useUserStoreHook();
const currentProject = computed(() => userStore.selectedProject);
const { proxy } = getCurrentInstance();
import { useMaterialsQueryList,newMaterialsAdd,materialsEdit,materialsDel,queryMaterialsInfo} from "@/api/materials/usageMaterials/index";
// 表格数据相关
const tableData = ref([]);
const total = ref(0);
const currentPage = ref(1);
const pageSize = ref(10);
const loading = ref(false);
// 搜索表单
const searchForm = reactive({
findType: '3', // 默认查询所有
keyword: ''
});
// 对话框相关
const dialogVisible = ref(false);
const dialogType = ref('add'); // add 或 edit
const dialogWidth = ref('70%');
const isFullscreen = ref(false);
const deleteDialogVisible = ref(false);
const formRef = ref(null);
const saveLoading = ref(false);
const deleteLoading = ref(false);
const currentRow = ref(null);
// 表单数据
const formData = reactive({
id: '',
name: '',
specification: '',
supplier: '',
findType: '1', // 默认采购
installationQuantity: '',
installationRatio: '',
contractSigning: '',
productionPhase: null,
executionCycle: null,
projectId: null,
supplyRequirements: '',
purchaseSubmission: '',
submissionMaterials: '',
remark: '',
createTime: '',
createBy: null,
updateTime: '',
updateBy: null
});
// 表单验证规则
const formRules = reactive({
name: [
{ required: true, message: '请输入材料名称', trigger: 'blur' },
{ max: 50, message: '材料名称不能超过50个字符', trigger: 'blur' }
],
supplier: [
{ required: true, message: '请输入供应商', trigger: 'blur' },
{ max: 100, message: '供应商名称不能超过100个字符', trigger: 'blur' }
],
findType: [
{ required: true, message: '请选择类型', trigger: 'change' }
]
});
// 初始化页面
onMounted(() => {
fetchData();
});
// 格式化日期
const formatDate = (dateString) => {
if (!dateString) return '-';
const date = new Date(dateString);
return date.toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
}).replace(',', ' ');
};
// 表格行样式
const tableRowClassName = ({ row, rowIndex }) => {
return rowIndex % 2 === 0 ? 'bg-white' : 'bg-gray-50';
};
// 获取数据
const fetchData = async () => {
loading.value = true;
try {
const res = await useMaterialsQueryList({
projectId: currentProject.value?.id,
findType:2
});
tableData.value = res.rows;
total.value = res.total;
loading.value = false;
} catch (error) {
ElMessage.error('获取数据失败:' + error.message);
console.error(error);
} finally {
loading.value = false;
}
};
// 搜索
const handleSearch = () => {
currentPage.value = 1; // 重置到第一页
fetchData();
};
// 刷新数据
const refreshData = () => {
fetchData();
ElMessage.success('数据已刷新');
};
// 分页大小改变
const handleSizeChange = (val) => {
pageSize.value = val;
currentPage.value = 1;
fetchData();
};
// 当前页改变
const handleCurrentChange = (val) => {
currentPage.value = val;
fetchData();
};
// 新增
const handleAdd = () => {
dialogType.value = 'add';
resetForm();
dialogVisible.value = true;
};
// 编辑
const handleEdit = (row) => {
dialogType.value = 'edit';
currentRow.value = row;
resetForm();
// 填充表单数据
Object.keys(formData).forEach(key => {
if (row.hasOwnProperty(key)) {
formData[key] = row[key];
}
});
dialogVisible.value = true;
};
// 双击行编辑
const handleRowDblClick = (row) => {
handleEdit(row);
};
// 删除
const handleDelete = (row) => {
currentRow.value = row;
deleteDialogVisible.value = true;
};
// 确认删除
const confirmDelete = async () => {
if (!currentRow.value) return;
deleteLoading.value = true;
try {
// 模拟API请求
await new Promise(resolve => setTimeout(resolve, 500));
// 从表格中移除数据
tableData.value = tableData.value.filter(item => item.id !== currentRow.value.id);
total.value--;
deleteDialogVisible.value = false;
ElMessage.success('删除成功');
} catch (error) {
ElMessage.error('删除失败:' + error.message);
console.error(error);
} finally {
deleteLoading.value = false;
}
};
// 保存
const handleSave = async () => {
// 表单验证
if (!formRef.value) return;
const valid = await formRef.value.validate();
if (!valid) return;
saveLoading.value = true;
try {
// 模拟API请求
await new Promise(resolve => setTimeout(resolve, 800));
const form = toRaw(formData);
if (dialogType.value === 'add') {
// 新增
const newId = Math.max(...tableData.value.map(item => item.id), 0) + 1;
const newItem = {
...form,
id: newId,
createTime: new Date().toISOString().slice(0, 19).replace('T', ' '),
createBy: 1, // 假设当前用户ID为1
updateTime: null,
updateBy: null
};
tableData.value.unshift(newItem);
total.value++;
ElMessage.success('新增成功');
} else {
// 编辑
const index = tableData.value.findIndex(item => item.id === form.id);
if (index !== -1) {
tableData.value[index] = {
...form,
updateTime: new Date().toISOString().slice(0, 19).replace('T', ' '),
updateBy: 1 // 假设当前用户ID为1
};
ElMessage.success('更新成功');
}
}
dialogVisible.value = false;
} catch (error) {
ElMessage.error('保存失败:' + error.message);
console.error(error);
} finally {
saveLoading.value = false;
}
};
// 重置表单
const resetForm = () => {
if (formRef.value) {
formRef.value.resetFields();
}
// 重置表单数据
Object.keys(formData).forEach(key => {
formData[key] = '';
});
// 设置默认值
formData.findType = '1';
formData.id = '';
};
// 关闭对话框
const handleDialogClose = () => {
resetForm();
dialogVisible.value = false;
};
</script>
<style scoped>
/* 自定义表格行悬停样式 */
::v-deep .el-table__row:hover > td {
background-color: #f0f7ff !important;
}
/* 表单间距优化 */
::v-deep .el-form-item {
margin-bottom: 16px;
}
/* 对话框动画 */
::v-deep .el-dialog__wrapper {
backdrop-filter: blur(2px);
}
/* 按钮样式优化 */
::v-deep .el-button--primary {
transition: all 0.2s ease;
}
::v-deep .el-button--primary:hover {
transform: translateY(-2px);
}
</style>