productInfoModal.vue 13 KB

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