materialsDeclarationAdd.vue 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. <template>
  2. <div class="common-dialog">
  3. <div class="common-dialog-content">
  4. <div class="common-dialog-title-box">
  5. <i class="common-dialog-title-icon" />
  6. <div>{{ props.id ? '修改物资申报' : '新增物资申报' }}</div>
  7. </div>
  8. <div class="common-dialog-box">
  9. <div class="text-box">
  10. <div class="text1">申报金额:</div>
  11. <div v-show="!!detailData.declaration_amount" class="text2">{{ formatToTwoDecimalPlaces(detailData.declaration_amount) }}元</div>
  12. </div>
  13. <el-form ref="formRef" :model="detailData" style="width: 100%">
  14. <el-table :data="detailData.detail" border :height="height">
  15. <el-table-column label="序号" width="80" align="center">
  16. <template #default="{ $index }">
  17. <span>{{ $index + 1 }}</span>
  18. </template>
  19. </el-table-column>
  20. <el-table-column label="物资名称" prop="material_name" align="center">
  21. <template #default="scope">
  22. <el-form-item :prop="'detail.' + scope.$index + '.material_type'" :rules="rules.material_name">
  23. <el-input v-model="scope.row.material_name" readonly>
  24. <template #append>
  25. <el-button @click="handleShowSelect(scope.$index)">选择</el-button>
  26. </template>
  27. </el-input>
  28. </el-form-item>
  29. </template>
  30. </el-table-column>
  31. <el-table-column label="仓库" prop="warehouse_id" align="center" />
  32. <el-table-column label="物资类型" prop="material_type" align="center" />
  33. <el-table-column label="物资数量(件)" prop="material_quantity" align="center">
  34. <template #default="scope">
  35. <el-form-item :prop="`detail.${scope.$index}.material_quantity`" :rules="rules.material_quantity">
  36. <el-input v-model="scope.row.material_quantity" type="number" placeholder="请输入" @input="calcTotalAmount" />
  37. </el-form-item>
  38. </template>
  39. </el-table-column>
  40. <el-table-column label="物资单价(元)" prop="material_unit_price" align="center">
  41. <template #default="scope">
  42. <el-form-item :prop="'detail.' + scope.$index + '.material_unit_price'" :rules="rules.material_unit_price">
  43. <el-input v-model="scope.row.material_unit_price" type="number" placeholder="请输入" @input="calcTotalAmount" />
  44. </el-form-item>
  45. </template>
  46. </el-table-column>
  47. <el-table-column label="物资用途" prop="material_purpose" align="center">
  48. <template #default="scope">
  49. <el-form-item :prop="'detail.' + scope.$index + '.material_purpose'" :rules="rules.material_purpose">
  50. <el-input v-model="scope.row.material_purpose" type="textarea" autosize placeholder="请输入" />
  51. </el-form-item>
  52. </template>
  53. </el-table-column>
  54. </el-table>
  55. </el-form>
  56. <div class="common-dialog-footer" style="margin-top: 18px">
  57. <el-row :span="24" :gutter="10" class="mb8">
  58. <el-col :span="1.5">
  59. <el-button @click="handleReturn">取消</el-button>
  60. </el-col>
  61. <el-col :span="1.5">
  62. <el-button type="primary" @click="handleAddRow">新增一项</el-button>
  63. </el-col>
  64. <el-col :span="1.5">
  65. <el-button :loading="buttonLoading" type="primary" @click="submitForm(formRef)">确定</el-button>
  66. </el-col>
  67. </el-row>
  68. </div>
  69. </div>
  70. </div>
  71. <materialTreeSelect v-model="showSelect" @confirm="handleSelectChange" />
  72. </div>
  73. </template>
  74. <script setup lang="ts">
  75. import {
  76. createProcurement,
  77. getDeclarationDetail,
  78. updateProcurement
  79. } from '@/api/comprehensiveGuarantee/materialReserveManagement/materialsDeclaration';
  80. import BigNumber from 'bignumber.js';
  81. import materialTreeSelect from './materialTreeSelect'
  82. import { formatToTwoDecimalPlaces, isNumericString } from '@/utils';
  83. import { getMaterialWarehouseList } from '@/api/comprehensiveGuarantee/materialReserveManagement/godownManagement';
  84. const props = defineProps({
  85. id: String
  86. });
  87. const { proxy } = getCurrentInstance() as ComponentInternalInstance;
  88. const emits = defineEmits(['close']);
  89. const formRef = ref();
  90. let detailData = reactive({
  91. declaration_amount: '',
  92. detail: []
  93. });
  94. const rules = reactive({
  95. material_name: [{ required: true, message: '请选择物资名称', trigger: 'change' }],
  96. material_quantity: [{ required: true, message: '请输入物资数量', trigger: 'blur' }],
  97. material_unit_price: [{ required: true, message: '请输入物资单价', trigger: 'blur' }],
  98. material_purpose: [{ required: true, message: '请输入物资用途', trigger: 'blur' }]
  99. });
  100. let buttonLoading = ref(false);
  101. let warehouseList = ref([]);
  102. let materialList = ref([]);
  103. // 计算总额
  104. const calcTotalAmount = () => {
  105. let total = new BigNumber('0');
  106. detailData.detail.forEach((item) => {
  107. if (isNumericString(item.material_quantity) && isNumericString(item.material_unit_price)) {
  108. const num = new BigNumber(item.material_quantity).times(new BigNumber(item.material_unit_price));
  109. total = total.plus(num);
  110. }
  111. });
  112. detailData.declaration_amount = total.toString();
  113. };
  114. const handleAddRow = () => {
  115. const newRow = {
  116. warehouse_id: '',
  117. material_name: '',
  118. material_type: '',
  119. material_code: '',
  120. material_quantity: '',
  121. material_unit_price: '',
  122. material_purpose: ''
  123. };
  124. detailData.detail.push(newRow);
  125. };
  126. const handleReturn = () => {
  127. emits('close');
  128. };
  129. const submitForm = async (formEl) => {
  130. if (!formEl) return;
  131. await formEl.validate((valid) => {
  132. if (valid) {
  133. if (props.id) {
  134. updateProcurement(detailData, props.id).then(() => {
  135. proxy.$modal.msgSuccess('修改成功');
  136. emits('close', true);
  137. });
  138. } else {
  139. createProcurement(detailData).then(() => {
  140. proxy.$modal.msgSuccess('新增成功');
  141. emits('close', true);
  142. });
  143. }
  144. } else {
  145. nextTick(() => {
  146. let isError = document.getElementsByClassName('is-error');
  147. isError[0].scrollIntoView({
  148. // 滚动到指定节点
  149. // 值有start,center,end,nearest,当前显示在视图区域中间
  150. block: 'center',
  151. // 值有auto、instant,smooth,缓动动画(当前是慢速的)
  152. behavior: 'smooth'
  153. });
  154. });
  155. proxy.$modal.msgError('表单校验失败');
  156. return false;
  157. }
  158. });
  159. };
  160. let showSelect = ref(false);
  161. let selectIndex = ref('');
  162. const handleShowSelect = (index) => {
  163. selectIndex.value = index;
  164. showSelect.value = true;
  165. };
  166. const handleSelectChange = (data) => {
  167. detailData.detail[selectIndex.value].material_code = data.id;
  168. detailData.detail[selectIndex.value].material_name = data.label;
  169. detailData.detail[selectIndex.value].warehouse_id = data.warehouse_id;
  170. detailData.detail[selectIndex.value].material_type = data.type;
  171. };
  172. let height = ref(300);
  173. // 计算表格高度
  174. const calcHeight = () => {
  175. const el = document.getElementsByClassName('common-dialog-content')[0];
  176. height.value = el && el.clientHeight - 173 > 400 ? el.clientHeight - 173 : 300;
  177. };
  178. onMounted(() => {
  179. if (props.id) {
  180. getDeclarationDetail(props.id).then((res) => {
  181. detailData.declaration_amount = res.data.declaration_amount;
  182. detailData.detail = res.data.detail;
  183. });
  184. } else {
  185. handleAddRow();
  186. }
  187. getMaterialWarehouseList().then((res) => {
  188. warehouseList.value = res.data;
  189. });
  190. // getMaterialList().then((res) => {
  191. // materialList.value = res.data;
  192. // });
  193. calcHeight();
  194. window.addEventListener('resize', calcHeight);
  195. });
  196. onUnmounted(() => {
  197. window.removeEventListener('resize', calcHeight);
  198. });
  199. </script>
  200. <style lang="scss" scoped>
  201. .text-box {
  202. width: 100%;
  203. display: flex;
  204. align-items: center;
  205. padding-bottom: 10px;
  206. color: rgba(0, 0, 0, 0.85);
  207. .text1 {
  208. font-size: 18px;
  209. font-weight: bold;
  210. }
  211. .text2 {
  212. font-size: 18px;
  213. }
  214. }
  215. .el-form-item {
  216. margin: 18px 0;
  217. }
  218. :deep(.custom-disabled) {
  219. .el-select__wrapper.is-disabled,
  220. .el-input__wrapper,
  221. .el-textarea__inner {
  222. background-color: #ffffff !important;
  223. }
  224. .el-select__wrapper.is-disabled .el-select__selected-item,
  225. .el-input__inner,
  226. .el-textarea__inner {
  227. color: rgba(0, 0, 0, 0.85) !important;
  228. -webkit-text-fill-color: rgba(0, 0, 0, 0.85) !important;
  229. }
  230. }
  231. </style>