|
@@ -1,264 +1,217 @@
|
|
|
<template>
|
|
|
<div class="common-dialog">
|
|
|
<div class="common-dialog-content">
|
|
|
- <el-row :gutter="20">
|
|
|
- <div class="common-dialog-title-box">
|
|
|
- <i class="common-dialog-title-icon" />
|
|
|
- <div>新增物资调度</div>
|
|
|
+ <div class="common-dialog-title-box">
|
|
|
+ <i class="common-dialog-title-icon" />
|
|
|
+ <div>新增物资调度</div>
|
|
|
+ </div>
|
|
|
+ <div class="common-dialog-box">
|
|
|
+ <div class="text-box">
|
|
|
+ <div class="text1">调度目的:</div>
|
|
|
+ <el-input v-model="dispatch_purpose" class="text2" type="textarea" autosize placeholder="请输入" :style="{ width: '500px' }" />
|
|
|
</div>
|
|
|
- <el-col :lg="24" :xs="24">
|
|
|
- <div class="common-dialog-box">
|
|
|
- <el-table :data="tableData" border height="400">
|
|
|
- <el-table-column label="序号" prop="seqNo" width="80">
|
|
|
- <template #default="{ $index }">
|
|
|
- <span>{{ $index + 1 }}</span>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column label="仓库名称" prop="warehouse_id">
|
|
|
- <template #default="{ row, $index }">
|
|
|
- <el-select v-model="row.warehouse_id" placeholder="请选择仓库">
|
|
|
- <el-option
|
|
|
- v-for="item in warehouseOptions"
|
|
|
- :key="item.warehouse_id"
|
|
|
- :label="item.warehouse_name"
|
|
|
- :value="item.warehouse_id"
|
|
|
- ></el-option>
|
|
|
- </el-select>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column label="物资类型" prop="materialType">
|
|
|
- <template #default="{ row, $index }">
|
|
|
- <el-select v-model="row.materialType" placeholder="请选择物资类型">
|
|
|
- <el-option
|
|
|
- v-for="item in materialTypeOptions"
|
|
|
- :key="item.material_type_id"
|
|
|
- :label="item.material_type_name"
|
|
|
- :value="item.material_type_name"
|
|
|
- ></el-option>
|
|
|
- </el-select>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column label="物资名称" prop="materialCode">
|
|
|
- <template #default="{ row, $index }">
|
|
|
- <el-select v-model="row.materialCode" placeholder="请选择物资">
|
|
|
- <el-option
|
|
|
- v-for="item in materialOptions"
|
|
|
- :key="item.material_id"
|
|
|
- :label="item.material_name"
|
|
|
- :value="item.material_id"
|
|
|
- ></el-option>
|
|
|
- </el-select>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column label="物资数量(件)" prop="quantity">
|
|
|
- <template #default="{ row, $index }">
|
|
|
- <span
|
|
|
- class="editable-span"
|
|
|
- contenteditable="true"
|
|
|
- @blur="saveEdit($index, 'quantity', $event.target.innerText)"
|
|
|
- v-text="row.quantity || ''"
|
|
|
- ></span>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column label="物资用途" prop="material_purpose">
|
|
|
- <template #default="{ row, $index }">
|
|
|
- <span
|
|
|
- class="editable-span"
|
|
|
- contenteditable="true"
|
|
|
- @blur="saveEdit($index, 'material_purpose', $event.target.innerText)"
|
|
|
- v-text="row.material_purpose || ''"
|
|
|
- ></span>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column label="调度目的" prop="dispatch_purpose">
|
|
|
- <template #default="{ row, $index }">
|
|
|
- <span
|
|
|
- class="editable-span"
|
|
|
- contenteditable="true"
|
|
|
- @blur="saveEdit($index, 'dispatch_purpose', $event.target.innerText)"
|
|
|
- v-text="row.dispatch_purpose || ''"
|
|
|
- ></span>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- </el-table>
|
|
|
- </div>
|
|
|
- </el-col>
|
|
|
- <div class="common-dialog-footer" style="width: 100%; justify-content: center; display: flex">
|
|
|
- <el-row :gutter="10" class="mb8">
|
|
|
+ <el-form ref="formRef" :model="detailData" style="width: 100%">
|
|
|
+ <el-table :data="detailData.detail" border :height="height">
|
|
|
+ <el-table-column label="序号" width="80" align="center">
|
|
|
+ <template #default="{ $index }">
|
|
|
+ <span>{{ $index + 1 }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="物资名称" prop="material_name" align="center">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-form-item :prop="'detail.' + scope.$index + '.material_type'" :rules="rules.material_name">
|
|
|
+ <el-input v-model="scope.row.material_name" readonly>
|
|
|
+ <template #append>
|
|
|
+ <el-button @click="handleShowSelect(scope.$index)">选择</el-button>
|
|
|
+ </template>
|
|
|
+ </el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="仓库" prop="warehouse_name" align="center" />
|
|
|
+ <el-table-column label="物资类型" prop="material_type" align="center" />
|
|
|
+ <el-table-column label="物资数量(件)" prop="material_quantity" align="center">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-form-item :prop="`detail.${scope.$index}.material_quantity`" :rules="rules.material_quantity">
|
|
|
+ <el-input v-model="scope.row.material_quantity" type="number" placeholder="请输入" @input="calcTotalAmount" />
|
|
|
+ </el-form-item>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="物资用途" prop="material_purpose" align="center">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-form-item :prop="'detail.' + scope.$index + '.material_purpose'" :rules="rules.material_purpose">
|
|
|
+ <el-input v-model="scope.row.material_purpose" type="textarea" autosize placeholder="请输入" />
|
|
|
+ </el-form-item>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="调度目的" prop="dispatch_purpose" align="center">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-form-item :prop="'detail.' + scope.$index + '.dispatch_purpose'" :rules="rules.dispatch_purpose">
|
|
|
+ <el-input v-model="scope.row.dispatch_purpose" type="textarea" autosize placeholder="请输入" />
|
|
|
+ </el-form-item>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </el-form>
|
|
|
+ <div class="common-dialog-footer" style="margin-top: 18px">
|
|
|
+ <el-row :span="24" :gutter="10" class="mb8">
|
|
|
<el-col :span="1.5">
|
|
|
- <el-button type="primary" @click="handleAddRow">新增一项</el-button>
|
|
|
+ <el-button @click="handleReturn">取消</el-button>
|
|
|
</el-col>
|
|
|
<el-col :span="1.5">
|
|
|
- <el-button type="primary" @click="handleSave">提交</el-button>
|
|
|
+ <el-button type="primary" @click="handleAddRow">新增一项</el-button>
|
|
|
</el-col>
|
|
|
<el-col :span="1.5">
|
|
|
- <el-button type="danger" @click="handleReturn">取消</el-button>
|
|
|
+ <el-button :loading="buttonLoading" type="primary" @click="submitForm(formRef)">确定</el-button>
|
|
|
</el-col>
|
|
|
</el-row>
|
|
|
</div>
|
|
|
- </el-row>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
+ <materialTreeSelect v-model="showSelect" @confirm="handleSelectChange" />
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
-import { ref, onMounted } from 'vue';
|
|
|
-import { getMaterialList, createDispatch } from '@/api/comprehensiveGuarantee/materialReserveManagement/materialsDistribution'; // 确保路径和导入语句是正确的
|
|
|
+import { createDispatch } from '@/api/comprehensiveGuarantee/materialReserveManagement/materialsDistribution';
|
|
|
+import materialTreeSelect from './materialTreeSelect';
|
|
|
+import { getMaterialWarehouseList } from '@/api/comprehensiveGuarantee/materialReserveManagement/godownManagement';
|
|
|
|
|
|
const props = defineProps({
|
|
|
- eventId: String
|
|
|
+ id: String
|
|
|
});
|
|
|
|
|
|
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
|
|
const emits = defineEmits(['close']);
|
|
|
|
|
|
-const tableData = ref<any[]>([]);
|
|
|
-const warehouseOptions = ref<{ warehouse_id: string; warehouse_name: string }[]>([]);
|
|
|
-const materialOptions = ref<{ material_id: number; material_name: string }[]>([]);
|
|
|
-const materialTypeOptions = ref<{ material_type_id: string; material_type_name: string }[]>([]);
|
|
|
+const formRef = ref();
|
|
|
+let detailData = reactive({
|
|
|
+ dispatch_purpose: '',
|
|
|
+ detail: []
|
|
|
+});
|
|
|
+const rules = reactive({
|
|
|
+ material_name: [{ required: true, message: '请选择物资名称', trigger: 'change' }],
|
|
|
+ material_quantity: [{ required: true, message: '请输入物资数量', trigger: 'blur' }],
|
|
|
+ dispatch_purpose: [{ required: true, message: '请输入调度目的', trigger: 'blur' }],
|
|
|
+ material_purpose: [{ required: true, message: '请输入物资用途', trigger: 'blur' }]
|
|
|
+});
|
|
|
+let buttonLoading = ref(false);
|
|
|
+let warehouseList = ref([]);
|
|
|
|
|
|
-// 添加默认行
|
|
|
-const addDefaultRow = () => {
|
|
|
+const handleAddRow = () => {
|
|
|
const newRow = {
|
|
|
- warehouse_id: '',
|
|
|
- materialTypeId: '',
|
|
|
- materialType: '',
|
|
|
- materialCode: '',
|
|
|
- quantity: '',
|
|
|
- material_purpose: '',
|
|
|
- dispatch_purpose: ''
|
|
|
+ id: '',
|
|
|
+ warehouse_name: '',
|
|
|
+ material_name: '',
|
|
|
+ material_type: '',
|
|
|
+ material_code: '',
|
|
|
+ material_quantity: '',
|
|
|
+ material_unit_price: '',
|
|
|
+ material_purpose: ''
|
|
|
};
|
|
|
- tableData.value.push(newRow);
|
|
|
-};
|
|
|
-
|
|
|
-// 获取仓库、物资和物资类型列表
|
|
|
-const fetchMaterialList = async () => {
|
|
|
- try {
|
|
|
- const response = await getMaterialList();
|
|
|
- if (response.code === 200) {
|
|
|
- // 去重逻辑
|
|
|
- const uniqueWarehouseOptions = Array.from(new Set(response.data.map(item => JSON.stringify(item)))).map(item => JSON.parse(item));
|
|
|
- warehouseOptions.value = uniqueWarehouseOptions.map((item) => ({
|
|
|
- warehouse_id: item.warehouse_id,
|
|
|
- warehouse_name: item.warehouse_name
|
|
|
- }));
|
|
|
-
|
|
|
- const uniqueMaterialTypeOptions = Array.from(new Set(response.data.map(item => JSON.stringify({material_type_id: item.material_type_id, material_type_name: item.material_type_name})))).map(item => JSON.parse(item));
|
|
|
- materialTypeOptions.value = uniqueMaterialTypeOptions.map((item) => ({
|
|
|
- material_type_id: item.material_type_id,
|
|
|
- material_type_name: item.material_type_name
|
|
|
- }));
|
|
|
-
|
|
|
- const uniqueMaterialOptions = Array.from(new Set(response.data.map(item => JSON.stringify({material_id: item.material_id, material_name: item.material_name})))).map(item => JSON.parse(item));
|
|
|
- materialOptions.value = uniqueMaterialOptions.map((item) => ({
|
|
|
- material_id: item.material_id,
|
|
|
- material_name: item.material_name
|
|
|
- }));
|
|
|
- }
|
|
|
- } catch (error) {
|
|
|
- console.error('获取仓库和物资列表失败:', error);
|
|
|
- }
|
|
|
-};
|
|
|
-
|
|
|
-// 保存编辑内容到本地存储
|
|
|
-const saveEdit = (index: number, key: string, value: string) => {
|
|
|
- tableData.value[index][key] = value;
|
|
|
- localStorage.setItem('tableData', JSON.stringify(tableData.value));
|
|
|
+ detailData.detail.push(newRow);
|
|
|
};
|
|
|
|
|
|
-// 处理添加新行
|
|
|
-const handleAddRow = () => addDefaultRow();
|
|
|
-
|
|
|
-// 处理返回
|
|
|
const handleReturn = () => {
|
|
|
emits('close');
|
|
|
};
|
|
|
|
|
|
-// 方法:转换表格数据为后端期望的格式
|
|
|
-const transformTableData = (): any => {
|
|
|
- return {
|
|
|
- dispatch_purpose: tableData.value[0].dispatch_purpose || '', // 根据实际业务逻辑填写或从其他地方获取
|
|
|
- detail: tableData.value.map((row, index) => ({
|
|
|
- serial_number: (index + 1).toString(),
|
|
|
- warehouse_id: row.warehouse_id || null,
|
|
|
- material_type_id: row.materialTypeId || null,
|
|
|
- material_type: row.materialType || null,
|
|
|
- material_code: row.materialCode || null,
|
|
|
- material_quantity: parseInt(row.quantity, 10),
|
|
|
- material_purpose: row.material_purpose || null
|
|
|
- }))
|
|
|
- };
|
|
|
+const submitForm = async (formEl) => {
|
|
|
+ if (!formEl) return;
|
|
|
+ await formEl.validate((valid) => {
|
|
|
+ if (valid) {
|
|
|
+ createDispatch(detailData).then(() => {
|
|
|
+ proxy.$modal.msgSuccess('新增成功');
|
|
|
+ emits('close', true);
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ nextTick(() => {
|
|
|
+ let isError = document.getElementsByClassName('is-error');
|
|
|
+ isError[0].scrollIntoView({
|
|
|
+ // 滚动到指定节点
|
|
|
+ // 值有start,center,end,nearest,当前显示在视图区域中间
|
|
|
+ block: 'center',
|
|
|
+ // 值有auto、instant,smooth,缓动动画(当前是慢速的)
|
|
|
+ behavior: 'smooth'
|
|
|
+ });
|
|
|
+ });
|
|
|
+ proxy.$modal.msgError('表单校验失败');
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ });
|
|
|
};
|
|
|
|
|
|
-// 方法:处理保存操作
|
|
|
-const handleSave = async () => {
|
|
|
- console.log('Handle Save Called'); // 调试信息
|
|
|
-
|
|
|
- const requestData = transformTableData();
|
|
|
-
|
|
|
- // 验证必填字段
|
|
|
- if (!validateRequiredFields(requestData)) {
|
|
|
- console.error('Validation failed');
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- try {
|
|
|
- console.log('Request Data:', requestData); // 打印请求数据
|
|
|
- const response = await createDispatch(requestData);
|
|
|
- console.log('Dispatch created successfully:', response);
|
|
|
- // 可选:关闭对话框或其他操作
|
|
|
- emits('close'); // 如果需要的话
|
|
|
- emits('refresh');
|
|
|
- } catch (error) {
|
|
|
- console.error('物资调度创建失败:', error);
|
|
|
+let showSelect = ref(false);
|
|
|
+let selectIndex = ref('');
|
|
|
+const handleShowSelect = (index) => {
|
|
|
+ selectIndex.value = index;
|
|
|
+ showSelect.value = true;
|
|
|
+};
|
|
|
+const handleSelectChange = (data) => {
|
|
|
+ detailData.detail[selectIndex.value].material_code = data.id;
|
|
|
+ detailData.detail[selectIndex.value].material_name = data.label;
|
|
|
+ detailData.detail[selectIndex.value].warehouse_name = data.warehouse_name;
|
|
|
+ detailData.detail[selectIndex.value].material_type = data.type;
|
|
|
+};
|
|
|
|
|
|
- // 提示用户关于具体的错误信息,比如哪个字段为空
|
|
|
- if (error.response && error.response.data.detail) {
|
|
|
- alert(error.response.data.detail); // 或者使用更友好的方式展示给用户
|
|
|
- }
|
|
|
- }
|
|
|
+let height = ref(300);
|
|
|
+// 计算表格高度
|
|
|
+const calcHeight = () => {
|
|
|
+ const el = document.getElementsByClassName('common-dialog-content')[0];
|
|
|
+ height.value = el && el.clientHeight - 173 > 400 ? el.clientHeight - 173 : 300;
|
|
|
};
|
|
|
-// 示例验证函数实现
|
|
|
-const validateRequiredFields = (requestData) => {
|
|
|
- if (!requestData.detail.every(item => item.warehouse_id && item.material_code && item.material_quantity > 0)) {
|
|
|
- return false;
|
|
|
+onMounted(() => {
|
|
|
+ if (props.id) {
|
|
|
+ getDeclarationDetail(props.id).then((res) => {
|
|
|
+ detailData.dispatch_purpose = res.data.dispatch_purpose;
|
|
|
+ detailData.detail = res.data.detail;
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ handleAddRow();
|
|
|
}
|
|
|
- return true;
|
|
|
-};
|
|
|
-onMounted(async () => {
|
|
|
- await fetchMaterialList();
|
|
|
- addDefaultRow();
|
|
|
+ getMaterialWarehouseList().then((res) => {
|
|
|
+ warehouseList.value = res.data;
|
|
|
+ });
|
|
|
+ // getMaterialList().then((res) => {
|
|
|
+ // materialList.value = res.data;
|
|
|
+ // });
|
|
|
+ calcHeight();
|
|
|
+ window.addEventListener('resize', calcHeight);
|
|
|
+});
|
|
|
+onUnmounted(() => {
|
|
|
+ window.removeEventListener('resize', calcHeight);
|
|
|
});
|
|
|
</script>
|
|
|
|
|
|
-<style scoped>
|
|
|
-.app-container {
|
|
|
- font-family: Avenir, Helvetica, Arial, sans-serif;
|
|
|
- -webkit-font-smoothing: antialiased;
|
|
|
- -moz-osx-font-smoothing: grayscale;
|
|
|
- text-align: center;
|
|
|
- color: #2c3e50;
|
|
|
-}
|
|
|
-.report-period {
|
|
|
- margin-top: 10px;
|
|
|
- font-size: 14px;
|
|
|
- color: #606266;
|
|
|
-}
|
|
|
-.editable-span {
|
|
|
- cursor: pointer;
|
|
|
- display: inline-block;
|
|
|
- white-space: nowrap;
|
|
|
- overflow: hidden;
|
|
|
- text-overflow: ellipsis;
|
|
|
-}
|
|
|
-.editable-span[contenteditable='true'] {
|
|
|
- white-space: normal;
|
|
|
- outline: none; /* 移除编辑时的焦点边框 */
|
|
|
+<style lang="scss" scoped>
|
|
|
+.text-box {
|
|
|
+ width: 100%;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ padding-bottom: 10px;
|
|
|
+ color: rgba(0, 0, 0, 0.85);
|
|
|
+ .text1 {
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: bold;
|
|
|
+ }
|
|
|
+ .text2 {
|
|
|
+ font-size: 18px;
|
|
|
+ }
|
|
|
}
|
|
|
-.editable-span[contenteditable='true']:empty::before {
|
|
|
- content: attr(data-placeholder); /* 可选:为空时显示占位符 */
|
|
|
- color: #999;
|
|
|
+.el-form-item {
|
|
|
+ margin: 18px 0;
|
|
|
}
|
|
|
-.common-dialog-footer {
|
|
|
- margin-top: 20px;
|
|
|
+:deep(.custom-disabled) {
|
|
|
+ .el-select__wrapper.is-disabled,
|
|
|
+ .el-input__wrapper,
|
|
|
+ .el-textarea__inner {
|
|
|
+ background-color: #ffffff !important;
|
|
|
+ }
|
|
|
+ .el-select__wrapper.is-disabled .el-select__selected-item,
|
|
|
+ .el-input__inner,
|
|
|
+ .el-textarea__inner {
|
|
|
+ color: rgba(0, 0, 0, 0.85) !important;
|
|
|
+ -webkit-text-fill-color: rgba(0, 0, 0, 0.85) !important;
|
|
|
+ }
|
|
|
}
|
|
|
</style>
|