InvoiceUpdateGenerateForm.vue 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. <template>
  2. <view>
  3. <view style="padding: 10px 0px 66px 0px;min-height: 100px">
  4. <!--标题-->
  5. <view style="text-align:center">
  6. <text class="title">{{title}}</text>
  7. </view>
  8. <view class="card">
  9. <!--表单-->
  10. <invoiceModule ref="invoiceModule" :invoice="jsonData" :formData="formData"></invoiceModule>
  11. <transferRecordsModule :historicTaskList="historicTaskList"></transferRecordsModule>
  12. <!--审核意见-->
  13. <view v-if="type === 'audit'">
  14. <view class="divider">
  15. <text class="divider-content"><span style="color: red">*</span> 审批意见</text>
  16. </view>
  17. <textarea :rows="5" maxlength="500" placeholder="请填写审核意见:" v-model="comments" show-word-limit></textarea>
  18. </view>
  19. <!--操作按钮-->
  20. <view class="bottom-wrap flex">
  21. <view class="flex-sub"
  22. v-for="(button, index) in buttons" :key="index" >
  23. <u-button type="primary" class=" buttonBox" :color="colors[index]" @click="submit(button, buttons)" :text="button.name"></u-button>
  24. </view>
  25. </view>
  26. </view>
  27. </view>
  28. </view>
  29. </template>
  30. <script>
  31. import InvoiceModule from './InvoiceModule.vue';
  32. import TransferRecordsModule from './TransferRecordsModule.vue';
  33. import ccpmService from '@/api/centerservice/ccpm/CcpmService'
  34. export default {
  35. onLoad: function (option) {
  36. this.flow = JSON.parse(decodeURIComponent(option.flow));
  37. this.businessId = this.flow.id
  38. this.processDefKey = this.flow.processDefKey
  39. this.title = this.flow.title
  40. this.type = this.flow.type
  41. this.jsonData = []
  42. this.comments = ''
  43. },
  44. data () {
  45. return {
  46. buttons: [
  47. {code: '_flow_agree', name: '同意'},
  48. {code: '_flow_reject', name: '驳回'},
  49. {code: '_flow_close', name: '关闭'},
  50. ],
  51. colors: [ '#3c9cff', '#f56c6c', '#5ac725', '#f9ae3d', '#89c152',
  52. '#c38cc1', '#448aca', '#73d1f1', '#ffb34b', '#f18080',
  53. '#88a867', '#bfbf39', '#94d554', '#f19ec2', '#afaae4',
  54. '#86cefa', '#98d1ee', '#72dcdc', '#9acdcb', '#77b1cc', '#80a7dc'
  55. ],
  56. flow: null,
  57. formData: {
  58. name: '',
  59. email: '',
  60. remarks: ''
  61. },
  62. jsonData: [],
  63. historicTaskList: [],
  64. title: '',
  65. businessId: '',
  66. type: '',
  67. processDefKey: '',
  68. comments: '' // 审核意见
  69. }
  70. },
  71. activated () {
  72. this.init()
  73. },
  74. created () {
  75. this.init()
  76. },
  77. components: {
  78. InvoiceModule,
  79. TransferRecordsModule,
  80. },
  81. methods: {
  82. // 初始化
  83. init () {
  84. this.$nextTick(async () => {
  85. await ccpmService.getByIdGenerate(this.businessId, this.processDefKey).then((data)=>{
  86. if (data) {
  87. this.jsonData = Array.isArray(data) ? data : [data];
  88. this.historicTaskList = data.histoicFlow
  89. } else {
  90. }
  91. })
  92. })
  93. },
  94. // 关闭
  95. close () {
  96. this.jsonData = []
  97. this.comments = ''
  98. uni.navigateTo({
  99. url: '/pages/workbench/task/TodoList'
  100. })
  101. },
  102. // 同意
  103. async agree () {
  104. const inputForm = this.$refs.invoiceModule.getInputForm();
  105. return new Promise( (resolve, reject) => {
  106. // 表单规则验证
  107. // ...
  108. let errors = [];
  109. if (this.isEmpty(inputForm.invoiceDate)) {
  110. errors.push('开票时间不能为空');
  111. }
  112. let acc = 0
  113. let i = inputForm.workAccountList.length;
  114. for (let j = 0; j < i; j++) {
  115. let k = j + 1;
  116. if (this.isEmpty(inputForm.workAccountList[j].number)) {
  117. errors.push('发票明细中第' + k + ' 条数据的 “发票号” 为空');
  118. }
  119. if (this.isEmpty(inputForm.workAccountList[j].account)) {
  120. errors.push('发票明细中第' + k + ' 条数据的 “开票金额” 为空');
  121. }
  122. acc = (acc + parseFloat(parseFloat(inputForm.workAccountList[j].account).toFixed(2)))
  123. }
  124. if (parseFloat(acc).toFixed(2) !== parseFloat(inputForm.money).toFixed(2)) {
  125. errors.push('发票明细中 “开票金额”总和 与发票详情中 “发票金额” 不等');
  126. }
  127. let errorDetected = true; // 布尔变量用于检测是否有错误发生
  128. inputForm.workAccountList.forEach( async(item, index) => {
  129. const numberString = item.number.trim(); // 去除空格
  130. // 查询是否已存在
  131. await ccpmService.queryByNumber(numberString).then((data) => {
  132. if (data === true) {
  133. errorDetected = false
  134. errors.push('“发票号” 已存在,请重新输入');
  135. }
  136. });
  137. if (errorDetected) {
  138. inputForm.workAccountList.forEach((item2, index2) => {
  139. if (index !== index2) {
  140. if (item.number === item2.number) {
  141. errors.push('发票明细中第 ' + (index + 1) + ' 条数据的 “发票号” 存在重复');
  142. }
  143. }
  144. })
  145. }
  146. })
  147. if (errors.length > 0) {
  148. // 存在错误,显示提示信息
  149. errors.forEach(error => {
  150. uni.showToast({
  151. title: error,
  152. icon: 'none',
  153. duration: 2000
  154. });
  155. });
  156. reject('Form validation failed');
  157. } else {
  158. if (this.isEmpty(this.comments)) {
  159. uni.showToast({ title: '请填写审批意见!', icon: "error" });
  160. } else {
  161. let jsonData = JSON.stringify(inputForm)
  162. ccpmService.invoiceAudit(this.businessId, 'yes', this.comments, this.processDefKey,jsonData).then((data) => {
  163. if (data.success) {
  164. this.$message.success(data.message)
  165. this.close()
  166. } else {
  167. this.$message.error(data.message)
  168. }
  169. }).catch(() => {
  170. })
  171. }
  172. }
  173. });
  174. },
  175. // 驳回
  176. reject () {
  177. const inputForm = this.$refs.invoiceModule.getInputForm();
  178. if (this.isEmpty(this.comments)) {
  179. uni.showToast({ title: '请填写审批意见', icon: "error" });
  180. } else {
  181. // 弹窗 二次确认
  182. uni.showModal({
  183. content: '确定驳回此报销申请吗?',
  184. success: async (res) => {
  185. if (res.confirm) {
  186. let jsonData = JSON.stringify(inputForm)
  187. ccpmService.invoiceAudit(this.businessId, 'no', this.comments, this.processDefKey,jsonData).then((data) => {
  188. if (data.success) {
  189. this.$message.success(data.message)
  190. this.close()
  191. } else {
  192. this.$message.error(data.message)
  193. }
  194. }).catch(() => {
  195. })
  196. }
  197. },
  198. })
  199. }
  200. },
  201. isEmpty(value) {
  202. let result = false;
  203. if (value == null || value == undefined) {
  204. result = true;
  205. }
  206. if (typeof value == 'string' && (value.replace(/\s+/g, "") == "" || value == "")) {
  207. result = true;
  208. }
  209. if (typeof value == "object" && value instanceof Array && value.length === 0) {
  210. result = true;
  211. }
  212. return result;
  213. },
  214. isNotEmpty (value) {
  215. return !this.isEmpty(value)
  216. },
  217. submit (currentBtn, buttons) {
  218. switch (currentBtn.code) {
  219. case '_flow_agree': // 同意
  220. this.agree()
  221. break
  222. case '_flow_reject': // 驳回
  223. this.reject()
  224. break
  225. case '_flow_close':// 关闭
  226. this.close()
  227. break
  228. }
  229. }
  230. }
  231. }
  232. </script>
  233. <style scoped>
  234. .title {
  235. font-size: 24px;
  236. font-weight: bold;
  237. }
  238. .card {
  239. padding: 15px;
  240. background-color: #fff;
  241. box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
  242. }
  243. .divider {
  244. display: flex;
  245. align-items: center;
  246. margin-top: 20px;
  247. }
  248. .divider-content {
  249. font-size: 16px;
  250. color: #333;
  251. }
  252. .FlowFormFooter {
  253. display: flex;
  254. justify-content: space-around;
  255. margin-top: 2em;
  256. }
  257. button {
  258. padding: 10px 20px;
  259. border: none;
  260. border-radius: 5px;
  261. }
  262. button[type=primary] {
  263. background-color: #409eff;
  264. color: #fff;
  265. }
  266. button[type=danger] {
  267. background-color: #f56c6c;
  268. color: #fff;
  269. }
  270. </style>