华西海圻ELN前端工程
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

515 lines
18 KiB

  1. <template>
  2. <el-dialog :close-on-click-modal="false" :close-on-press-escape="false" title="分装(分装后的编号可用于下一步关联选择)" append-to-body
  3. :visible.sync="visible" @close="close" width="1100px">
  4. <div class="dialog-content">
  5. <div class="header-container">
  6. <div class="header-item">
  7. <div class="header-title">母液编号</div>
  8. <HandleFormItem :fieldKey="formData.mybh + '_mybh'" :isFieldsRecord="false" :item="inputItem" :error="formErrors.mybh"
  9. v-model="formData.mybh" />
  10. </div>
  11. <div class="header-item">
  12. <div class="header-title">分装数量</div>
  13. <HandleFormItem :isFieldsRecord="false" :fieldKey="formData.mybh + '_fzsl'" @blur="onBlurFzsl" :item="integerInputNumberItem"
  14. type="inputNumber" :error="formErrors.fzsl" v-model="formData.fzsl" />
  15. </div>
  16. </div>
  17. <div class="content-container">
  18. <div class="content-item">
  19. <span>分装编号</span>
  20. <span class="ml-20">单位</span>
  21. <div class="unit-select">
  22. <HandleFormItem :fieldKey="formData.mybh + '_dw'" :isFieldsRecord="false" :item="unitItem" type="select" :error="formErrors.dw"
  23. @blur="(e) => onCommonBlur(e, 'dw')" v-model="formData.dw" />
  24. </div>
  25. <span class="ml-20">每份包装量</span>
  26. <div class="unit-select">
  27. <HandleFormItem :fieldKey="formData.mybh + '_mfbzl'" type="inputNumber" :error="formErrors.mfbzl" :isFieldsRecord="false"
  28. :item="inputNumberItem" v-model="formData.mfbzl" />
  29. </div>
  30. <el-button type="primary" plain @click="onAverage">平均分配</el-button>
  31. <el-button type="primary" plain @click="onReset">重置</el-button>
  32. </div>
  33. <div class="header-container header2">
  34. <div v-for="(item, index) in fzList" class="list-item" :key="index">
  35. <div class="list-label">{{ formData.mybh }}-set{{ item.subCode }}</div>
  36. <HandleFormItem :fieldKey="formData.mybh + '_num_' + item.subCode" :isFieldsRecord="false" :item="inputNumberItem" :error="fzListErrors[index]"
  37. type="inputNumber" @blur="onBlurFzNum(index)" v-model="item.num" />
  38. <el-button type="primary" class="ml-5" plain @click="onPrint(item)">打印</el-button>
  39. </div>
  40. </div>
  41. </div>
  42. </div>
  43. <template slot="footer" class="dialog-footer">
  44. <el-button @click="close">{{ $t('form.cancel') }}</el-button>
  45. <el-button type="primary" @click="onSubmit">{{ $t('form.saveConfirm') }}</el-button>
  46. </template>
  47. </el-dialog>
  48. </template>
  49. <script>
  50. import HandleFormItem from '@/components/Template/HandleFormItem.vue';
  51. import { compareVolume } from '@/utils/volumeTools.js';
  52. import { EventBus } from '@/utils/eventBus';
  53. import { getLatestSn } from '@/api/template';
  54. import { isValueEmpty } from "@/utils/index";
  55. import moment from 'moment';
  56. import { getuuid } from "@/utils/index.js";
  57. export default {
  58. inject: ['updateZdxgjl',"getZdxgjl"],
  59. dicts: [
  60. 'business_tjdw',
  61. ],
  62. components: {
  63. HandleFormItem,
  64. },
  65. data() {
  66. return {
  67. visible: false,
  68. inputItem: {
  69. type: "input",
  70. fillType: "actFill",
  71. disabled: true,
  72. },
  73. integerInputNumberItem: {
  74. type: "inputNumber",
  75. fillType: "actFill",
  76. precision: 0,
  77. label: "分装数量",
  78. maxlength: 3
  79. },
  80. inputNumberItem: {
  81. type: "inputNumber",
  82. fillType: "actFill",
  83. },
  84. formData: {
  85. mybh: "",//母液编号
  86. fzsl: "",//分装数量
  87. dw: "",//单位
  88. mfbzl: "",//每份包装量
  89. },
  90. fzList: [],//分装列表
  91. // 错误状态字段
  92. formErrors: {
  93. mybh: false,
  94. fzsl: false,
  95. dw: false,
  96. },
  97. fzListErrors: [], // 分装列表错误状态
  98. uuid: "",//事件id
  99. originalData: {},//原始数据
  100. uuid:getuuid(),//事件id
  101. }
  102. },
  103. computed: {
  104. unitItem() {
  105. return {
  106. type: "select",
  107. fillType: "actFill",
  108. options: this.dict.type.business_tjdw
  109. }
  110. }
  111. },
  112. mounted() {
  113. EventBus.$on('onEditSignCallback', this.handleEditSignCallback);
  114. EventBus.$on('onFormEditSignCancel', this.handleEditSignCancel);
  115. },
  116. unmounted() {
  117. EventBus.$off('onEditSignCallback', this.handleEditSignCallback);
  118. EventBus.$off('onFormEditSignCancel', this.handleEditSignCancel);
  119. },
  120. methods: {
  121. handleEditSignCancel(data) {
  122. },
  123. handleEditSignCallback(data) {
  124. if (data.uuid === this.uuid) {
  125. this.updateRecords();
  126. }
  127. },
  128. close() {
  129. this.visible = false;
  130. this.fzList = [];
  131. this.formData = {};
  132. this.resetErrors();
  133. },
  134. show(data) {
  135. const cloneData = JSON.parse(JSON.stringify(data));
  136. console.log(cloneData, "cloneData")
  137. if (data && data.uuid) {//为了标识eventBus的事件id
  138. this.uuid = data.uuid
  139. }
  140. this.originalData = {
  141. fzList: [],
  142. mybh: cloneData.mybh,
  143. fzsl: cloneData.fzsl,
  144. dw: cloneData.dw,
  145. mfbzl: cloneData.mfbzl,
  146. }
  147. if (data.fzList) {
  148. this.fzList = JSON.parse(JSON.stringify(cloneData.fzList));
  149. this.originalData.fzList = JSON.parse(JSON.stringify(cloneData.fzList));
  150. // 初始化分装列表错误状态
  151. this.fzListErrors = new Array(this.fzList.length).fill(false);
  152. delete cloneData.fzList;
  153. }
  154. this.formData = cloneData;
  155. // 重置错误状态
  156. this.resetErrors();
  157. this.visible = true;
  158. },
  159. onSubmit() {
  160. // 验证表单数据
  161. if (!this.validateFormData()) {
  162. this.$message.error('表单内容未填完,请填写后再提交')
  163. return;
  164. } else {
  165. const errMsg = "分装后小份容量之和大于母液容量,是否确认分装?"
  166. const { maxVolume, maxVolumeUnit, dw } = this.formData;
  167. const totalVolume = this.fzList.reduce((acc, cur) => acc + Number(cur.num), 0);
  168. const compareResult = compareVolume(totalVolume, dw, maxVolume, maxVolumeUnit);
  169. console.log(compareResult, totalVolume, dw, maxVolume, maxVolumeUnit, "比较结果");
  170. if (compareResult > 0 || !maxVolume) {//没有填写实际溶液体积的也需要提示错误信息
  171. this.$modal.confirm(errMsg, '提示', {
  172. confirmButtonText: this.$t('form.saveConfirm'),
  173. cancelButtonText: this.$t('form.cancel'),
  174. type: 'warning'
  175. }).then(() => {
  176. this.submitEmit();
  177. }).catch(() => {
  178. // 取消操作,不执行任何操作
  179. });
  180. return;
  181. }
  182. this.submitEmit();
  183. }
  184. },
  185. submitEmit() {
  186. const { originalData } = this;
  187. const { mybh, fzsl, dw, mfbzl } = this.formData;
  188. const nowData = { fzList: this.fzList, mybh, fzsl, dw, mfbzl };
  189. if (!originalData.fzList.length) {
  190. this.updateRecords();
  191. } else if (JSON.stringify(nowData) !== JSON.stringify(originalData)) {
  192. EventBus.$emit('showEditSignDialog', { uuid: this.uuid });
  193. return;
  194. } else {
  195. this.updateRecords();
  196. }
  197. },
  198. handleSubmit() {
  199. EventBus.$emit('dialogSubPackageSubmit', { ...this.formData, fzList: this.fzList, uuid: this.uuid });
  200. setTimeout(() => {
  201. this.close();
  202. }, 500);
  203. },
  204. getCommonInfo(type){
  205. const { nickName, name } = this.$store.getters;
  206. const o ={
  207. mybh:"母液编号",
  208. fzsl:"分装数量",
  209. dw:"单位",
  210. mfbzl:"每份包装量",
  211. num:"分装编号"
  212. }
  213. return{
  214. userNameCn: nickName,
  215. userNameEn: name,
  216. time: moment().format("YYYY-MM-DD HH:mm:ss"),
  217. fieldCn: o[type],
  218. fieldEn: o[type],
  219. }
  220. },
  221. updateRecords() {
  222. const { originalData } = this;
  223. const records = [];
  224. const { mybh, fzsl, dw, mfbzl } = this.formData;
  225. const nowData = { fzList: this.fzList, mybh, fzsl, dw, mfbzl };
  226. // 定义要比较的字段
  227. const fieldsToCompare = ['mybh', 'fzsl', 'dw', 'mfbzl'];
  228. // 比较基础字段
  229. fieldsToCompare.forEach(field => {
  230. if (originalData[field] !== nowData[field]) {
  231. const record = {
  232. key: mybh + '_' + field,
  233. oldValue: originalData[field],
  234. value: nowData[field],
  235. title: originalData[field] ? "修改" : "提交",
  236. ...this.getCommonInfo(field),
  237. }
  238. records.push(record);
  239. this.updateZdxgjl(record);
  240. }
  241. });
  242. // 比较分装列表
  243. this.compareFzList(originalData.fzList, nowData.fzList, records);
  244. console.log(records, "records")
  245. this.handleSubmit();
  246. if (records.length == 0) {
  247. return;
  248. }
  249. const params = {
  250. type: "fieldChanged",
  251. newRecord: records,
  252. resourceList: this.getZdxgjl(),
  253. source: "customTable",
  254. }
  255. EventBus.$emit('onModifyRecord', params);
  256. },
  257. // 比较分装列表的辅助方法
  258. compareFzList(originalFzList, nowFzList, records) {
  259. console.log(originalFzList, nowFzList, records, "compareFzList")
  260. const { mybh } = this.formData;
  261. if(!originalFzList.length){
  262. nowFzList.forEach(item => {
  263. const record = {
  264. key: mybh + '_num_' + item.subCode,
  265. oldValue: '',
  266. value: item.num,
  267. title: item.num ? "修改" : "提交",
  268. ...this.getCommonInfo('num'),
  269. };
  270. records.push(record);
  271. this.updateZdxgjl(record);
  272. })
  273. return;
  274. }
  275. if (originalFzList.length === nowFzList.length) {
  276. for (let i = 0; i < originalFzList.length; i++) {
  277. if (originalFzList[i].num !== nowFzList[i].num) {
  278. const record = {
  279. key: mybh + '_num_' + originalFzList[i].subCode,
  280. oldValue: originalFzList[i].num,
  281. value: nowFzList[i].num,
  282. title: originalFzList[i].num ? "修改" : "提交",
  283. ...this.getCommonInfo('num'),
  284. };
  285. records.push(record);
  286. this.updateZdxgjl(record);
  287. }
  288. }
  289. }else if(originalFzList.length>nowFzList.length){
  290. for (let i = 0; i < nowFzList.length; i++) {
  291. if (originalFzList[i].num !== nowFzList[i].num) {
  292. const record = {
  293. key: mybh + '_num_' + nowFzList[i].subCode,
  294. oldValue: originalFzList[i].num,
  295. value: nowFzList[i].num,
  296. title: originalFzList[i].num ? "修改" : "提交",
  297. ...this.getCommonInfo('num'),
  298. };
  299. records.push(record);
  300. this.updateZdxgjl(record);
  301. }
  302. }
  303. }else{
  304. for (let i = 0; i < originalFzList.length; i++) {
  305. if (originalFzList[i].num !== nowFzList[i].num) {
  306. const record = {
  307. key: mybh + '_num_' + nowFzList[i].subCode,
  308. oldValue: originalFzList[i].num,
  309. value: nowFzList[i].num,
  310. title: originalFzList[i].num ? "修改" : "提交",
  311. ...this.getCommonInfo('num'),
  312. };
  313. records.push(record);
  314. this.updateZdxgjl(record);
  315. }
  316. }
  317. }
  318. },
  319. validateFormData() {
  320. let isValid = true;
  321. const { mybh, fzsl, dw, mfbzl } = this.formData;
  322. // 验证母液编号
  323. if (isValueEmpty(mybh)) {
  324. this.formErrors.mybh = true;
  325. isValid = false;
  326. }
  327. // 验证分装数量
  328. if (isValueEmpty(fzsl)) {
  329. this.formErrors.fzsl = true;
  330. isValid = false;
  331. }
  332. // 验证单位
  333. if (isValueEmpty(dw)) {
  334. this.formErrors.dw = true;
  335. isValid = false;
  336. }
  337. // 验证单位
  338. if (isValueEmpty(mfbzl)) {
  339. this.formErrors.mfbzl = true;
  340. isValid = false;
  341. }
  342. // 验证分装列表中的数值
  343. if (this.fzList && this.fzList.length > 0) {
  344. for (let i = 0; i < this.fzList.length; i++) {
  345. if (isValueEmpty(this.fzList[i].num)) {
  346. // 确保fzListErrors数组有足够的元素
  347. if (this.fzListErrors.length <= i) {
  348. this.$set(this.fzListErrors, i, true);
  349. } else {
  350. this.fzListErrors[i] = true;
  351. }
  352. isValid = false;
  353. }
  354. }
  355. }
  356. return isValid;
  357. },
  358. resetErrors() {
  359. // 重置表单错误状态
  360. Object.keys(this.formErrors).forEach(key => {
  361. this.formErrors[key] = false;
  362. });
  363. // 重置分装列表错误状态
  364. this.fzListErrors.forEach((_, index) => {
  365. this.$set(this.fzListErrors, index, false);
  366. });
  367. },
  368. // 分装数量失去焦点时,根据数量生成分装列表
  369. async onBlurFzsl(e) {
  370. console.log(e, "失去焦点时的数量")
  371. // 清除当前字段的错误状态
  372. if (e) {
  373. this.formErrors.fzsl = false;
  374. }
  375. // 清空现有列表
  376. this.fzList = [];
  377. this.fzListErrors = [];
  378. const result = await getLatestSn({
  379. pre: this.formData.mybh,
  380. count: e,
  381. type: 2,
  382. })
  383. if (result.code === 200) {
  384. const codes = result.data;
  385. // 根据输入的数量生成新列表
  386. for (let i = 0; i < e; i++) {
  387. this.fzList.push({
  388. num: "",
  389. subCode: codes[i],
  390. preCode: `-set${codes[i]}`
  391. });
  392. // 同步初始化错误状态数组
  393. this.fzListErrors.push(false);
  394. }
  395. }
  396. },
  397. onAverage() {
  398. const { mfbzl } = this.formData;
  399. this.fzList.forEach((item, index) => {
  400. item.num = mfbzl;
  401. // 同时更新错误状态
  402. if (this.fzListErrors[index] !== undefined) {
  403. this.$set(this.fzListErrors, index, false);
  404. }
  405. })
  406. // 清除相关字段的错误状态
  407. this.formErrors.mfbzl = false;
  408. },
  409. onReset() {
  410. this.fzList.forEach((item, index) => {
  411. item.num = "";
  412. // 同时更新错误状态
  413. if (this.fzListErrors[index] !== undefined) {
  414. this.$set(this.fzListErrors, index, false);
  415. }
  416. })
  417. // 清除相关字段的错误状态
  418. this.formErrors.mfbzl = false;
  419. },
  420. onPrint(item) {
  421. EventBus.$emit('subPackageDialogPrintTag', { ...this.formData, printCode: `${this.formData.mybh}-set${item.subCode}`, uuid: this.uuid });
  422. },
  423. onCommonBlur(e, field) {
  424. if (this.formData[field]) {
  425. this.formErrors[field] = false;
  426. }
  427. },
  428. onBlurFzNum(index) {
  429. if (this.fzList[index] && this.fzList[index].num) {
  430. if (this.fzListErrors[index] !== undefined) {
  431. this.$set(this.fzListErrors, index, false);
  432. }
  433. }
  434. },
  435. }
  436. }
  437. </script>
  438. <style lang="scss" scoped>
  439. .dialog-content {
  440. padding: 20px;
  441. }
  442. .unit-select {
  443. width: 100px;
  444. }
  445. .content-item {
  446. display: flex;
  447. align-items: center;
  448. }
  449. .header-container {
  450. display: grid;
  451. grid-template-columns: 1fr 1fr 1fr;
  452. grid-gap: 20px;
  453. margin-top: 20px;
  454. }
  455. .header2 {
  456. grid-template-columns: 1fr 1fr;
  457. }
  458. .header-item {
  459. box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
  460. background: #fff;
  461. border-radius: 4px;
  462. padding: 20px;
  463. }
  464. .header-title {
  465. margin-bottom: 10px;
  466. }
  467. .content-container {
  468. margin-top: 20px;
  469. padding: 20px;
  470. box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
  471. max-height: 50vh;
  472. overflow: auto;
  473. }
  474. .ml-20 {
  475. margin-left: 20px;
  476. }
  477. .list-item {
  478. display: flex;
  479. align-items: center;
  480. // margin-top: 20px;
  481. }
  482. .list-label {
  483. margin-right: 5px;
  484. // width: 200px;
  485. }
  486. .ml-5{
  487. margin-left: 5px;
  488. }
  489. </style>