epenseCdfModal.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. <template>
  2. <div>
  3. <a-spin :spinning="spinning" tip="Loading...">
  4. <div>
  5. <div class="epenseCdfModal-con">
  6. <!-- 列表 -->
  7. <a-table
  8. class="sTable fixPagination"
  9. ref="table"
  10. :scroll="{ y: 300 }"
  11. size="small"
  12. :rowKey="(record,index) => 'cdfTable-'+index"
  13. :columns="columns"
  14. :data-source="dataList"
  15. :pagination="false"
  16. bordered>
  17. <div slot="customTitle1"><span style="color: red;">*</span>费用承担方类型</div>
  18. <div slot="customTitle2"><span style="color: red;">*</span>费用承担方</div>
  19. <div slot="customTitle3"><span style="color: red;">*</span>费用承担金额</div>
  20. <!-- 费用承担方类型 -->
  21. <template slot="fycdftype" slot-scope="text,record,index">
  22. <v-select
  23. code="EXPENSE_ACCOUNT_DETAIL_SPLIT_OBJ_TYPE"
  24. allowClear
  25. style="width: 100%;"
  26. :isEnable="true"
  27. v-model="record.splitObjType"
  28. @change="splitObjTypeChange(index)"
  29. placeholder="请选择承担方类型"
  30. ></v-select>
  31. </template>
  32. <!-- 费用承担方 -->
  33. <template slot="fycdf" slot-scope="text,record,index">
  34. <!-- 部门 -->
  35. <department v-show="record.splitObjType=='DEPARTMENT'" style="width: 100%;" placeholder="请选择承担方" v-model="record.splitObjSn"></department>
  36. <!-- 经销商 -->
  37. <custList
  38. v-show="record.splitObjType=='CUSTOMER'"
  39. cooperateFlag="1"
  40. @change="custChange"
  41. :id="'cust-'+index"
  42. :ref="'custList-'+record.no"
  43. placeholder="请选择(输入名称搜索)"></custList>
  44. <span v-if="!record.splitObjType">--</span>
  45. </template>
  46. <!-- 费用承担金额 -->
  47. <template slot="amount" slot-scope="text,record,index">
  48. <a-input-number
  49. v-show="record.splitObjType"
  50. style="width: 100%;"
  51. v-model="record.splitAmount"
  52. @change="splitAmountChange"
  53. :precision="2"
  54. :min="0"
  55. :max="999999"
  56. placeholder="请输入"
  57. />
  58. <span v-if="!record.splitObjType">--</span>
  59. </template>
  60. <!-- 承担人员 -->
  61. <template slot="cdry" slot-scope="text,record,index">
  62. <div
  63. style="display: flex;align-items: center;width: 100%;padding: 5px 0;border-bottom: 1px solid #eee;"
  64. v-for="(item,idx) in record.childDetailSplitList"
  65. :key="item.id">
  66. <employee style="width: 40%;" placeholder="请选择承担人员" v-model="item.splitObjSn"></employee>
  67. -
  68. <a-input-number
  69. style="width: 40%;"
  70. v-model="item.splitAmount"
  71. :precision="2"
  72. :min="0"
  73. :max="999999"
  74. placeholder="请输入费用"
  75. />
  76. <div style="padding-left: 15px;" v-if="record.childDetailSplitList&&record.childDetailSplitList.length>1">
  77. <a-button
  78. @click="handleDelCdry(record,idx)"
  79. title="删除"
  80. size="small"
  81. type="danger"
  82. shape="circle"
  83. icon="delete" />
  84. </div>
  85. <div v-if="record.childDetailSplitList&&idx == record.childDetailSplitList.length - 1">
  86. <a-button
  87. @click="handleAddCdry(record,idx)"
  88. title="添加承担人员"
  89. size="small"
  90. type="primary"
  91. class="button-info"
  92. shape="circle"
  93. icon="plus" />
  94. </div>
  95. </div>
  96. <span v-if="record.childDetailSplitList&&record.childDetailSplitList.length==0">--</span>
  97. </template>
  98. <template slot="action" slot-scope="text,record,index">
  99. <a-button
  100. size="small"
  101. type="link"
  102. class="button-error"
  103. @click="handleDelRow(record,index)"
  104. >删除</a-button>
  105. </template>
  106. <template slot="footer" slot-scope="currentPageData">
  107. <a-button
  108. type="link"
  109. class="button-info"
  110. block
  111. @click="handleAddRow()"
  112. >+ 新增费用承担方</a-button>
  113. </template>
  114. </a-table>
  115. </div>
  116. </div>
  117. </a-spin>
  118. </div>
  119. </template>
  120. <script>
  121. import { VSelect } from '@/components'
  122. import department from './department.js'
  123. import employee from './employee.js'
  124. import custList from '@/views/common/custList.vue'
  125. export default {
  126. components: { VSelect, department, employee, custList },
  127. name: 'EpenseCdfModal',
  128. props: {
  129. list: { // 弹框显示状态
  130. type: Array,
  131. default: () => { return [] }
  132. }
  133. },
  134. watch: {
  135. list (newValue, oldValue) {
  136. this.dataList = JSON.parse(JSON.stringify(newValue))
  137. this.dataList.map(item => {
  138. item.no = item.id
  139. if (item.splitObjType == 'DEPARTMENT' && (!item.childDetailSplitList || item.childDetailSplitList.length == 0)) {
  140. this.$set(item, 'childDetailSplitList', [{
  141. splitObjType: 'EMPLOYEE',
  142. splitObjSn: undefined,
  143. splitAmount: 0
  144. }])
  145. }
  146. if (item.splitObjType == 'CUSTOMER') {
  147. this.$nextTick(() => {
  148. this.$refs['custList-' + item.no].setDufaultVal(item.splitObjName)
  149. })
  150. }
  151. })
  152. if (this.dataList.length == 0) {
  153. this.handleAddRow()
  154. }
  155. }
  156. },
  157. data () {
  158. return {
  159. spinning: false,
  160. dataList: [],
  161. columns: [
  162. { slots: { title: 'customTitle1' }, scopedSlots: { customRender: 'fycdftype' }, align: 'center', width: '15%' },
  163. { slots: { title: 'customTitle2' }, scopedSlots: { customRender: 'fycdf' }, align: 'center', width: '20%' },
  164. { slots: { title: 'customTitle3' }, scopedSlots: { customRender: 'amount' }, align: 'center', width: '15%' },
  165. { title: '承担人员-人员平摊费用', scopedSlots: { customRender: 'cdry' }, align: 'center', width: '40%' },
  166. { title: '操作', scopedSlots: { customRender: 'action' }, width: '10%', align: 'center' }
  167. ]
  168. }
  169. },
  170. mounted () {
  171. this.handleAddRow()
  172. },
  173. methods: {
  174. // 费用承担方类型
  175. splitObjTypeChange (index) {
  176. const row = this.dataList[index]
  177. console.log(index, row.splitObjType)
  178. row.splitObjSn = undefined
  179. // 只有部门有承担人员
  180. this.$set(row, 'childDetailSplitList', row.splitObjType == 'DEPARTMENT' ? [{
  181. splitObjType: 'EMPLOYEE',
  182. splitObjSn: undefined,
  183. splitAmount: Number(row.splitAmount).toFixed(2)
  184. }] : [])
  185. if (row.splitObjType == 'CUSTOMER') {
  186. this.$set(row, 'splitObjSn', undefined)
  187. this.$set(row, 'splitObjName', undefined)
  188. this.$refs['custList-' + row.no].dealerName = []
  189. }
  190. this.$emit('fyTotal', this.fyTotal())
  191. },
  192. // 经销商
  193. custChange (v, obj, id) {
  194. const row = this.dataList[id.split('-')[1]]
  195. this.$set(row, 'splitObjSn', v.key)
  196. this.$set(row, 'splitObjName', obj.dealerName)
  197. this.$emit('fyTotal', this.fyTotal())
  198. },
  199. // 承担费用
  200. splitAmountChange () {
  201. this.$emit('fyTotal', this.fyTotal())
  202. },
  203. // 清空数据
  204. clearList () {
  205. this.dataList = []
  206. },
  207. // 获取数据
  208. getList () {
  209. let hasError = 0
  210. const list = this.dataList.filter(item => item.splitObjType && item.splitObjSn && item.splitAmount)
  211. const ret = JSON.parse(JSON.stringify(list))
  212. if (ret.length != this.dataList.length) {
  213. hasError = 1
  214. } else {
  215. ret.map(item => {
  216. if (item.splitObjType == 'DEPARTMENT') {
  217. const al = item.childDetailSplitList.filter(a => !a.splitObjSn && a.splitAmount > 0)
  218. if (al.length) {
  219. hasError = 3
  220. } else {
  221. const dl = item.childDetailSplitList.filter(a => a.splitObjSn) || []
  222. // 有承担人员
  223. if (dl && dl.length) {
  224. let t = 0
  225. dl.map(b => t = Number(t) + Number(b.splitAmount))
  226. // console.log(Number(t), Number(item.splitAmount))
  227. hasError = (Number(t) != Number(item.splitAmount)) ? 2 : 0
  228. }
  229. item.childDetailSplitList = dl
  230. }
  231. }
  232. })
  233. }
  234. if (ret.length == 0) {
  235. hasError = 1
  236. }
  237. return [hasError, ret]
  238. },
  239. // 添加人员
  240. handleAddCdry (row, idx) {
  241. const cur = row.childDetailSplitList[idx]
  242. if (!cur.splitObjSn) {
  243. this.$message.info('请选择承担人员')
  244. return
  245. }
  246. if (cur.splitAmount <= 0) {
  247. this.$message.info('请输入平摊费用')
  248. return
  249. }
  250. // 校验承担费用合计是否超过费用承担金额
  251. let totalFy = 0
  252. row.childDetailSplitList.map(item => {
  253. totalFy = totalFy + Number(item.splitAmount)
  254. })
  255. // console.log(totalFy, row.splitAmount)
  256. if (totalFy >= Number(row.splitAmount).toFixed(2)) {
  257. this.$warning({
  258. title: '提示',
  259. content: '人员平摊费用合计必需等于费用承担金额'
  260. })
  261. return
  262. }
  263. // 已使用费用
  264. let ysyAmount = 0
  265. row.childDetailSplitList.map(item => {
  266. ysyAmount = ysyAmount + Number(item.splitAmount)
  267. })
  268. // 添加
  269. row.childDetailSplitList.push({
  270. splitObjType: 'EMPLOYEE',
  271. splitObjSn: undefined,
  272. splitAmount: Number(row.splitAmount - ysyAmount).toFixed(2)
  273. })
  274. },
  275. // 删除人员
  276. handleDelCdry (row, index) {
  277. row.childDetailSplitList.splice(index, 1)
  278. },
  279. // 添加承担费用
  280. handleAddRow () {
  281. this.dataList.push({
  282. no: new Date().getTime(),
  283. splitObjType: '',
  284. splitObjSn: undefined,
  285. splitAmount: 0,
  286. childDetailSplitList: []
  287. })
  288. },
  289. // 删除承担费用
  290. handleDelRow (a, index) {
  291. this.dataList.splice(index, 1)
  292. this.$emit('fyTotal', this.fyTotal())
  293. this.dataList.map(item => {
  294. if (item.splitObjType == 'CUSTOMER') {
  295. this.$nextTick(() => {
  296. this.$refs['custList-' + item.no].setDufaultVal(item.splitObjName)
  297. })
  298. }
  299. })
  300. },
  301. fyTotal: function () {
  302. let total = 0
  303. this.dataList.map(item => { total = total + item.splitAmount })
  304. return total.toFixed(2)
  305. }
  306. }
  307. }
  308. </script>
  309. <style lang="less">
  310. .epenseCdfModal-modal{
  311. .ant-modal-body {
  312. padding: 30px 40px 24px;
  313. }
  314. .epenseCdfModal-con{
  315. text-align: center;
  316. h3{
  317. font-size: 16px;
  318. font-weight: bold;
  319. margin-bottom: 25px;
  320. }
  321. }
  322. .btn-cont {
  323. text-align: center;
  324. margin: 35px 0 10px;
  325. }
  326. }
  327. </style>