productInfoModal.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. <template>
  2. <a-modal
  3. centered
  4. class="productInfoModal-modal"
  5. :footer="null"
  6. :maskClosable="false"
  7. title="新增产品信息"
  8. v-model="isShow"
  9. @cancel="isShow=false"
  10. width="60%">
  11. <a-spin :spinning="spinning" tip="Loading...">
  12. <div>
  13. <a-descriptions v-if="baseData">
  14. <a-descriptions-item label="记账类型">
  15. {{ baseData.accountTypeDictValue }}
  16. </a-descriptions-item>
  17. <a-descriptions-item label="记账名称">
  18. {{ baseData.accountName }}
  19. </a-descriptions-item>
  20. <a-descriptions-item label="记账费用">
  21. ¥{{ baseData.expense }}
  22. </a-descriptions-item>
  23. </a-descriptions>
  24. <div class="productInfoModal-con">
  25. <!-- 列表 -->
  26. <a-table
  27. class="sTable fixPagination"
  28. ref="table"
  29. :scroll="{ y: 200 }"
  30. size="small"
  31. :rowKey="(record) => record.id"
  32. :columns="columns"
  33. :data-source="dataList"
  34. :pagination="false"
  35. bordered>
  36. <div slot="customTitle"><span style="color: red;">*</span>费用金额</div>
  37. <template slot="action" slot-scope="text,record,index">
  38. <a-button
  39. size="small"
  40. type="link"
  41. class="button-error"
  42. @click="handleDelRow(record,index)"
  43. >删除</a-button>
  44. </template>
  45. <!-- 产品品牌 -->
  46. <template slot="productBrand" slot-scope="text,record,index">
  47. <ProductBrand style="width: 100%;" :disabled="!!record.productCode" :id="'productBrand-'+index" @change="productBrandChange" v-model="record.productBrandSn"></ProductBrand>
  48. </template>
  49. <!-- 产品分类 -->
  50. <template slot="productType" slot-scope="text,record,index">
  51. <ProductTypeAll
  52. style="width: 100%;"
  53. :disabled="!!record.productCode"
  54. :ref="'productType-'+record.no"
  55. :id="'productType-'+index"
  56. v-model="record.productType"
  57. @change="changeProductType"></ProductTypeAll>
  58. </template>
  59. <!-- 产品编码 -->
  60. <template slot="productCode" slot-scope="text,record,index">
  61. <productCodeList :ref="'productCode-'+record.no" :key="'productCode-'+index" :id="'productCode-'+index" @change="e => productCodeChange(e, record)" />
  62. </template>
  63. <!-- 费用金额 -->
  64. <template slot="expense" slot-scope="text,record">
  65. <a-input-number
  66. style="width: 100%;"
  67. v-model="record.expense"
  68. :precision="2"
  69. :min="0"
  70. :max="999999"
  71. placeholder="请输入"
  72. />
  73. </template>
  74. <template slot="footer" slot-scope="currentPageData">
  75. <a-button
  76. type="link"
  77. class="button-info"
  78. v-if="dataList.length==0"
  79. block
  80. @click="handleAddRow()"
  81. >+ 新增产品信息</a-button>
  82. </template>
  83. </a-table>
  84. </div>
  85. <div class="btn-cont">
  86. <a-button id="productInfoModal-back" @click="isShow = false" style="margin-right: 15px;">取消</a-button>
  87. <a-button type="primary" id="productInfoModal-save" @click="handleSave">确定</a-button>
  88. </div>
  89. </div>
  90. </a-spin>
  91. </a-modal>
  92. </template>
  93. <script>
  94. import { VSelect, STable } from '@/components'
  95. import ProductTypeAll from '@/views/common/productTypeAll.js'
  96. import ProductBrand from '@/views/common/productBrand.js'
  97. import productCodeList from '@/views/common/productCodeList.vue'
  98. import { expenseAcctDetailSaveProducts, expenseAcctDetailFindProductsBySn } from '@/api/expenseManagement.js'
  99. export default {
  100. components: { VSelect, STable, ProductTypeAll, ProductBrand, productCodeList },
  101. name: 'ProductInfoModal',
  102. props: {
  103. openModal: { // 弹框显示状态
  104. type: Boolean,
  105. default: false
  106. },
  107. expenseAccountSn: { // 报销单sn
  108. type: String,
  109. default: ''
  110. },
  111. expenseAccountNo: { // 报销单号
  112. type: String,
  113. default: ''
  114. },
  115. expenseAccountDetailSn: {
  116. type: String,
  117. default: ''
  118. }
  119. },
  120. data () {
  121. return {
  122. spinning: false,
  123. isShow: this.openModal, // 是否打开弹框
  124. dataList: [],
  125. baseData: null,
  126. columns: [
  127. { title: '产品品牌', scopedSlots: { customRender: 'productBrand' }, align: 'center', width: '20%' },
  128. { title: '产品分类', scopedSlots: { customRender: 'productType' }, align: 'center', width: '30%' },
  129. { title: '产品编码', scopedSlots: { customRender: 'productCode' }, align: 'center', width: '20%' },
  130. // { slots: { title: 'customTitle' }, scopedSlots: { customRender: 'expense' }, align: 'center', width: '20%' }
  131. { title: '操作', scopedSlots: { customRender: 'action' }, width: '10%', align: 'center' }
  132. ]
  133. }
  134. },
  135. methods: {
  136. // 产品编码
  137. productCodeChange (val, row) {
  138. console.log(val, row)
  139. row.productSn = val.key || undefined
  140. row.productCode = val.row && val.row.code ? val.row.code : undefined
  141. row.productName = val.row && val.row.name ? val.row.name : undefined
  142. row.productBrandSn = val.row && val.row.productBrandSn ? val.row.productBrandSn : undefined
  143. row.productBrandName = val.row && val.row.productBrandName ? val.row.productBrandName : undefined
  144. row.productTypeSn1 = val.row && val.row.productTypeSn1 ? val.row.productTypeSn1 : undefined
  145. row.productTypeSn2 = val.row && val.row.productTypeSn2 ? val.row.productTypeSn2 : undefined
  146. row.productTypeSn3 = val.row && val.row.productTypeSn3 ? val.row.productTypeSn3 : undefined
  147. row.productTypeName1 = val.row && val.row.productTypeName1 ? val.row.productTypeName1 : undefined
  148. row.productTypeName2 = val.row && val.row.productTypeName2 ? val.row.productTypeName2 : undefined
  149. row.productTypeName3 = val.row && val.row.productTypeName3 ? val.row.productTypeName3 : undefined
  150. // 设置默认值
  151. const defval = row.productTypeSn1 || row.productTypeSn2 || row.productTypeSn3 ? [row.productTypeSn1, row.productTypeSn2, row.productTypeSn3] : []
  152. this.$set(row, 'productType', defval)
  153. this.$nextTick(() => {
  154. this.$refs['productType-' + row.no].setDefValue(defval)
  155. })
  156. },
  157. // 产品品牌
  158. productBrandChange (val, id, option) {
  159. const index = id.split('-')[1]
  160. const row = this.dataList[index]
  161. row.productBrandName = option && option.brandName ? option.brandName : undefined
  162. },
  163. // 产品分类 change
  164. changeProductType (val, id, options) {
  165. console.log(val, id, options)
  166. const index = id.split('-')[1]
  167. const row = this.dataList[index]
  168. if (val.length > 1) {
  169. row.productTypeSn1 = val[0] ? val[0] : ''
  170. row.productTypeSn2 = val[1] ? val[1] : ''
  171. row.productTypeSn3 = val[2] ? val[2] : ''
  172. if (options) {
  173. row.productTypeName1 = options[0] ? options[0].productTypeName : ''
  174. row.productTypeName2 = options[1] ? options[1].productTypeName : ''
  175. row.productTypeName3 = options[2] ? options[2].productTypeName : ''
  176. }
  177. } else if (val.length == 1) {
  178. this.$set(row, 'productType', [])
  179. this.$nextTick(() => {
  180. this.$refs['productType-' + row.no].setDefValue([])
  181. })
  182. this.$message.info('不能只选择一级分类')
  183. }
  184. },
  185. // 添加
  186. handleAddRow () {
  187. this.dataList.push({
  188. 'no': new Date().getTime(),
  189. 'expense': 0,
  190. 'expenseAccountDetailSn': this.expenseAccountDetailSn,
  191. 'expenseAccountSn': this.expenseAccountSn,
  192. 'productBrandName': '',
  193. 'productBrandSn': undefined,
  194. 'productCode': undefined,
  195. 'productName': '',
  196. 'productSn': '',
  197. 'productType': [],
  198. 'productTypeName1': '',
  199. 'productTypeName2': '',
  200. 'productTypeName3': '',
  201. 'productTypeSn1': '',
  202. 'productTypeSn2': '',
  203. 'productTypeSn3': ''
  204. })
  205. },
  206. // 删除
  207. handleDelRow (record, index) {
  208. console.log(record, this.$refs)
  209. this.dataList.splice(index, 1)
  210. this.dataList.map(item => {
  211. this.$nextTick(() => {
  212. const refDom = this.$refs['productCode-' + item.no]
  213. if (refDom) {
  214. refDom.dealerName = ''
  215. refDom.setDufaultVal(item.productCode || '')
  216. }
  217. })
  218. })
  219. },
  220. // 确定
  221. handleSave () {
  222. // 校验数据
  223. const retList = JSON.parse(JSON.stringify(this.dataList))
  224. console.log(retList)
  225. // if (retList.length == 0) {
  226. // this.$message.info('请添加产品信息')
  227. // return
  228. // }
  229. let hasError = 0
  230. retList.map(item => {
  231. if (!item.expense) {
  232. hasError = 1
  233. }
  234. if (!(item.productTypeSn1 || item.productCode || item.productBrandSn)) {
  235. hasError = 2
  236. }
  237. delete item.productType
  238. delete item.no
  239. })
  240. // if (hasError == 1) {
  241. // this.$message.info('请输入费用金额')
  242. // return
  243. // }
  244. if (hasError == 2) {
  245. this.$message.info('产品品牌、产品分类、产品编码,三个至少填一个')
  246. return
  247. }
  248. this.spinning = true
  249. expenseAcctDetailSaveProducts({
  250. 'expenseAccountDetailSn': this.expenseAccountDetailSn,
  251. 'detailProductsList': retList
  252. }).then(res => {
  253. this.spinning = false
  254. if (res.status == 200) {
  255. this.$message.success(res.message)
  256. this.$emit('ok', res.data)
  257. this.isShow = false
  258. }
  259. })
  260. },
  261. // 设置基础数据
  262. setBaseData (data) {
  263. this.baseData = data
  264. },
  265. // 查询详情
  266. getDetail () {
  267. this.spinning = true
  268. expenseAcctDetailFindProductsBySn({ detailSn: this.expenseAccountDetailSn }).then(res => {
  269. if (res.data && res.data.length) {
  270. this.dataList = res.data
  271. this.dataList.map(item => {
  272. item.no = item.id
  273. this.$nextTick(() => {
  274. if (item.productTypeSn1 || item.productTypeSn2 || item.productTypeSn3) {
  275. item.productType = [item.productTypeSn1, item.productTypeSn2, item.productTypeSn3]
  276. this.$refs['productType-' + item.no].setDefValue([item.productTypeSn1, item.productTypeSn2, item.productTypeSn3])
  277. }
  278. if (item.productCode) {
  279. this.$refs['productCode-' + item.no].setDufaultVal(item.productCode)
  280. }
  281. })
  282. })
  283. } else {
  284. this.dataList = [{
  285. 'no': new Date().getTime(),
  286. 'expense': 0,
  287. 'expenseAccountDetailSn': this.expenseAccountDetailSn,
  288. 'expenseAccountSn': this.expenseAccountSn,
  289. 'productBrandName': '',
  290. 'productBrandSn': undefined,
  291. 'productCode': '',
  292. 'productName': '',
  293. 'productSn': '',
  294. 'productType': [],
  295. 'productTypeName1': '',
  296. 'productTypeName2': '',
  297. 'productTypeName3': '',
  298. 'productTypeSn1': '',
  299. 'productTypeSn2': '',
  300. 'productTypeSn3': ''
  301. }]
  302. }
  303. this.spinning = false
  304. })
  305. }
  306. },
  307. watch: {
  308. // 父页面传过来的弹框状态
  309. openModal (newValue, oldValue) {
  310. this.isShow = newValue
  311. },
  312. // 重定义的弹框状态
  313. isShow (newValue, oldValue) {
  314. if (!newValue) {
  315. this.dataList = []
  316. this.baseData = null
  317. this.$emit('close')
  318. } else {
  319. this.getDetail()
  320. }
  321. }
  322. }
  323. }
  324. </script>
  325. <style lang="less">
  326. .productInfoModal-modal{
  327. .ant-modal-body {
  328. padding: 30px 40px 24px;
  329. }
  330. .productInfoModal-con{
  331. text-align: center;
  332. h3{
  333. font-size: 16px;
  334. font-weight: bold;
  335. margin-bottom: 25px;
  336. }
  337. }
  338. .btn-cont {
  339. text-align: center;
  340. margin: 35px 0 10px;
  341. }
  342. }
  343. </style>