|
@@ -1,124 +1,134 @@
|
|
|
<template>
|
|
|
- <div class="app-container p-2">
|
|
|
- <el-row :gutter="20">
|
|
|
- <el-col :span="6">
|
|
|
- <h2>新增</h2>
|
|
|
- </el-col>
|
|
|
- <el-col :lg="24" :xs="24">
|
|
|
- <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="materialType">
|
|
|
- <template #default="{ row, $index }">
|
|
|
- <span
|
|
|
- class="editable-span"
|
|
|
- contenteditable="true"
|
|
|
- @blur="saveEdit($index, 'materialType', $event.target.innerText)"
|
|
|
- v-text="row.materialType"
|
|
|
- ></span>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column label="物资名称" prop="materialName">
|
|
|
- <template #default="{ row, $index }">
|
|
|
- <span
|
|
|
- class="editable-span"
|
|
|
- contenteditable="true"
|
|
|
- @blur="saveEdit($index, 'materialName', $event.target.innerText)"
|
|
|
- v-text="row.materialName"
|
|
|
- ></span>
|
|
|
- </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="unitPrice">
|
|
|
- <template #default="{ row, $index }">
|
|
|
- <span
|
|
|
- class="editable-span"
|
|
|
- contenteditable="true"
|
|
|
- @blur="saveEdit($index, 'unitPrice', $event.target.innerText)"
|
|
|
- v-text="row.unitPrice"
|
|
|
- ></span>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column label="物资用途" prop="purpose">
|
|
|
- <template #default="{ row, $index }">
|
|
|
- <span
|
|
|
- class="editable-span"
|
|
|
- contenteditable="true"
|
|
|
- @blur="saveEdit($index, 'purpose', $event.target.innerText)"
|
|
|
- v-text="row.purpose"
|
|
|
- ></span>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- </el-table>
|
|
|
- </el-col>
|
|
|
- <div class="common-dialog-footer" style="width: 100%; justify-content: center; display: flex">
|
|
|
- <el-row :span="24" :gutter="10" class="mb8">
|
|
|
- <el-col :span="1.5">
|
|
|
- <el-button type="primary" @click="handleAddRow">新增一项</el-button>
|
|
|
- </el-col>
|
|
|
- <el-col :span="1.5">
|
|
|
- <el-button type="primary" @click="handleSave">提交</el-button>
|
|
|
- </el-col>
|
|
|
- <el-col :span="1.5">
|
|
|
- <el-button type="danger" @click="handleReturn">取消</el-button>
|
|
|
- </el-col>
|
|
|
- </el-row>
|
|
|
+ <div class="common-dialog">
|
|
|
+ <div class="common-dialog-content">
|
|
|
+ <div class="common-dialog-title-box">
|
|
|
+ <i class="common-dialog-title-icon" />
|
|
|
+ <div>{{ props.id ? '修改物资申报' : '新增物资申报' }}</div>
|
|
|
</div>
|
|
|
- </el-row>
|
|
|
+ <div class="common-dialog-box">
|
|
|
+ <div class="text-box">
|
|
|
+ <div class="text1">申报金额:</div>
|
|
|
+ <div v-show="!!detailData.declaration_amount" class="text2">{{ formatToTwoDecimalPlaces(detailData.declaration_amount) }}元</div>
|
|
|
+ </div>
|
|
|
+ <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_type" align="center">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-form-item :prop="'detail.' + scope.$index + '.material_type'" :rules="rules.material_type">
|
|
|
+ <el-select v-model="scope.row.material_type">
|
|
|
+ <el-option v-for="(item, index) in material_type" :key="index" :label="item.label" :value="item.value" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="物资名称" prop="material_code" align="center">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-form-item :prop="'detail.' + scope.$index + '.material_type'" :rules="rules.material_type">
|
|
|
+ <el-select v-model="scope.row.material_code">
|
|
|
+ <el-option v-for="(item, index) in materialList" :key="index" :label="item.material_name" :value="item.material_id" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <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_unit_price" align="center">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-form-item :prop="'detail.' + scope.$index + '.material_type'" :rules="rules.material_type">
|
|
|
+ <el-input v-model="scope.row.material_unit_price" 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_type'" :rules="rules.material_type">
|
|
|
+ <el-input v-model="scope.row.material_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 @click="handleReturn">取消</el-button>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button type="primary" @click="handleAddRow">新增一项</el-button>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button :loading="buttonLoading" type="primary" @click="submitForm(formRef)">确定</el-button>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
-import { ref, onMounted } from 'vue';
|
|
|
-import { ElTable, ElButton, ElCol, ElRow, ElTableColumn } from 'element-plus';
|
|
|
-import { defineProps, defineEmits } from 'vue';
|
|
|
+import { getMaterialList } from '@/api/comprehensiveGuarantee/materialReserveManagement/MaterialStatistics';
|
|
|
+import {
|
|
|
+ createProcurement,
|
|
|
+ getDeclarationDetail,
|
|
|
+ updateProcurement
|
|
|
+} from '@/api/comprehensiveGuarantee/materialReserveManagement/materialsDeclaration';
|
|
|
+import BigNumber from 'bignumber.js';
|
|
|
+import { formatToTwoDecimalPlaces, isNumericString } from '@/utils';
|
|
|
|
|
|
const props = defineProps({
|
|
|
- eventId: String
|
|
|
+ id: String
|
|
|
});
|
|
|
|
|
|
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
|
|
+const { material_type } = toRefs<any>(proxy?.useDict('material_type'));
|
|
|
const emits = defineEmits(['close']);
|
|
|
|
|
|
-const tableData = ref<any[]>([]);
|
|
|
-
|
|
|
+const formRef = ref();
|
|
|
+let detailData = reactive({
|
|
|
+ declaration_amount: '',
|
|
|
+ detail: []
|
|
|
+});
|
|
|
+const rules = reactive({
|
|
|
+ material_type: [{ required: true, message: '请选择物资类型', trigger: 'change' }],
|
|
|
+ material_code: [{ required: true, message: '请选择物资名称', trigger: 'change' }],
|
|
|
+ material_quantity: [{ required: true, message: '请输入物资数量', trigger: 'blur' }],
|
|
|
+ material_unit_price: [{ required: true, message: '请输入物资单价', trigger: 'blur' }],
|
|
|
+ material_purpose: [{ required: true, message: '请输入物资用途', trigger: 'blur' }]
|
|
|
+});
|
|
|
+let materialList = ref([]);
|
|
|
+// 新增一列
|
|
|
const addDefaultRow = () => {
|
|
|
const newRow = {
|
|
|
- materialType: '',
|
|
|
- materialName: '',
|
|
|
- quantity: '', // 用户需要输入
|
|
|
- unitPrice: '', // 用户需要输入
|
|
|
- purpose: ''
|
|
|
+ material_type: '',
|
|
|
+ material_code: '',
|
|
|
+ material_quantity: '',
|
|
|
+ material_unit_price: '',
|
|
|
+ material_purpose: ''
|
|
|
};
|
|
|
- tableData.value.push(newRow);
|
|
|
+ detailData.detail.push(newRow);
|
|
|
};
|
|
|
|
|
|
-const saveEdit = (index: number, key: string, value: string) => {
|
|
|
- let numValue = value;
|
|
|
-
|
|
|
- if (key === 'quantity' || key === 'unitPrice') {
|
|
|
- numValue = parseFloat(value);
|
|
|
- if (isNaN(numValue) || numValue < 0) {
|
|
|
- // 如果不是有效的数字或者数字小于0,则不更新数据
|
|
|
- alert('请输入有效的正数!');
|
|
|
- return;
|
|
|
+// 计算总额
|
|
|
+const calcTotalAmount = () => {
|
|
|
+ let total = new BigNumber('0');
|
|
|
+ detailData.detail.forEach((item) => {
|
|
|
+ if (isNumericString(item.material_quantity) && isNumericString(item.material_unit_price)) {
|
|
|
+ const num = new BigNumber(item.material_quantity).times(new BigNumber(item.material_unit_price));
|
|
|
+ total = total.plus(num);
|
|
|
}
|
|
|
- numValue = numValue.toString();
|
|
|
- }
|
|
|
-
|
|
|
- tableData.value[index][key] = numValue;
|
|
|
- localStorage.setItem('tableData', JSON.stringify(tableData.value));
|
|
|
+ });
|
|
|
+ detailData.declaration_amount = total.toString();
|
|
|
};
|
|
|
|
|
|
const handleAddRow = () => addDefaultRow();
|
|
@@ -127,42 +137,80 @@ const handleReturn = () => {
|
|
|
emits('close');
|
|
|
};
|
|
|
|
|
|
-const handleSave = () => {
|
|
|
- // 这里可以添加保存到服务器的逻辑
|
|
|
- console.log('数据已保存:', tableData.value);
|
|
|
+const submitForm = async (formEl) => {
|
|
|
+ if (!formEl) return;
|
|
|
+ await formEl.validate((valid) => {
|
|
|
+ if (valid) {
|
|
|
+ if (props.id) {
|
|
|
+ updateProcurement(detailData, props.id).then(() => {
|
|
|
+ proxy.$modal.msgSuccess('修改成功');
|
|
|
+ emits('close', true);
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ createProcurement(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;
|
|
|
+ }
|
|
|
+ });
|
|
|
};
|
|
|
|
|
|
+let height = ref(400);
|
|
|
+// 计算表格高度
|
|
|
+const calcHeight = () => {
|
|
|
+ const el = document.getElementsByClassName('common-dialog-content')[0];
|
|
|
+ height.value = el ? el.clientHeight - 173 : 400;
|
|
|
+};
|
|
|
+onMounted(() => {
|
|
|
+ if (props.id) {
|
|
|
+ getDeclarationDetail(props.id).then((res) => {
|
|
|
+ detailData.declaration_amount = res.data.declaration_amount;
|
|
|
+ detailData.detail = res.data.detail;
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ addDefaultRow();
|
|
|
+ }
|
|
|
+ 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; /* 移除编辑时的焦点边框 */
|
|
|
-}
|
|
|
-.editable-span[contenteditable='true']:empty::before {
|
|
|
- content: attr(data-placeholder); /* 可选:为空时显示占位符 */
|
|
|
- color: #999;
|
|
|
+<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;
|
|
|
+ }
|
|
|
}
|
|
|
-.common-dialog-footer {
|
|
|
- margin-top: 20px;
|
|
|
+.el-form-item {
|
|
|
+ margin: 18px 0;
|
|
|
}
|
|
|
</style>
|