details.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  1. <template>
  2. <div class="edit">
  3. <van-nav-bar title="报销凭证详情" left-text="返回" @click-left="back" fixed left-arrow />
  4. <van-form class="edit_form" label-width="140">
  5. <!-- 报销人 -->
  6. <van-field
  7. label="报销人"
  8. @click="ownerIdShow = true"
  9. readonly
  10. clickable
  11. required
  12. >
  13. <template #input>
  14. <span v-if="user.userNameNeedTranslate == 1"><ww-open-data type='userName' :openid='formshowText.name'></ww-open-data></span>
  15. <span v-else>{{formshowText.name}}</span>
  16. </template>
  17. </van-field>
  18. <van-popup v-model="ownerIdShow" position="bottom" v-if="false">
  19. <van-picker
  20. value-key="name"
  21. show-toolbar
  22. :columns="userList"
  23. @confirm="ownerIdChange"
  24. @cancel="
  25. ownerIdShow = false;
  26. $forceUpdate();
  27. "
  28. />
  29. </van-popup>
  30. <!-- 填报日期 -->
  31. <van-field
  32. v-model="editForm.createDate"
  33. label="填报日期"
  34. @click="createDateShow = true"
  35. readonly
  36. clickable
  37. required
  38. ></van-field>
  39. <van-popup v-model="createDateShow" position="bottom" v-if="canEdit">
  40. <van-datetime-picker
  41. type="date"
  42. title="选择填报日期"
  43. @confirm="createDateChange"
  44. @cancel="
  45. createDateShow = false;
  46. $forceUpdate();
  47. "
  48. v-model="currentDate1"
  49. :min-date="minDate"
  50. :max-date="maxDate"
  51. />
  52. </van-popup>
  53. <!-- 发票张数 -->
  54. <van-field label="发票张数" :readonly="!canEdit">
  55. <template #input>
  56. <van-stepper v-model="editForm.ticketNum" :disabled="!canEdit" disable-input @plus="ticNumChange(1)" @minus="ticNumChange(0)" />
  57. </template>
  58. </van-field>
  59. <!-- 费用类型 -->
  60. <van-field
  61. v-model="editForm.type"
  62. label="费用类型"
  63. @click="typeShow = true"
  64. readonly
  65. clickable
  66. >
  67. <template #input>{{ typeList[editForm.type] }}</template>
  68. </van-field>
  69. <van-popup v-model="typeShow" position="bottom" v-if="canEdit">
  70. <van-picker
  71. show-toolbar
  72. :columns="typeList"
  73. @confirm="typeChange"
  74. @cancel="
  75. typeShow = false;
  76. $forceUpdate();
  77. "
  78. />
  79. </van-popup>
  80. <!-- 备注 -->
  81. <van-field v-model="editForm.remark" label="备注" :readonly="!canEdit" type="textarea"></van-field>
  82. <!-- 发票 -->
  83. <van-field label="发票" readonly>
  84. <template #input
  85. >总费用: ¥{{ totalCost }}</template
  86. >
  87. </van-field>
  88. <div class="invoice" v-if="invoiceList.length != 0">
  89. <div
  90. v-for="(item, index) in invoiceList"
  91. :key="item.id"
  92. style="position: relative"
  93. :class="index == 0 ? '' : 'invoice_item'"
  94. >
  95. <van-icon
  96. name="delete-o"
  97. class="deletebtn"
  98. @click="deleteInvoice(index)"
  99. v-if="canEdit && index != 0"
  100. />
  101. <van-field
  102. label="所属项目:"
  103. v-model="item.projectId"
  104. @click="(in_projectShow = true), (invoiceIndex = index)"
  105. readonly
  106. clickable
  107. required
  108. >
  109. <template #input>{{
  110. formshowText.inProjectName[index]
  111. }}</template>
  112. </van-field>
  113. <van-field
  114. label="费用日期:"
  115. v-model="item.happenDate"
  116. @click="(in_dateShow = true), (invoiceIndex = index)"
  117. readonly
  118. clickable
  119. required
  120. ></van-field>
  121. <van-field
  122. label="发票种类:"
  123. v-model="item.invoiceType"
  124. @click="(in_typeShow = true), (invoiceIndex = index)"
  125. readonly
  126. clickable
  127. required
  128. >
  129. <template #input>{{
  130. inTypeList[item.invoiceType]
  131. }}</template>
  132. </van-field>
  133. <van-field
  134. label="费用类型:"
  135. v-model="item.expenseType"
  136. @click="(in_exTypeShow = true), (invoiceIndex = index)"
  137. readonly
  138. clickable
  139. required
  140. ></van-field>
  141. <van-field
  142. label="费用金额(含税):"
  143. v-model="item.amount"
  144. type="number"
  145. :readonly="!canEdit"
  146. required
  147. ></van-field>
  148. <van-field
  149. label="发票号:"
  150. v-model="item.invoiceNo"
  151. readonly
  152. ></van-field>
  153. <van-field
  154. label="税率%:"
  155. v-model="item.taxPercent"
  156. :readonly="!canEdit"
  157. ></van-field>
  158. <van-field
  159. label="税额:"
  160. readonly
  161. ><template #input>¥{{getTaxValue(item.amount,item.taxPercent)}}</template></van-field>
  162. <van-field label="备注:" v-model="item.remark" :readonly="!canEdit"></van-field>
  163. <van-field
  164. label="报销凭证:"
  165. @click="invoiceIndex = index"
  166. :clickable="!canEdit"
  167. >
  168. <template #input>
  169. <van-uploader
  170. v-model="uploader[index]"
  171. :before-read="beforeRead"
  172. :after-read="afterRead"
  173. @delete="item.pic = null"
  174. :max-count="1"
  175. :disabled="!canEdit"
  176. :deletable="canEdit"
  177. />
  178. </template>
  179. </van-field>
  180. </div>
  181. </div>
  182. <div class="addinvoice" v-if="canEdit"><van-button size="small" icon="plus" type="info" plain hairline @click="addInvoice">添加发票</van-button></div>
  183. <!-- 发票-popup -->
  184. <span>
  185. <!-- 所属项目 -->
  186. <van-popup v-model="in_projectShow" position="bottom" v-if="canEdit">
  187. <van-picker
  188. value-key="projectName"
  189. show-toolbar
  190. :columns="inProjectList"
  191. @confirm="inProjectChange"
  192. @cancel="
  193. in_projectShow = false;
  194. $forceUpdate();
  195. "
  196. />
  197. </van-popup>
  198. <!-- 费用日期 -->
  199. <van-popup v-model="in_dateShow" position="bottom" v-if="canEdit">
  200. <van-datetime-picker
  201. type="date"
  202. title="选择费用日期"
  203. v-model="currentDate2"
  204. @confirm="inDateChange"
  205. @cancel="
  206. in_dateShow = false;
  207. $forceUpdate();
  208. "
  209. :min-date="minDate"
  210. :max-date="maxDate"
  211. />
  212. </van-popup>
  213. <!-- 发票种类 -->
  214. <van-popup v-model="in_typeShow" position="bottom" v-if="canEdit">
  215. <van-picker
  216. show-toolbar
  217. :columns="inTypeList"
  218. @confirm="inTypeChange"
  219. @cancel="
  220. in_typeShow = false;
  221. $forceUpdate();
  222. "
  223. />
  224. </van-popup>
  225. <!-- 费用类型 -->
  226. <van-popup v-model="in_exTypeShow" position="bottom" v-if="canEdit">
  227. <van-picker
  228. value-key="typeName"
  229. show-toolbar
  230. :columns="inexTypeList"
  231. @confirm="inexTypeChange"
  232. @cancel="
  233. in_exTypeShow = false;
  234. $forceUpdate();
  235. "
  236. />
  237. </van-popup>
  238. </span>
  239. </van-form>
  240. <!-- 提交 -->
  241. <div class="form_btn" style="position: fixed; bottom: 0px; width: 100%" v-if="canEdit">
  242. <div style="padding-bottom: 10px">
  243. <van-button
  244. square
  245. block
  246. type="info"
  247. @click="submitExpense"
  248. :loading="confirmLoading"
  249. style="width: 100%; float: left"
  250. >提交</van-button
  251. >
  252. </div>
  253. </div>
  254. </div>
  255. </template>
  256. <script>
  257. export default {
  258. data() {
  259. return {
  260. user: JSON.parse(localStorage.userInfo),
  261. canEdit: this.$route.params.canEdit,
  262. canExamine: false,
  263. currentDate1 : new Date(),
  264. currentDate2 : new Date(),
  265. minDate: new Date(2020,0,1),
  266. maxDate: new Date(2025,11,31),
  267. editForm: {
  268. ownerId: '',
  269. createDate: '',
  270. ticketNum: 0,
  271. type: 0,
  272. remark: ''
  273. },
  274. invoiceList: [],
  275. confirmLoading: false,
  276. formshowText: {
  277. name: '',
  278. inProjectName: []
  279. },
  280. ownerIdShow: false,
  281. userList: [],
  282. createDateShow: false,
  283. typeShow: false,
  284. typeList: ['一般','差旅','外包'],
  285. invoiceIndex: 0,
  286. in_projectShow: false,
  287. inProjectList: [],
  288. in_dateShow: false,
  289. in_typeShow: false,
  290. inTypeList: ['增值税专用发票','增值税普通发票'],
  291. in_exTypeShow: false,
  292. allexTypeList: [],
  293. inexTypeList: [],
  294. uploader: [[]],
  295. }
  296. },
  297. computed: {
  298. totalCost(){
  299. let costnum = 0
  300. for(let i in this.invoiceList){
  301. costnum += (this.invoiceList[i].amount ? parseFloat(this.invoiceList[i].amount) : 0)
  302. }
  303. return costnum.toFixed(2)
  304. }
  305. },
  306. filters: {
  307. numtosum(value) {
  308. if (value == undefined || !value) return '0.00'
  309. value = value.toFixed(2)
  310. const intPart = Math.trunc(value)
  311. const intPartFormat = intPart.toString().replace(/(\d)(?=(?:\d{3})+$)/g, '$1,')
  312. let floatPart = '.00'
  313. const valueArray = value.toString().split('.')
  314. if (valueArray.length === 2) { // 有小数部分
  315. floatPart = valueArray[1].toString() // 取得小数部分
  316. return intPartFormat + '.' + floatPart
  317. }
  318. return intPartFormat + floatPart
  319. },
  320. },
  321. mounted() {
  322. console.log(this.$route.params);
  323. for(let i in this.user.functionList){
  324. if(this.user.functionList[i].name == '费用审核'){
  325. this.canExamine = true
  326. }
  327. }
  328. this.getDetail()
  329. if(this.canEdit){
  330. // if(this.canExamine){
  331. // this.getUserList()
  332. // }
  333. this.getProjectList()
  334. }
  335. },
  336. methods: {
  337. back(){
  338. history.back();
  339. },
  340. formatDate(date) {
  341. let mon = date.getMonth() + 1
  342. return `${date.getFullYear()}-${mon<10?'0'+mon:mon}-${date.getDate()<10?'0'+date.getDate():date.getDate()}`;
  343. },
  344. getTaxValue(amount,percent){
  345. let per = percent / 100
  346. let amo = amount / (1 + per)*per
  347. return amo.toFixed(2)
  348. },
  349. // costCount(){
  350. // let costnum = 0
  351. // for(let i in this.invoiceList){
  352. // costnum += this.invoiceList[i].amount*1
  353. // }
  354. // this.totalCost = costnum
  355. // },
  356. ownerIdChange(value,key){
  357. this.editForm.ownerId = value.id
  358. this.formshowText.name = value.name
  359. this.ownerIdShow = false
  360. },
  361. createDateChange(value,key){
  362. this.editForm.createDate = this.formatDate(value)
  363. this.createDateShow = false
  364. },
  365. typeChange(value,key){
  366. this.editForm.type = key
  367. this.typeShow = false
  368. this.inexTypeList = this.allexTypeList.filter(a=>a.mainType == this.editForm.type)
  369. },
  370. ticNumChange(value){
  371. if(value){
  372. this.invoiceList.push({
  373. projectId: '',
  374. happenDate: '',
  375. invoiceType: '',
  376. expenseType: '',
  377. amount: '',
  378. invoiceNo: '',
  379. taxPercent: '',
  380. taxValue: '',
  381. remark: '',
  382. pic: '',
  383. })
  384. }else{
  385. this.invoiceList.pop()
  386. }
  387. },
  388. addInvoice(){
  389. this.invoiceList.push({
  390. projectId: '',
  391. happenDate: '',
  392. invoiceType: '',
  393. expenseType: '',
  394. amount: '',
  395. invoiceNo: '',
  396. taxPercent: '',
  397. taxValue: '',
  398. remark: '',
  399. pic: '',
  400. })
  401. this.uploader.push([])
  402. this.editForm.ticketNum = this.invoiceList.length
  403. },
  404. deleteInvoice(index){
  405. this.invoiceList.splice(index,1)
  406. this.editForm.ticketNum = this.invoiceList.length
  407. this.uploader.splice(index,1)
  408. },
  409. inProjectChange(value,key){
  410. this.formshowText.inProjectName[this.invoiceIndex] = value.projectName
  411. this.invoiceList[this.invoiceIndex].projectId = value.id
  412. this.in_projectShow = false
  413. },
  414. inDateChange(value,key){
  415. this.invoiceList[this.invoiceIndex].happenDate = this.formatDate(value)
  416. this.in_dateShow = false
  417. },
  418. inTypeChange(value,key){
  419. this.invoiceList[this.invoiceIndex].invoiceType = key
  420. this.in_typeShow = false
  421. },
  422. inexTypeChange(value,key){
  423. this.invoiceList[this.invoiceIndex].expenseType = value.typeName
  424. this.in_exTypeShow = false
  425. },
  426. beforeRead(file){
  427. if(file.type != 'image/jpeg' && file.type != 'image/png'){
  428. this.$toast.fail('请选择jpg或png格式的图片')
  429. return false
  430. }
  431. return true
  432. },
  433. afterRead(file){
  434. let formData = new FormData();
  435. formData.append("multipartFile", file.file);
  436. this.$axios.post("/common/uploadFile", formData)
  437. .then(res => {
  438. if(res.code == "ok") {
  439. this.invoiceList[this.invoiceIndex].pic = res.data
  440. } else {
  441. this.$toast.fail('上传失败');
  442. this.uploader[this.invoiceIndex] = []
  443. }
  444. }).catch(err=> {this.$toast.clear();console.log(err);this.uploader[this.invoiceIndex]=[]});
  445. },
  446. submitExpense(){
  447. if(!this.editForm.ownerId){
  448. this.$toast.fail('请选择报销人')
  449. return
  450. }
  451. if(!this.editForm.createDate){
  452. this.$toast.fail('请选择填报日期')
  453. return
  454. }
  455. let required1 = false
  456. let required2 = false
  457. let required3 = false
  458. let required4 = false
  459. let required5 = false
  460. for(let i in this.invoiceList){
  461. if(!this.invoiceList[i].projectId){
  462. required1 = '所属项目'
  463. }
  464. if(!this.invoiceList[i].happenDate){
  465. required2 = '费用日期'
  466. }
  467. if(!this.invoiceList[i].invoiceType){
  468. required3 = '发票种类'
  469. }
  470. if(!this.invoiceList[i].expenseType){
  471. required4 = '费用类型'
  472. }
  473. if(!this.invoiceList[i].amount){
  474. required5 = '费用金额(含税)'
  475. }
  476. }
  477. if(required1 || required2 || required3 || required4 || required5){
  478. let requiredStr = (required1 ? required1 + '、' : '')
  479. + (required2 ? required2 + '、' : '')
  480. + (required3 ? required3 + '、' : '')
  481. + (required4 ? required4 + '、' : '')
  482. + (required5 ? required5 + '、' : '')
  483. requiredStr = requiredStr.substring(0,requiredStr.length - 1)
  484. this.$toast.fail('请添加发票的[' + requiredStr + ']')
  485. return
  486. }
  487. delete this.editForm.invoiceList
  488. this.editForm.items = JSON.stringify(this.invoiceList)
  489. this.editForm.totalAmount = this.totalCost
  490. this.confirmLoading = true
  491. this.$axios.post("/expense-sheet/add", this.editForm)
  492. .then(res => {
  493. if(res.code == "ok") {
  494. this.$toast.success('提交成功')
  495. this.confirmLoading = false
  496. this.back()
  497. } else {
  498. this.confirmLoading = false
  499. this.$toast.fail('获取失败');
  500. }
  501. }).catch(err=> {this.confirmLoading = false;this.$toast.clear();console.log(err)});
  502. },
  503. getDetail(){
  504. this.$axios.post("/expense-sheet/getDetail", {id: this.$route.params.id})
  505. .then(res => {
  506. if(res.code == "ok") {
  507. this.editForm = res.data
  508. if(this.canEdit){this.getExTypeList()}
  509. this.formshowText.name = res.data.ownerName
  510. this.totalCost = res.data.totalAmount
  511. this.invoiceList = res.data.invoiceList
  512. for(let i in res.data.invoiceList){
  513. this.formshowText.inProjectName.push(res.data.invoiceList[i].projectName)
  514. if(res.data.invoiceList[i].pic){
  515. this.uploader[i] = [{url:'/upload/' + res.data.invoiceList[i].pic}]
  516. }else{
  517. this.uploader[i] = []
  518. }
  519. }
  520. } else {
  521. this.$toast.fail('获取失败');
  522. }
  523. }).catch(err=> {this.$toast.clear();console.log(err)});
  524. },
  525. getUserList(){
  526. this.$axios.post("/user/getSimpleActiveUserList", {})
  527. .then(res => {
  528. if(res.code == "ok") {
  529. this.userList = res.data
  530. } else {
  531. this.$toast.fail('获取失败');
  532. }
  533. }).catch(err=> {this.$toast.clear();console.log(err)});
  534. },
  535. getProjectList(){
  536. this.$axios.post("/project/getProjectList", {})
  537. .then(res => {
  538. if(res.code == "ok") {
  539. this.inProjectList = res.data
  540. } else {
  541. this.$toast.fail('获取失败');
  542. }
  543. }).catch(err=> {this.$toast.clear();console.log(err)});
  544. },
  545. getExTypeList(){
  546. this.$axios.post("/expense-type/getList", {})
  547. .then(res => {
  548. if(res.code == "ok") {
  549. this.allexTypeList = res.data
  550. this.inexTypeList = this.allexTypeList.filter(a=>a.mainType == this.editForm.type)
  551. } else {
  552. this.$toast.fail('获取失败');
  553. }
  554. }).catch(err=> {this.$toast.clear();console.log(err)});
  555. },
  556. },
  557. };
  558. </script>
  559. <style lang="less" scoped>
  560. .edit{
  561. margin-top: 46px;
  562. overflow: auto;
  563. .form_btn{
  564. z-index: 1000;
  565. }
  566. .edit_form{
  567. .userCheckbox {
  568. padding: 10px;
  569. }
  570. padding-bottom: 46px;
  571. .invoice{
  572. border: 0.5px solid rgb(135, 195, 255);
  573. margin: 0.2rem;
  574. .deletebtn{
  575. position: absolute;
  576. z-index: 1000;
  577. font-size: 24px;
  578. right: 0.08rem;
  579. top: 0.08rem;
  580. color: #c03131;
  581. }
  582. .invoice_item{
  583. border-top: 0.5px solid rgb(135, 195, 255);
  584. }
  585. }
  586. .addinvoice{
  587. padding: 0 0.3rem 0.3rem;
  588. margin-top: 0.2rem;
  589. text-align: right;
  590. }
  591. }
  592. }
  593. </style>
  594. <style>
  595. .edit_form .invoice .van-field__label{
  596. color: #999;
  597. }
  598. .edit_form .invoice .van-field__control{
  599. color: #999;
  600. }
  601. </style>