BaseForm.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614
  1. <template>
  2. <a-modal
  3. :title="title"
  4. :width="1400"
  5. :visible="visible"
  6. :confirmLoading="confirmLoading"
  7. @cancel="handleCancel"
  8. >
  9. <a-card >
  10. <a-form :form="form">
  11. <row-list :col="1" v-show="false">
  12. <row-item>
  13. <a-form-item>
  14. <a-input v-decorator="['id']" type="hidden"/>
  15. <a-input v-decorator="['sbId']" type="hidden"/>
  16. </a-form-item>
  17. </row-item>
  18. </row-list>
  19. <row-list :col="2">
  20. <row-item >
  21. <a-form-item
  22. label="计划类型"
  23. :labelCol="BaseTool.Constant.labelCol"
  24. :wrapperCol="BaseTool.Constant.wrapperCol"
  25. >
  26. <a-select v-decorator="['type', { rules: [{required: true, message: '采购计划类型不能为空'}]}]" placeholder="请选择">
  27. <a-select-option
  28. v-for="(label,value) in typeMap"
  29. :key="value"
  30. :label="label"
  31. :value="parseInt(value)">{{ label }}
  32. </a-select-option>
  33. </a-select>
  34. </a-form-item>
  35. </row-item>
  36. <row-item >
  37. <a-form-item
  38. label="请购原因"
  39. :labelCol="BaseTool.Constant.labelCol"
  40. :wrapperCol="BaseTool.Constant.wrapperCol"
  41. >
  42. <a-input
  43. v-decorator="['remark']"/>
  44. </a-form-item>
  45. </row-item>
  46. <row-item >
  47. <a-form-item
  48. label="采购类型"
  49. :labelCol="BaseTool.Constant.labelCol"
  50. :wrapperCol="BaseTool.Constant.wrapperCol"
  51. >
  52. <a-select v-decorator="['cptcode', { rules: [{required: true, message: '采购类型不能为空'}]}]" placeholder="请选择">
  53. <a-select-option
  54. v-for="(label,value) in cptcodeMap"
  55. :key="value"
  56. :label="label"
  57. :value="value">{{ label }}
  58. </a-select-option>
  59. </a-select>
  60. </a-form-item>
  61. </row-item>
  62. <row-item >
  63. <a-form-item
  64. label="业务类型"
  65. :labelCol="BaseTool.Constant.labelCol"
  66. :wrapperCol="BaseTool.Constant.wrapperCol"
  67. >
  68. <a-select v-decorator="['cbustype', {rules: [{required: true, message: '业务类型不能为空'}]}]" placeholder="请选择">
  69. <a-select-option
  70. v-for="(label,value) in cbustypeMap"
  71. :key="value"
  72. :label="label"
  73. :value="value">{{ label }}
  74. </a-select-option>
  75. </a-select>
  76. </a-form-item>
  77. </row-item>
  78. <row-item >
  79. <a-form-item
  80. label="采购厂区"
  81. :labelCol="BaseTool.Constant.labelCol"
  82. :wrapperCol="BaseTool.Constant.wrapperCol"
  83. >
  84. <a-select :disabled="title==='编辑'" v-decorator="['oldOrNew', {rules: [{required: true, message: '采购厂区不能为空'}]}]" @change="setTree">
  85. <a-select-option
  86. v-for="(label,value) in flagMap"
  87. :key="value"
  88. :label="label"
  89. :value="parseInt(value)">{{ label }}
  90. </a-select-option>
  91. </a-select>
  92. </a-form-item>
  93. </row-item>
  94. <row-item >
  95. <a-form-item
  96. label="申请部门"
  97. :labelCol="BaseTool.Constant.labelCol"
  98. :wrapperCol="BaseTool.Constant.wrapperCol"
  99. >
  100. <a-select :disabled="!oldOrNew" v-decorator="['cdepcode', {rules: [{required: true, message: '申请部门不能为空'}]}]" placeholder="请选择">
  101. <a-select-option
  102. v-for="(label,value) in oldOrNew===2?deptMap:deptNewMap"
  103. :key="value"
  104. :label="label"
  105. :value="value">{{ label }}
  106. </a-select-option>
  107. </a-select>
  108. </a-form-item>
  109. </row-item>
  110. <!-- <row-item >-->
  111. <!-- <a-form-item-->
  112. <!-- label="需求跟踪方式"-->
  113. <!-- :labelCol="BaseTool.Constant.labelCol"-->
  114. <!-- :wrapperCol="BaseTool.Constant.wrapperCol"-->
  115. <!-- >-->
  116. <!-- <a-select v-decorator="['cestIrequireTrackStyle', {rules: [{required: true, message: '需求跟踪方式不能为空'}]}]" placeholder="请选择">-->
  117. <!-- <a-select-option-->
  118. <!-- v-for="(label,value) in soMap"-->
  119. <!-- :key="value"-->
  120. <!-- :label="label"-->
  121. <!-- :value="parseInt(value)">{{ label }}-->
  122. <!-- </a-select-option>-->
  123. <!-- </a-select>-->
  124. <!-- </a-form-item>-->
  125. <!-- </row-item>-->
  126. <row-item >
  127. <a-form-item
  128. label="计划到货日期"
  129. :labelCol="BaseTool.Constant.labelCol"
  130. :wrapperCol="BaseTool.Constant.wrapperCol"
  131. >
  132. <a-date-picker
  133. style="width: 100%"
  134. :disabled-date="disabledDate"
  135. @change="dateChange"
  136. :format="BaseTool.Date.PICKER_NORM_DATE_PATTERN"
  137. v-decorator="['planGetDate', {rules: [{required: true, message: '计划到货日期不能为空'}]}]" />
  138. </a-form-item>
  139. </row-item>
  140. <row-item >
  141. <a-form-item
  142. label="需求日期"
  143. :labelCol="BaseTool.Constant.labelCol"
  144. :wrapperCol="BaseTool.Constant.wrapperCol"
  145. >
  146. <a-date-picker
  147. :disabled="!date"
  148. style="width: 100%"
  149. :disabled-date="disabledDate2"
  150. :format="BaseTool.Date.PICKER_NORM_DATE_PATTERN"
  151. v-decorator="['needDate', {rules: [{required: true, message: '需求日期不能为空'}]}]" />
  152. </a-form-item>
  153. </row-item>
  154. <row-item >
  155. <a-form-item
  156. label="设备位号"
  157. :labelCol="BaseTool.Constant.labelCol"
  158. :wrapperCol="BaseTool.Constant.wrapperCol"
  159. >
  160. <a-input
  161. style="width: 70%"
  162. disabled
  163. v-decorator="['positionNo']" />
  164. <a-button :disabled="title==='编辑'" style="width: 30%" type="primary" @click="handleSbSelect">选择</a-button>
  165. </a-form-item>
  166. </row-item>
  167. <!-- <row-item >
  168. <a-form-item
  169. label="关联项目"
  170. :labelCol="BaseTool.Constant.labelCol"
  171. :wrapperCol="BaseTool.Constant.wrapperCol"
  172. >
  173. <a-tree-select
  174. style="width: 100%"
  175. :treeData="treeData"
  176. :showSearch="true"
  177. tree-node-filter-prop="title"
  178. :dropdownStyle="{ maxHeight: '400px', overflow: 'auto' }"
  179. v-decorator="['projectId']"
  180. placeholder="请选择"
  181. >
  182. </a-tree-select>
  183. </a-form-item>
  184. </row-item> -->
  185. <!-- <row-item >
  186. <a-form-item
  187. label="物资描述"
  188. :labelCol="BaseTool.Constant.labelCol"
  189. :wrapperCol="BaseTool.Constant.wrapperCol"
  190. >
  191. <a-textarea
  192. v-decorator="['cdefine11', { rules: [{required: true, message: '物资描述不能为空'}]}]"/>
  193. </a-form-item>
  194. </row-item> -->
  195. <!-- <row-item >
  196. <a-form-item
  197. label="物料简述"
  198. :labelCol="BaseTool.Constant.labelCol"
  199. :wrapperCol="BaseTool.Constant.wrapperCol"
  200. >
  201. <a-textarea
  202. v-decorator="['cdefine12', { rules: [{required: true, message: '物料简述不能为空'}]}]"/>
  203. </a-form-item>
  204. </row-item> -->
  205. </row-list>
  206. </a-form>
  207. </a-card>
  208. <a-card>
  209. <div class="table-operator" style="margin-bottom: 8px;">
  210. <a-button size="small" :disabled="!oldOrNew" type="primary" @click="handleSpareStoreSelect">
  211. <a-icon type="plus"/>
  212. 物料库添加
  213. </a-button>
  214. <!-- <a-button size="small" :disabled="!(oldOrNew&&sbId)" style="margin-left:20px;" type="primary" @click="handleBomSpareStoreSelect">
  215. <a-icon type="plus"/>
  216. BOM添加
  217. </a-button> -->
  218. </div>
  219. <a-table
  220. bordered
  221. :data-source="data"
  222. :columns="columns"
  223. tableLayout="auto"
  224. rowKey="id"
  225. :scroll="{ x: 1500 }"
  226. >
  227. <template slot="iexchrate" slot-scope="text, record">
  228. <a-input-number v-model="record.iexchrate" :step="0.01" />
  229. </template>
  230. <template slot="funitprice" slot-scope="text, record" >
  231. <a-input-number v-model="record.funitprice" :step="0.0001" @blur="computeTax(record,1)" />
  232. </template>
  233. <template slot="fmoney" slot-scope="text, record">
  234. <a-input-number v-model="record.fmoney" :step="0.01" @blur="computeTax(record,2)" />
  235. </template>
  236. <template slot="num" slot-scope="text, record">
  237. <a-input-number v-model="record.num" :min="1" @blur="computeTax(record,1)" />
  238. </template>
  239. <template slot="ipertaxrate" slot-scope="text, record">
  240. <a-input-number
  241. v-model="record.ipertaxrate"
  242. :step="0.01"
  243. :formatter="value => `${value}%`"
  244. :parser="value => value.replace('%', '')" />
  245. </template>
  246. <template slot="cbmemo" slot-scope="text, record">
  247. <a-input v-model="record.cbmemo" />
  248. </template>
  249. <template slot="cdefine28" slot-scope="text, record">
  250. <a-input v-model="record.cdefine28" />
  251. </template>
  252. <template slot="cdefine22" slot-scope="text, record">
  253. <a-input v-model="record.cdefine22" />
  254. </template>
  255. <span slot="action" slot-scope="record">
  256. <template>
  257. <a-popconfirm title="是否要删除该条数据?" @confirm="handleDelOne(record)">
  258. <a>删除</a>
  259. </a-popconfirm>
  260. </template>
  261. </span>
  262. </a-table>
  263. </a-card>
  264. <template slot="footer">
  265. <a-button :loading="confirmLoading" type="primary" @click="save()">保存</a-button>
  266. </template>
  267. <sb-info-select-modal ref="sbInfoSelectModal" @selected="handleSbSelectd"/>
  268. <spare-store-select-modal ref="spareStoreSelectModal" @selected="handleSpareStoreSelected"/>
  269. <BomSpareStoreSelectModal ref="bomSpareStoreSelectModal" @selected="handleSpareStoreSelected"/>
  270. </a-modal>
  271. </template>
  272. <script>
  273. import pick from 'lodash.pick'
  274. import moment from 'moment'
  275. import { addPurchaseOrder2, updatePurchaseOrder2, getPurchasePrice } from '@/api/purchase/purchase-order'
  276. import SbInfoSelectModal from './SbInfoSelectModal'
  277. import SpareStoreSelectModal from '@/views/store/sparestore/modules/SpareStoreSelectModalYY3.vue'
  278. import BomSpareStoreSelectModal from './SpareStoreSelectModalYY.vue'
  279. import { fetchProjectTree } from '@/api/project/project'
  280. export default {
  281. name: 'BaseFillGather',
  282. components: {
  283. SpareStoreSelectModal,
  284. SbInfoSelectModal,
  285. BomSpareStoreSelectModal
  286. },
  287. data () {
  288. return {
  289. form: this.$form.createForm(this),
  290. visible: false,
  291. title: '新增',
  292. data: [],
  293. treeData: [],
  294. columns: [
  295. {
  296. title: '序号',
  297. width: 50,
  298. dataIndex: 'index',
  299. customRender: (text, record, index) => {
  300. return index + 1
  301. }
  302. },
  303. {
  304. title: '物料名称',
  305. width: 100,
  306. dataIndex: 'spareName'
  307. },
  308. {
  309. title: '存货编码',
  310. width: 100,
  311. dataIndex: 'no'
  312. },
  313. {
  314. title: '规格型号',
  315. width: 100,
  316. dataIndex: 'ggxh'
  317. },
  318. {
  319. title: '仓库名称',
  320. width: 100,
  321. dataIndex: 'storeName'
  322. },
  323. {
  324. title: '货架号',
  325. width: 150,
  326. dataIndex: 'storePosition'
  327. },
  328. {
  329. title: '批号',
  330. width: 100,
  331. dataIndex: 'cbatch'
  332. },
  333. {
  334. title: '需求人',
  335. dataIndex: 'cdefine22',
  336. width: 150,
  337. scopedSlots: { customRender: 'cdefine22' }
  338. },
  339. {
  340. title: '使用地点',
  341. dataIndex: 'cdefine28',
  342. width: 150,
  343. scopedSlots: { customRender: 'cdefine28' }
  344. },
  345. {
  346. title: '物资描述',
  347. dataIndex: 'cbmemo',
  348. width: 150,
  349. scopedSlots: { customRender: 'cbmemo' }
  350. },
  351. {
  352. title: '汇率',
  353. dataIndex: 'iexchrate',
  354. width: 150,
  355. scopedSlots: { customRender: 'iexchrate' }
  356. },
  357. {
  358. title: '本币无税单价',
  359. dataIndex: 'funitprice',
  360. width: 150,
  361. scopedSlots: { customRender: 'funitprice' }
  362. },
  363. {
  364. title: '税率',
  365. dataIndex: 'ipertaxrate',
  366. width: 150,
  367. scopedSlots: { customRender: 'ipertaxrate' }
  368. },
  369. {
  370. title: '申请数量',
  371. dataIndex: 'num',
  372. width: 150,
  373. scopedSlots: { customRender: 'num' }
  374. },
  375. {
  376. title: '本币价税合计',
  377. dataIndex: 'fmoney',
  378. width: 150,
  379. scopedSlots: { customRender: 'fmoney' }
  380. },
  381. {
  382. title: '操作',
  383. key: 'action',
  384. align: 'center',
  385. scopedSlots: { customRender: 'action' }
  386. }
  387. ],
  388. typeMap: {},
  389. ipqcMap: [],
  390. flagMap: {},
  391. model: {},
  392. sbId: null,
  393. rows: [],
  394. sortNums: [],
  395. params: {},
  396. directorMap: [],
  397. infoNum: 0,
  398. cptcodeMap: {},
  399. deptMap: {},
  400. deptNewMap: {},
  401. soMap: {},
  402. date: false,
  403. cbustypeMap: {},
  404. confirmLoading: false,
  405. oldOrNew: null
  406. }
  407. },
  408. created () {
  409. this.flagMap = this.DictCache.getLabelByValueMapByType(this.DictCache.TYPE.PROJECT_NEW_AND_OLD)
  410. this.typeMap = this.DictCache.getLabelByValueMapByType(this.DictCache.TYPE.LONG_YAN_PURCHASE_TYPE)
  411. this.cptcodeMap = this.DictCache.getLabelByValueMapByType(this.DictCache.TYPE.LONG_YAN_PURCHASE_ORDER_PLAN_TYPE)
  412. this.deptMap = this.DictCache.getLabelByValueMapByType(this.DictCache.TYPE.YONG_YOU_DEPT)
  413. this.deptNewMap = this.DictCache.getLabelByValueMapByType(this.DictCache.TYPE.YONG_YOU_DEPT_NEW)
  414. this.cbustypeMap = this.DictCache.getLabelByValueMapByType(this.DictCache.TYPE.LONG_YAN_PURCHASE_BUSINESS_TYPE)
  415. this.soMap = this.DictCache.getLabelByValueMapByType(this.DictCache.TYPE.SO_TYPE)
  416. },
  417. methods: {
  418. computeTax (record, type) {
  419. if (type === 1) {
  420. console.log(record)
  421. const data = (record.funitprice * record.num * (1 + record.ipertaxrate / 100)).toFixed(2)
  422. record.fmoney = isNaN(data) ? 0 : data
  423. } else {
  424. const data = (record.fmoney / (record.num * (1 + record.ipertaxrate / 100))).toFixed(4)
  425. record.funitprice = isNaN(data) ? 0 : data
  426. }
  427. this.$forceUpdate()
  428. },
  429. disabledDate (current) {
  430. // Can not select days before today and today
  431. return current && current < moment().endOf('day')
  432. },
  433. disabledDate2 (current) {
  434. // Can not select days before today and today
  435. return current && current <= this.date
  436. },
  437. dateChange (data) {
  438. console.log(data)
  439. this.date = data
  440. },
  441. base (record) {
  442. this.visible = true
  443. if (this.BaseTool.Object.isBlank(record)) {
  444. this.title = '新增'
  445. return
  446. }
  447. this.title = '编辑'
  448. this.data = record.detailVOS
  449. this.setTree(record.oldOrNew)
  450. const { form: { setFieldsValue } } = this
  451. this.$nextTick(() => {
  452. setFieldsValue(Object.assign(pick(record, [
  453. 'id',
  454. 'sbId',
  455. 'type',
  456. 'oldOrNew',
  457. 'projectId',
  458. 'positionNo',
  459. 'cdefine11',
  460. 'cdefine12',
  461. 'cptcode',
  462. 'remark',
  463. 'cdepcode',
  464. 'cbustype',
  465. 'planGetDate',
  466. 'needDate',
  467. 'cdefine22',
  468. 'cdefine28'
  469. ])))
  470. })
  471. },
  472. // 获取巡检人与巡检主管信息
  473. handleSbSelect () {
  474. this.$refs.sbInfoSelectModal.base({})
  475. },
  476. handleSbSelectd (keys, rows) {
  477. const [ key ] = keys
  478. const [ row ] = rows
  479. const { form: { setFieldsValue } } = this
  480. this.sbId = key
  481. // 日期处理
  482. this.$nextTick(() => {
  483. setFieldsValue(Object.assign({
  484. 'sbId': key,
  485. 'positionNo': row.positionNo
  486. }))
  487. })
  488. },
  489. setTree (val) {
  490. console.log(val)
  491. this.oldOrNew = val
  492. fetchProjectTree({
  493. flag: val
  494. }).then((res) => {
  495. this.treeData = res.data
  496. })
  497. },
  498. save () {
  499. const { form: { validateFieldsAndScroll } } = this
  500. // this.confirmLoading = true
  501. validateFieldsAndScroll((errors, values) => {
  502. if (errors) {
  503. Object.values(errors).map(item => {
  504. this.$message.error(item.errors[0].message)
  505. })
  506. this.confirmLoading = false
  507. return
  508. }
  509. let status = 0
  510. values.needDate = values.needDate ? this.BaseTool.Date.formatter(values.needDate, this.BaseTool.Date.PICKER_NORM_DATE_PATTERN) : null
  511. values.planGetDate = values.planGetDate ? this.BaseTool.Date.formatter(values.planGetDate, this.BaseTool.Date.PICKER_NORM_DATE_PATTERN) : null
  512. values.detailDTOS = this.data.map(item => {
  513. if (!item.funitprice) {
  514. status++
  515. this.$message.error('请填写' + item.spareName + '单价')
  516. }
  517. item.funitprice = (+item.funitprice).toFixed(4)
  518. item.ipertaxrate = (+item.ipertaxrate).toFixed(2)
  519. item.fmoney = (+item.fmoney).toFixed(2)
  520. return item
  521. })
  522. if (status !== 0) {
  523. return
  524. }
  525. if (values.id) {
  526. updatePurchaseOrder2(values).then(res => {
  527. this.$message.success('修改成功!')
  528. this.handleCancel()
  529. })
  530. } else {
  531. addPurchaseOrder2(values).then(res => {
  532. this.$message.success('创建成功!')
  533. this.handleCancel()
  534. })
  535. }
  536. })
  537. },
  538. handleSpareStoreSelect () {
  539. console.log(this.oldOrNew)
  540. this.$refs.spareStoreSelectModal.base({ tokenType: this.oldOrNew })
  541. },
  542. handleBomSpareStoreSelect () {
  543. this.$refs.bomSpareStoreSelectModal.base({ tokenType: this.oldOrNew, sbId: this.sbId })
  544. },
  545. handleSpareStoreSelected (record, keys, rows) {
  546. console.log(rows)
  547. const codes = []
  548. const { data } = this
  549. for (let i = 0; i < rows.length; i++) {
  550. let find = false
  551. for (let j = 0; j < data.length; j++) {
  552. if (rows[i].spareId === data[j].spareId && rows[i].cbatch === data[j].cbatch) {
  553. find = true
  554. break
  555. }
  556. }
  557. if (!find) {
  558. const selectData = this.BaseTool.Object.copy(rows[i])
  559. codes.push(selectData.no)
  560. selectData.storeNum = selectData.num
  561. selectData.num = 1
  562. selectData.iexchrate = 1
  563. selectData.ipertaxrate = 13
  564. data.push(selectData)
  565. }
  566. }
  567. getPurchasePrice({
  568. codes: codes.join(),
  569. isNew: this.oldOrNew
  570. }).then(res => {
  571. data.forEach(item => {
  572. item.funitprice = res.data.find(price => item.no === price.cinvCode).iunitPrice
  573. const data = (item.funitprice * item.num * (1 + item.ipertaxrate / 100)).toFixed(2)
  574. item.fmoney = isNaN(data) ? 0 : data
  575. })
  576. this.$forceUpdate()
  577. })
  578. },
  579. handleDelOne (record) {
  580. const data = [...this.data]
  581. this.data = data.filter(item => record.spareId !== item.spareId)
  582. },
  583. handleCancel (values) {
  584. this.visible = false
  585. this.data = []
  586. this.date = null
  587. this.params = {}
  588. this.form.resetFields()
  589. this.sbId = null
  590. this.oldOrNew = null
  591. this.$emit('ok', values)
  592. }
  593. }
  594. }
  595. </script>
  596. <style lang="less" scoped>
  597. .tooltip{
  598. font-size:20px;
  599. color:#ccc;
  600. &:hover {
  601. color:#2f54eb;
  602. }
  603. }
  604. </style>