details.vue 21 KB

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