华西海圻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.

450 lines
15 KiB

  1. <!-- 质量分装 -->
  2. <template>
  3. <div class="zl-container">
  4. <div class="dialog-content">
  5. <div class="header-container">
  6. <div class="header-item" v-for="item in subConfig" :key="item.key">
  7. <div class="header-title">{{ item.label }}</div>
  8. <HandleFormItem fieldItemLabel = "质量分装" :fieldKey = item.fieldKey
  9. :item="item" :error="formErrors[item.key]"
  10. :type="item.type"
  11. @blur = "(e)=>onCommonBlur(e,item.key)"
  12. v-model="formData[item.key]" />
  13. </div>
  14. <!-- <div class="header-item">
  15. <div class="header-title">分装数量</div>
  16. <HandleFormItem fieldKey = "clfz_fzsl" @blur="onBlurFzsl" :item="integerInputNumberItem"
  17. type = "inputNumber"
  18. :error="formErrors.fzsl" v-model="formData.fzsl" />
  19. </div>
  20. <div class="header-item">
  21. <div class="header-title">单位</div>
  22. <div class="unit-select">
  23. <HandleFormItem fieldKey = "clfz_dw" :item="unitItem" type="select" :error="formErrors.dw"
  24. @blur="(e) => onCommonBlur(e, 'dw')" v-model="formData.dw" />
  25. </div>
  26. </div> -->
  27. </div>
  28. <div class="content-container">
  29. <div class="header-container">
  30. <div v-for="(item, index) in fzList" class="list-item" :key="index">
  31. <div class="list-label">{{ formData.mybh }}-set{{ item.subCode }}</div>
  32. <HandleFormItem fieldItemLabel = "质量分装" :fieldKey = "'clfz_set'+index+'_prenum'" :item="preInputNumberItem"
  33. :error="hasError(index, 'prenum')"
  34. :disabled="true"
  35. type="inputNumber" @blur="onBlurFzNum(index,'prenum')" v-model="item.prenum" />
  36. <HandleFormItem fieldItemLabel = "质量分装" :fieldKey = "'clfz_set'+index+'_actnum'" class="ml-5" :item="inputNumberItem"
  37. :error="hasError(index, 'actnum')"
  38. type="inputNumber" @blur="onBlurFzNum(index,'actnum')" v-model="item.actnum" />
  39. <HandleFormItem
  40. class="ml-5"
  41. type="button"
  42. :item="getButtonItem()"
  43. @clickButton="(e)=>onGetValue(item)" />
  44. </div>
  45. </div>
  46. </div>
  47. </div>
  48. </div>
  49. </template>
  50. <script>
  51. import HandleFormItem from '@/components/Template/HandleFormItem.vue';
  52. import { EventBus } from '@/utils/eventBus';
  53. import { getLatestSn } from '@/api/template';
  54. import { isValueEmpty } from '@/utils/index.js';
  55. export default {
  56. inject: ['templateFillType'],
  57. dicts: [
  58. 'business_tjdw',
  59. ],
  60. components: {
  61. HandleFormItem,
  62. },
  63. props: {
  64. subData: {
  65. type: Object,
  66. default: () => ({})
  67. },
  68. },
  69. data() {
  70. return {
  71. inputItem: {
  72. type: "input",
  73. fillType: "actFill",
  74. disabled: true,
  75. },
  76. integerInputNumberItem: {
  77. type: "inputNumber",
  78. fillType: "actFill",
  79. precision: 0,
  80. maxlength: 3
  81. },
  82. inputNumberItem: {
  83. type: "inputNumber",
  84. fillType: "actFill",
  85. label:"实际称量"
  86. },
  87. preInputNumberItem: {
  88. type: "inputNumber",
  89. fillType: "preFill",
  90. label:"预计称量"
  91. },
  92. formData: {
  93. mybh: "",//母液编号
  94. fzsl: "",//分装数量
  95. dw: "",//单位
  96. },
  97. fzList: [],//分装列表
  98. // 错误状态字段
  99. formErrors: {
  100. fzsl: false,
  101. dw: false,
  102. },
  103. fzListErrors: [], // 分装列表错误状态
  104. uuid:"",//事件id
  105. }
  106. },
  107. watch: {
  108. subData:{
  109. handler(newVal) {
  110. if(newVal.formData){
  111. this.formData = newVal.formData;
  112. }
  113. if(newVal.fzList){
  114. this.fzList = newVal.fzList;
  115. }
  116. },
  117. deep: true,
  118. immediate: true,
  119. },
  120. // 监听formData的变化
  121. formData: {
  122. handler(newVal) {
  123. this.onDataChange();
  124. },
  125. deep: true
  126. },
  127. // 监听fzList的变化
  128. fzList: {
  129. handler(newVal) {
  130. this.onDataChange();
  131. },
  132. deep: true
  133. }
  134. },
  135. computed: {
  136. subConfig(){
  137. return[
  138. {
  139. fieldKey:"clfz_mybh",
  140. key:"mybh",
  141. label:"母编号",
  142. type:"input",
  143. disabled: true,
  144. fillType: "actFill",
  145. },
  146. {
  147. fieldKey:"clfz_fzsl",
  148. key:"fzsl",
  149. label:"分装数量",
  150. type:"inputNumber",
  151. fillType: "preFill",
  152. },
  153. {
  154. fieldKey:"clfz_dw",
  155. key:"dw",
  156. label:"单位",
  157. type:"select",
  158. options: this.dict.type.business_tjdw,
  159. fillType: "preFill",
  160. },
  161. ]
  162. },
  163. },
  164. methods: {
  165. updateFormData(data){
  166. this.formData = {...this.formData,...data};
  167. },
  168. // 获取按钮项
  169. getButtonItem() {
  170. return {
  171. fillType: "actFill",
  172. buttonName:"获取值",
  173. }
  174. },
  175. close() {
  176. this.visible = false;
  177. this.fzList = [];
  178. this.formData = {};
  179. this.resetErrors();
  180. },
  181. validateFormData() {
  182. let isValid = true;
  183. // 定义需要验证的基础字段配制
  184. const baseFieldConfigs = this.subConfig;
  185. // 验证基础字段
  186. baseFieldConfigs.forEach(config => {
  187. if (config.fillType === this.templateFillType) {
  188. if (isValueEmpty(this.formData[config.key]) && !config.disabled) {
  189. this.formErrors[config.key] = true;
  190. isValid = false;
  191. }
  192. }
  193. });
  194. // 验证分装列表中的数值 - 根据字段的fillType和当前templateFillType比较
  195. if (this.fzList && this.fzList.length > 0) {
  196. for (let i = 0; i < this.fzList.length; i++) {
  197. // 验证预填分装数量
  198. if (this.preInputNumberItem.fillType === this.templateFillType) {
  199. if (isValueEmpty(this.fzList[i].prenum)) {
  200. this.fzListErrors.push({
  201. rowIndex: i,
  202. field: "prenum",
  203. error: "请输入预填分装数量",
  204. })
  205. isValid = false;
  206. }
  207. }
  208. // 验证实际分装数量
  209. if (this.inputNumberItem.fillType === this.templateFillType) {
  210. if (isValueEmpty(this.fzList[i].actnum)) {
  211. this.fzListErrors.push({
  212. rowIndex: i,
  213. field: "actnum",
  214. error: "请输入实际分装数量",
  215. })
  216. isValid = false;
  217. }
  218. }
  219. }
  220. }
  221. return {valid: isValid,error:"质量分装数据没填完"};
  222. },
  223. resetErrors() {
  224. // 重置表单错误状态
  225. Object.keys(this.formErrors).forEach(key => {
  226. this.formErrors[key] = false;
  227. });
  228. // 重置分装列表错误状态
  229. this.fzListErrors.forEach((_, index) => {
  230. this.fzListErrors = []
  231. });
  232. },
  233. // 分装数量失去焦点时,根据数量生成分装列表
  234. async onBlurFzsl(e) {
  235. // 清除当前字段的错误状态
  236. if (e) {
  237. this.formErrors.fzsl = false;
  238. }
  239. // 清空现有列表
  240. this.fzList = [];
  241. this.fzListErrors = [];
  242. const result = await getLatestSn({
  243. pre: this.formData.mybh,
  244. count: e,
  245. type: 2,
  246. })
  247. if(result.code === 200){
  248. const codes = result.data;
  249. // 根据输入的数量生成新列表
  250. for (let i = 0; i < e; i++) {
  251. this.fzList.push({
  252. prenum: "",
  253. actnum: "",
  254. subCode: codes[i],
  255. });
  256. }
  257. const params = {
  258. type: "fieldChanged",
  259. newRecord: null,
  260. resourceList: null,
  261. }
  262. EventBus.$emit("onModifyRecord", params);
  263. }
  264. },
  265. onGetValue(item) {
  266. item.actnum = 123;
  267. console.log(item,"获取值")
  268. this.fzList = [...this.fzList]
  269. },
  270. onCommonBlur(e,field) {
  271. if (this.formData[field]) {
  272. this.formErrors[field] = false;
  273. }
  274. if(field === 'fzsl'){
  275. this.onBlurFzsl(e);
  276. }
  277. },
  278. onBlurFzNum(index, field) {
  279. if (this.fzList[index]) {
  280. // 确保fzListErrors数组有足够的元素
  281. if (this.fzListErrors.length <= index) {
  282. this.$set(this.fzListErrors, index, false);
  283. }
  284. if (this.fzList[index][field]) {
  285. // 有值的话就清空对应的错误信息
  286. this.$set(this.fzListErrors, index, false);
  287. } else {
  288. // 没有值的话就边框标红
  289. this.$set(this.fzListErrors, index, true);
  290. }
  291. }
  292. },
  293. verifyFzListError(index, field) {
  294. // 如果index和field都为空,就全匹配
  295. if (index === undefined && field === undefined) {
  296. if (this.fzList && this.fzList.length > 0) {
  297. // 清空现有错误信息
  298. this.fzListErrors = [];
  299. // 遍历fzList,没有值的就放到fzListErrors里面
  300. for (let i = 0; i < this.fzList.length; i++) {
  301. const item = this.fzList[i];
  302. if (isValueEmpty(item.prenum)) {
  303. this.fzListErrors.push({
  304. rowIndex: i,
  305. field: "prenum",
  306. error: "请输入预填分装数量"
  307. });
  308. }
  309. if (isValueEmpty(item.actnum)) {
  310. this.fzListErrors.push({
  311. rowIndex: i,
  312. field: "actnum",
  313. error: "请输入实际分装数量"
  314. });
  315. }
  316. }
  317. }
  318. } else if (index !== undefined) {
  319. // 如果index不为空,检查指定索引的项
  320. if (this.fzList[index]) {
  321. const item = this.fzList[index];
  322. if (field === undefined) {
  323. // 如果field为空,检查prenum和actnum
  324. // 先移除该索引的所有错误信息
  325. this.fzListErrors = this.fzListErrors.filter(err => err.rowIndex !== index);
  326. // 没有值的就放到fzListErrors里面
  327. if (isValueEmpty(item.prenum)) {
  328. this.fzListErrors.push({
  329. rowIndex: index,
  330. field: "prenum",
  331. error: "请输入预填分装数量"
  332. });
  333. }
  334. if (isValueEmpty(item.actnum)) {
  335. this.fzListErrors.push({
  336. rowIndex: index,
  337. field: "actnum",
  338. error: "请输入实际分装数量"
  339. });
  340. }
  341. } else {
  342. // 如果field不为空,检查指定字段
  343. // 先移除该索引和字段的错误信息
  344. this.fzListErrors = this.fzListErrors.filter(err => !(err.rowIndex === index && err.field === field));
  345. // 没有值的就放到fzListErrors里面
  346. if (isValueEmpty(item[field])) {
  347. this.fzListErrors.push({
  348. rowIndex: index,
  349. field: field,
  350. error: field === "prenum" ? "请输入预填分装数量" : "请输入实际分装数量"
  351. });
  352. }
  353. }
  354. }
  355. }
  356. },
  357. hasError(index, field) {
  358. const o = this.fzListErrors.find((item)=>{
  359. return item.rowIndex === index && item.field === field;
  360. })
  361. return o !== undefined;
  362. },
  363. // 数据变化处理方法
  364. onDataChange() {
  365. // 触发自定义事件,将数据变化传递给父组件
  366. this.$emit('update', {
  367. formData: this.formData,
  368. fzList: this.fzList
  369. });
  370. },
  371. }
  372. }
  373. </script>
  374. <style lang="scss" scoped>
  375. .zl-container{
  376. // width: 1100px;
  377. }
  378. .dialog-content {
  379. // padding: 20px;
  380. }
  381. .ml-5{
  382. margin-left: 5px;
  383. }
  384. .unit-select {
  385. width: 100px;
  386. }
  387. .content-item {
  388. display: flex;
  389. align-items: center;
  390. }
  391. .header-container {
  392. display: grid;
  393. grid-template-columns: 1fr 1fr 1fr;
  394. grid-gap: 20px;
  395. margin-top: 10px;
  396. }
  397. .header-item {
  398. // box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
  399. background: #fff;
  400. border-radius: 4px;
  401. display: flex;
  402. align-items: center;
  403. // padding: 20px;
  404. }
  405. .header-title {
  406. // margin-bottom: 10px;
  407. margin-right: 5px;
  408. }
  409. .content-container {
  410. margin-top: 10px;
  411. // padding: 20px;
  412. // box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
  413. // max-height: 50vh;
  414. overflow: auto;
  415. }
  416. .ml-20 {
  417. margin-left: 20px;
  418. }
  419. .list-item {
  420. display: flex;
  421. align-items: center;
  422. // margin-top: 20px;
  423. }
  424. .list-label {
  425. margin-right: 5px;
  426. // width: 200px;
  427. }
  428. </style>