SendFunds.vue 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869
  1. <template>
  2. <div style="width: 100%; padding: 0px 15px">
  3. <el-form :model="formData.data" :rules="rules" ref="formDom" label-position="top" :disabled="judgeStatus()">
  4. <div class="_t">基础信息</div>
  5. <el-row :gutter="10">
  6. <el-col :span="6">
  7. <el-form-item label="归属公司" prop="corporationId">
  8. <el-select v-model="formData.data.corporationId" placeholder="请选择" filterable style="width: 100%">
  9. <el-option v-for="item in companyData" :label="item.name" :value="item.id"> </el-option>
  10. </el-select>
  11. </el-form-item>
  12. </el-col>
  13. <el-col :span="6">
  14. <el-form-item label="归属部门" prop="departmentId">
  15. <el-tree-select
  16. v-model="formData.data.departmentId"
  17. :data="deptTreeData"
  18. check-strictly
  19. :render-after-expand="false"
  20. node-key="deptId"
  21. style="width: 100%"
  22. :props="defaultProps" />
  23. </el-form-item>
  24. </el-col>
  25. </el-row>
  26. <el-row :gutter="10">
  27. <el-col :span="6">
  28. <el-form-item label="币种" prop="currency">
  29. <el-select v-model="formData.data.currency" placeholder="请选择" filterable style="width: 100%">
  30. <el-option v-for="item in currencyType" :label="item.dictValue" :value="item.dictKey"> </el-option>
  31. </el-select>
  32. </el-form-item>
  33. </el-col>
  34. <el-col :span="6">
  35. <el-form-item label="请款类型" prop="type">
  36. <el-select v-model="formData.data.type" placeholder="请选择" filterable style="width: 100%" @change="changeType">
  37. <el-option v-for="item in fundsType" :label="item.dictValue" :value="item.dictKey"> </el-option>
  38. </el-select>
  39. </el-form-item>
  40. </el-col>
  41. <el-col :span="6" v-if="formData.data.type === '3'">
  42. <el-form-item label="关联预支" prop="advanceId">
  43. <el-select v-model="formData.data.advanceId" placeholder="请选择" filterable style="width: 100%" @change="changeAdvanceId">
  44. <el-option v-for="item in advanceList" :label="item.createTime.substr(0, 10) + ' ' + item.currency + item.total" :value="item.id"> </el-option>
  45. </el-select>
  46. </el-form-item>
  47. </el-col>
  48. <el-col :span="6" v-if="formData.data.type === '3'">
  49. <el-form-item label=" ">
  50. <el-button type="primary" @click="clickPrint" text>查看</el-button>
  51. </el-form-item>
  52. </el-col>
  53. </el-row>
  54. <el-row>
  55. <el-col :span="6">
  56. <el-form-item label="用款时间" prop="paymentTime">
  57. <el-date-picker v-model="formData.data.paymentTime" type="datetime" placeholder="请选择" value-format="YYYY-MM-DD HH:mm:ss" />
  58. </el-form-item>
  59. </el-col>
  60. </el-row>
  61. <el-form-item label="用款说明" prop="paymentRemarks">
  62. <el-input v-model="formData.data.paymentRemarks" placeholder="请输入" type="textarea"> </el-input>
  63. </el-form-item>
  64. <el-form-item label="上传附件">
  65. <div style="width: 100%">
  66. <el-upload
  67. v-model:fileList="fileList"
  68. action="https://winfaster.obs.cn-south-1.myhuaweicloud.com"
  69. :data="uploadData"
  70. multiple
  71. :before-upload="handleBeforeUpload"
  72. :on-success="handleSuccess"
  73. :on-preview="onPreviewFile">
  74. <el-button>选择</el-button>
  75. </el-upload>
  76. </div>
  77. </el-form-item>
  78. <div class="_t">请款明细</div>
  79. <el-form-item>
  80. <el-button type="primary" @click="handleAddRow" v-if="formData.data.type !== '3'" style="margin: 10px 0"> 添加行 </el-button>
  81. <el-table :data="formData.data.accountRequestFundsDetailList">
  82. <el-table-column prop="count" label="费用类型" min-width="150">
  83. <template #default="{ row, $index }">
  84. <el-form-item :prop="'accountRequestFundsDetailList.' + $index + '.costType'" :rules="rules.costType" :inline-message="true">
  85. <el-select v-model="row.costType" placeholder="请选择" filterable style="width: 100%">
  86. <el-option v-for="item in fundsCostType" :label="item.dictValue" :value="item.dictKey"> </el-option>
  87. </el-select>
  88. </el-form-item>
  89. </template>
  90. </el-table-column>
  91. <el-table-column prop="count" label="关联合同" min-width="150">
  92. <template #default="{ row, $index }">
  93. <el-form-item :prop="'accountRequestFundsDetailList.' + $index + '.contractId'" :rules="rules.contractId" :inline-message="true">
  94. <el-select v-model="row.contractId" placeholder="请选择" filterable style="width: 100%">
  95. <el-option v-for="item in contractList" :label="item.code" :value="item.id"> </el-option>
  96. </el-select>
  97. </el-form-item>
  98. </template>
  99. </el-table-column>
  100. <el-table-column prop="count" label="款项说明" min-width="150">
  101. <template #default="{ row, $index }">
  102. <el-form-item :prop="'accountRequestFundsDetailList.' + $index + '.remarks'" :rules="rules.remarks" :inline-message="true">
  103. <el-input v-model="row.remarks" placeholder="请输入" type="textarea" />
  104. </el-form-item>
  105. </template>
  106. </el-table-column>
  107. <el-table-column prop="advanceAmount" label="预支金额" width="120" v-if="formData.data.type === '3'" />
  108. <el-table-column prop="amount" :label="formData.data.type !== '3' ? '请款金额' : '核销金额'" min-width="150">
  109. <template #default="{ row, $index }">
  110. <el-form-item :prop="'accountRequestFundsDetailList.' + $index + '.amount'" :rules="rules.amount" :inline-message="true">
  111. <el-input-number
  112. onmousewheel="return false;"
  113. v-model="row.amount"
  114. :precision="2"
  115. :controls="false"
  116. :min="0"
  117. style="width: 100%"
  118. @change="handleChangeAmount" />
  119. </el-form-item>
  120. </template>
  121. </el-table-column>
  122. <el-table-column prop="zip" label="操作" width="100" v-if="formData.data.type !== '3'">
  123. <template #default="{ $index }">
  124. <el-button type="primary" link @click="handleRemove($index)">删除</el-button>
  125. </template>
  126. </el-table-column>
  127. </el-table>
  128. </el-form-item>
  129. <el-row :gutter="10">
  130. <el-col :span="6" v-if="formData.data.type === '3'">
  131. <el-form-item label="预支总额" prop="advanceAmounts">
  132. <el-input v-model="formData.data.advanceAmounts" placeholder="请输入" disabled />
  133. </el-form-item>
  134. </el-col>
  135. <el-col :span="6">
  136. <el-form-item :label="formData.data.type !== '3' ? '请款总额' : '核销总额'" prop="total">
  137. <el-input v-model="formData.data.total" placeholder="请输入" disabled />
  138. </el-form-item>
  139. </el-col>
  140. <el-col :span="6">
  141. <el-form-item label="单据数量" prop="quantity">
  142. <el-input-number
  143. onmousewheel="return false;"
  144. v-model="formData.data.quantity"
  145. placeholder="请输入"
  146. style="width: 100%"
  147. :precision="0"
  148. :controls="false"
  149. :min="0" />
  150. </el-form-item>
  151. </el-col>
  152. </el-row>
  153. <div class="_t">收付款信息</div>
  154. <el-row :gutter="10">
  155. <el-col :span="6">
  156. <el-form-item label="付款方式" prop="paymentMethod">
  157. <el-select v-model="formData.data.paymentMethod" placeholder="请选择" filterable style="width: 100%">
  158. <el-option v-for="item in fundsPaymentMethod" :label="item.dictValue" :value="item.dictKey"> </el-option>
  159. </el-select>
  160. </el-form-item>
  161. </el-col>
  162. <el-col :span="6">
  163. <el-form-item label="付款账户" prop="accountManagementId">
  164. <el-select v-model="formData.data.accountManagementId" placeholder="请选择" filterable style="width: 100%">
  165. <el-option v-for="item in accountData" :label="item.alias" :value="item.id"> </el-option>
  166. </el-select>
  167. </el-form-item>
  168. </el-col>
  169. </el-row>
  170. <el-row :gutter="10">
  171. <el-col :span="6">
  172. <el-form-item label="户名" prop="name">
  173. <el-input v-model="formData.data.name" placeholder="请输入" />
  174. </el-form-item>
  175. </el-col>
  176. <el-col :span="6">
  177. <el-form-item label="银行账号" prop="accountOpening">
  178. <el-input v-model="formData.data.accountOpening" placeholder="请输入" />
  179. </el-form-item>
  180. </el-col>
  181. </el-row>
  182. <el-row :gutter="10">
  183. <el-col :span="6">
  184. <el-form-item label="开户银行" prop="openingBank">
  185. <el-input v-model="formData.data.openingBank" placeholder="请输入" />
  186. </el-form-item>
  187. </el-col>
  188. <el-col :span="6">
  189. <el-form-item label="联行号 / SWIFT Code" prop="interbankNumber">
  190. <el-input v-model="formData.data.interbankNumber" placeholder="请输入" />
  191. </el-form-item>
  192. </el-col>
  193. </el-row>
  194. </el-form>
  195. <el-dialog title="查看" v-if="openPrint" v-model="openPrint" width="840px">
  196. <div id="pdfDom" style="width: 776px">
  197. <div style="padding: 60px 30px; font-size: 12px !important; color: black">
  198. <div style="font-size: 16px; text-align: center; padding: 8px">
  199. <span>{{ dictDataEcho(printDetails.type, fundsType) }}审批单</span>
  200. </div>
  201. <div style="padding: 8px 0">
  202. <span>{{ printDetails.corporationName }}</span>
  203. <span style="padding-left: 32px">创建时间: {{ printDetails.createTime }}</span>
  204. </div>
  205. <div style="border: 1px solid black">
  206. <div style="display: flex; border-bottom: 1px solid black">
  207. <div style="width: 126px; border-right: 1px solid black; padding: 8px">创建人</div>
  208. <div style="width: calc(100% - 126px); padding: 8px">
  209. {{ dictValueLabel(printDetails.createUser, userList) }}
  210. </div>
  211. </div>
  212. <div style="display: flex; border-bottom: 1px solid black">
  213. <div style="width: 126px; border-right: 1px solid black; padding: 8px">创建人部门</div>
  214. <div style="width: calc(100% - 126px); padding: 8px">
  215. {{ printDetails.deptName }}
  216. </div>
  217. </div>
  218. <div style="display: flex; border-bottom: 1px solid black" v-if="printDetails.type !== '3'">
  219. <div style="width: 126px; border-right: 1px solid black; padding: 4px 8px; display: flex; align-items: center">费用明细</div>
  220. <div style="width: calc(100% - 126px)">
  221. <div style="border-bottom: 1px solid black; display: flex">
  222. <div style="width: 80px; padding: 4px 8px; border-right: 1px solid black; text-align: center">费用类型</div>
  223. <div style="width: 120px; padding: 4px 8px; border-right: 1px solid black; text-align: center">关联合同</div>
  224. <div style="width: calc(100% - 360px); padding: 4px 8px; border-right: 1px solid black; text-align: center">款项说明</div>
  225. <div style="width: 60px; padding: 4px 8px; border-right: 1px solid black; text-align: center">货币</div>
  226. <div style="width: 100px; padding: 4px 8px; text-align: center">付款金额</div>
  227. </div>
  228. <template v-if="printDetails.accountRequestFundsDetailList && printDetails.accountRequestFundsDetailList.length > 0">
  229. <div v-for="(item, index) in printDetails.accountRequestFundsDetailList" :key="index">
  230. <div
  231. :style="
  232. index + 1 !== printDetails.accountRequestFundsDetailList.length ? 'border-bottom: 1px solid black; display: flex' : ' display: flex'
  233. ">
  234. <div style="width: 80px; padding: 4px 8px; border-right: 1px solid black; text-align: center">
  235. {{ dictDataEcho(item.costType, fundsCostType) }}
  236. </div>
  237. <div style="width: 120px; padding: 4px 8px; border-right: 1px solid black; display: flex; align-items: center">
  238. {{ item.contractCode }}
  239. </div>
  240. <div style="width: calc(100% - 360px); padding: 4px 8px; border-right: 1px solid black; display: flex; align-items: center">
  241. {{ item.remarks }}
  242. </div>
  243. <div style="width: 60px; padding: 4px 8px; border-right: 1px solid black; display: flex; align-items: center">
  244. {{ dictDataEcho(printDetails.currency, currencyType) }}
  245. </div>
  246. <div style="width: 100px; padding: 4px 8px; display: flex; align-items: center">
  247. {{ item.amount }}
  248. </div>
  249. </div>
  250. </div>
  251. </template>
  252. </div>
  253. </div>
  254. <div style="display: flex; border-bottom: 1px solid black" v-else>
  255. <div style="width: 126px; border-right: 1px solid black; padding: 4px 8px; display: flex; align-items: center">费用明细</div>
  256. <div style="width: calc(100% - 126px)">
  257. <div style="border-bottom: 1px solid black; display: flex">
  258. <div style="width: 80px; padding: 4px 8px; border-right: 1px solid black; text-align: center">费用类型</div>
  259. <div style="width: 120px; padding: 4px 8px; border-right: 1px solid black; text-align: center">关联合同</div>
  260. <div style="width: calc(100% - 420px); padding: 4px 8px; border-right: 1px solid black; text-align: center">款项说明</div>
  261. <div style="width: 60px; padding: 4px 8px; border-right: 1px solid black; text-align: center">货币</div>
  262. <div style="width: 80px; padding: 4px 8px; border-right: 1px solid black; text-align: center">预支金额</div>
  263. <div style="width: 80px; padding: 4px 8px; text-align: center">付款金额</div>
  264. </div>
  265. <template v-if="printDetails.accountRequestFundsDetailList && printDetails.accountRequestFundsDetailList.length > 0">
  266. <div v-for="(item, index) in printDetails.accountRequestFundsDetailList" :key="index">
  267. <div
  268. :style="
  269. index + 1 !== printDetails.accountRequestFundsDetailList.length ? 'border-bottom: 1px solid black; display: flex' : ' display: flex'
  270. ">
  271. <div style="width: 80px; padding: 4px 8px; border-right: 1px solid black; text-align: center">
  272. {{ dictDataEcho(item.costType, fundsCostType) }}
  273. </div>
  274. <div style="width: 120px; padding: 4px 8px; border-right: 1px solid black; display: flex; align-items: center">
  275. {{ item.contractCode }}
  276. </div>
  277. <div style="width: calc(100% - 420px); padding: 4px 8px; border-right: 1px solid black; display: flex; align-items: center">
  278. {{ item.remarks }}
  279. </div>
  280. <div style="width: 60px; padding: 4px 8px; border-right: 1px solid black; display: flex; align-items: center">
  281. {{ dictDataEcho(printDetails.currency, currencyType) }}
  282. </div>
  283. <div style="width: 80px; padding: 4px 8px; border-right: 1px solid black; display: flex; align-items: center">
  284. {{ item.advanceAmount }}
  285. </div>
  286. <div style="width: 80px; padding: 4px 8px; display: flex; align-items: center">
  287. {{ item.amount }}
  288. </div>
  289. </div>
  290. </div>
  291. </template>
  292. </div>
  293. </div>
  294. <div style="display: flex; border-bottom: 1px solid black" v-if="printDetails.type !== '3'">
  295. <div style="width: 126px; border-right: 1px solid black; padding: 8px">总报销金额</div>
  296. <div style="width: calc(100% - 126px); display: flex">
  297. <div style="width: calc(100% - 100px); padding: 8px; border-right: 1px solid black">{{ NumberToChinese(computeMoney("amount")) }}</div>
  298. <div style="width: 100px; padding: 8px">{{ computeMoney("amount") }}</div>
  299. </div>
  300. </div>
  301. <div v-else>
  302. <div style="display: flex; border-bottom: 1px solid black">
  303. <div style="display: flex; border-bottom: 1px solid black">
  304. <div style="width: 126px; border-right: 1px solid black; padding: 8px">核销总金额</div>
  305. <div style="width: calc(100% - 126px); display: flex">
  306. <div style="width: calc(100% - 100px); padding: 8px; border-right: 1px solid black">{{ NumberToChinese(computeMoney("amount")) }}</div>
  307. <div style="width: 100px; padding: 8px">{{ computeMoney("amount") }}</div>
  308. </div>
  309. </div>
  310. <div style="width: 126px; border-right: 1px solid black; padding: 8px">预支总金额</div>
  311. <div style="width: calc(100% - 126px); display: flex">
  312. <div style="width: calc(100% - 100px); padding: 8px; border-right: 1px solid black">{{ NumberToChinese(computeMoney("advanceAmount")) }}</div>
  313. <div style="width: 100px; padding: 8px">{{ computeMoney("advanceAmount") }}</div>
  314. </div>
  315. </div>
  316. <div style="display: flex; border-bottom: 1px solid black">
  317. <div style="width: 126px; border-right: 1px solid black; padding: 8px">差额 (核销 - 预支)</div>
  318. <div style="width: calc(100% - 126px); display: flex">
  319. <div style="width: calc(100% - 100px); padding: 8px; border-right: 1px solid black">{{ NumberToChinese(computeBalance()) }}</div>
  320. <div style="width: 100px; padding: 8px">{{ computeBalance() }}</div>
  321. </div>
  322. </div>
  323. </div>
  324. <div style="display: flex; border-bottom: 1px solid black">
  325. <div style="width: 126px; border-right: 1px solid black; padding: 8px">单据数量</div>
  326. <div style="width: calc(100% - 126px); padding: 8px">
  327. {{ printDetails.quantity }}
  328. </div>
  329. </div>
  330. <div style="display: flex; border-bottom: 1px solid black">
  331. <div style="width: 126px; border-right: 1px solid black; padding: 0 8px; display: flex; align-items: center">收款信息</div>
  332. <div style="width: calc(100% - 126px)">
  333. <div style="border-bottom: 1px solid black; display: flex">
  334. <div style="width: 19%; padding: 0 8px; border-right: 1px solid black; text-align: center">支付方式</div>
  335. <div style="width: 27%; padding: 0 8px; border-right: 1px solid black; text-align: center">收款方户名</div>
  336. <div style="width: 27%; padding: 0 8px; border-right: 1px solid black; text-align: center">开户行</div>
  337. <div style="width: 27%; padding: 0 8px; text-align: center">收款方账号</div>
  338. </div>
  339. <div style="display: flex">
  340. <div style="width: 19%; padding: 0 8px; border-right: 1px solid black; display: flex; align-items: center">
  341. {{ dictDataEcho(printDetails.paymentMethod, fundsPaymentMethod) }}
  342. </div>
  343. <div style="width: 27%; padding: 0 8px; border-right: 1px solid black; display: flex; align-items: center">
  344. {{ printDetails.name }}
  345. </div>
  346. <div style="width: 27%; padding: 0 8px; border-right: 1px solid black; display: flex; align-items: center">
  347. {{ printDetails.openingBank }}
  348. </div>
  349. <div style="width: 27%; padding: 0 8px; display: flex; align-items: center">
  350. {{ printDetails.accountOpening }}
  351. </div>
  352. </div>
  353. </div>
  354. </div>
  355. <div style="display: flex; border-bottom: 1px solid black">
  356. <div style="width: 126px; border-right: 1px solid black; padding: 8px">电子发票(PDF/JPG)</div>
  357. <div style="width: calc(100% - 126px); padding: 8px">{{ printDetails.electronicInvoiceText }}</div>
  358. </div>
  359. <div style="display: flex">
  360. <div style="width: 126px; border-right: 1px solid black; padding: 4px 8px; display: flex; align-items: center">审批流程</div>
  361. <div style="width: calc(100% - 126px)">
  362. <template v-if="printDetails.recordList && printDetails.recordList.length > 0">
  363. <div v-for="(item, index) in printDetails.recordList" :key="index">
  364. <div
  365. :style="
  366. index + 1 !== printDetails.recordList.length
  367. ? 'border-bottom: 1px solid black; padding: 4px 8px; display: flex'
  368. : 'padding: 4px 8px; display: flex'
  369. ">
  370. <div style="width: calc(100% - 120px); word-wrap: break-word">
  371. <span>{{ item.nodeName }}: </span>
  372. <span style="padding-left: 4px">{{ item.processedUser }}</span>
  373. <span style="padding-left: 4px">{{ item.remark }}</span>
  374. </div>
  375. <div style="width: 120px">{{ item.processedDate }}</div>
  376. </div>
  377. </div>
  378. </template>
  379. </div>
  380. </div>
  381. </div>
  382. <div style="padding-top: 16px">
  383. <span>打印时间: {{ presentTime }}</span>
  384. <span style="padding-left: 32px">打印人: {{ useUserStore().user.nickName }}</span>
  385. </div>
  386. </div>
  387. </div>
  388. <template #footer>
  389. <el-button @click="openPrint = false" size="large">取消</el-button>
  390. <el-button type="primary" @click="clickDownload()" size="large">下载PDF</el-button>
  391. </template>
  392. </el-dialog>
  393. </div>
  394. </template>
  395. <script setup>
  396. import { ElMessage } from "element-plus";
  397. import useUserStore from "@/store/modules/user";
  398. import { useRoute } from "vue-router";
  399. import moment from "moment";
  400. const route = useRoute();
  401. const { proxy } = getCurrentInstance();
  402. const defaultProps = {
  403. children: "children",
  404. label: "deptName",
  405. };
  406. const userList = ref([]);
  407. const formData = reactive({
  408. data: {
  409. paymentTime: "",
  410. accountRequestFundsDetailList: [],
  411. fileList: [],
  412. },
  413. });
  414. let rules = ref({
  415. corporationId: [{ required: true, message: "请选择归属公司", trigger: "change" }],
  416. departmentId: [{ required: true, message: "请选择归属部门", trigger: "change" }],
  417. type: [{ required: true, message: "请选择请款类型", trigger: "change" }],
  418. // paymentTime: [{ required: true, message: "请选择用款时间", trigger: "change" }],
  419. currency: [{ required: true, message: "请选择币种", trigger: "change" }],
  420. paymentMethod: [{ required: true, message: "请选择付款方式", trigger: "change" }],
  421. advanceId: [{ required: true, message: "请选择关联预支", trigger: "change" }],
  422. // accountManagementId: [
  423. // { required: true, message: "请选择付款账号", trigger: "change" },
  424. // ],
  425. costType: [{ required: true, message: "请选择费用类型", trigger: "change" }],
  426. remarks: [{ required: true, message: "请输入款项说明", trigger: "blur" }],
  427. amount: [{ required: true, message: "请输入请款金额", trigger: "blur" }],
  428. });
  429. const handleAddRow = () => {
  430. formData.data.accountRequestFundsDetailList.push({
  431. costType: "",
  432. remarks: "",
  433. amount: undefined,
  434. });
  435. };
  436. const handleRemove = (index) => {
  437. formData.data.accountRequestFundsDetailList.splice(index, 1);
  438. handleChangeAmount();
  439. };
  440. // 提交方法
  441. const formDom = ref(null);
  442. const handleSubmit = async () => {
  443. let status = await formDom.value.validate();
  444. if (status) {
  445. if (fileList.value && fileList.value.length > 0) {
  446. for (let i = 0; i < fileList.value.length; i++) {
  447. if (fileList.value[i].raw.uploadState) {
  448. ElMessage("文件上传中,请稍后提交");
  449. return false;
  450. }
  451. }
  452. formData.data.fileList = fileList.value.map((item) => {
  453. return {
  454. id: item.raw.id,
  455. fileName: item.raw.fileName,
  456. fileUrl: item.raw.fileUrl,
  457. uploadState: item.raw.uploadState,
  458. };
  459. });
  460. } else {
  461. formData.data.fileList = [];
  462. }
  463. if (!(formData.data.accountRequestFundsDetailList.length > 0)) {
  464. ElMessage("请添加请款明细!");
  465. return false;
  466. }
  467. for (let i = 0; i < formData.data.accountRequestFundsDetailList.length; i++) {
  468. if (!formData.data.accountRequestFundsDetailList[i].amount || Number(formData.data.accountRequestFundsDetailList[i].amount) === 0) {
  469. ElMessage("请款金额不能为0");
  470. return false;
  471. }
  472. }
  473. return true;
  474. } else {
  475. setTimeout(() => {
  476. const errorDiv = document.getElementsByClassName("is-error");
  477. errorDiv[0].scrollIntoView();
  478. }, 0);
  479. }
  480. return status;
  481. };
  482. // 获取用户信息并赋默认值
  483. const userInfo = useUserStore().user;
  484. // const tenantId = "@福建宏星!#¥%……&*()";
  485. const tenantId = userInfo.tenantId;
  486. watch(
  487. props.queryData,
  488. () => {
  489. if (props.queryData && (route.query.processType == 10 || route.query.processType == 20)) {
  490. for (var text in props.queryData) {
  491. formData.data[text] = props.queryData[text];
  492. }
  493. oldType.value = proxy.deepClone(formData.data.type);
  494. if (formData.data.fileList && formData.data.fileList.length > 0) {
  495. fileList.value = formData.data.fileList.map((item) => {
  496. return {
  497. raw: item,
  498. name: item.fileName,
  499. url: item.fileUrl,
  500. };
  501. });
  502. }
  503. }
  504. },
  505. {
  506. deep: true,
  507. }
  508. );
  509. onMounted(() => {
  510. formData.data.paymentTime = proxy.parseTime(new Date());
  511. });
  512. const companyData = ref([]);
  513. const accountData = ref([]);
  514. const deptTreeData = ref([]);
  515. const fundsType = ref([]);
  516. const fundsCostType = ref([]);
  517. const fundsPaymentMethod = ref([]);
  518. const currencyType = ref([]);
  519. const advanceList = ref([]);
  520. const contractList = ref([]);
  521. const getDictData = () => {
  522. // 获取归属公司数据
  523. proxy.post("/corporation/page", { pageNum: 1, pageSize: 9999 }).then((res) => {
  524. companyData.value = res.rows;
  525. });
  526. // 账户数据
  527. proxy.post("/accountManagement/page", { pageNum: 1, pageSize: 9999 }).then((res) => {
  528. accountData.value = res.rows;
  529. });
  530. // 关联合同
  531. proxy.post("/contract/page", { pageNum: 1, pageSize: 9999 }).then((res) => {
  532. contractList.value = res.rows;
  533. });
  534. // 部门树
  535. proxy
  536. .get("/tenantDept/list", {
  537. pageNum: 1,
  538. pageSize: 9999,
  539. tenantId: userInfo.tenantId,
  540. })
  541. .then((message) => {
  542. recursive(message.data);
  543. deptTreeData.value = [];
  544. let data = proxy.handleTree(message.data, "deptId");
  545. if (data && data.length > 0) {
  546. for (let i = 0; i < data.length; i++) {
  547. if (data[i].children && data[i].children.length > 0) {
  548. deptTreeData.value = deptTreeData.value.concat(data[i].children);
  549. }
  550. }
  551. }
  552. });
  553. // 请款类型数据
  554. proxy
  555. .post("/dictTenantData/page", {
  556. pageNum: 1,
  557. pageSize: 999,
  558. tenantId: tenantId,
  559. dictCode: "founds_type",
  560. })
  561. .then((res) => {
  562. fundsType.value = res.rows;
  563. });
  564. // 请款费用类型数据
  565. proxy
  566. .post("/dictTenantData/page", {
  567. pageNum: 1,
  568. pageSize: 999,
  569. tenantId: tenantId,
  570. dictCode: "funds_cost_type",
  571. })
  572. .then((res) => {
  573. fundsCostType.value = res.rows;
  574. });
  575. // 请款付款方式数据
  576. proxy
  577. .post("/dictTenantData/page", {
  578. pageNum: 1,
  579. pageSize: 999,
  580. tenantId: tenantId,
  581. dictCode: "funds_payment_method",
  582. })
  583. .then((res) => {
  584. fundsPaymentMethod.value = res.rows;
  585. });
  586. // 币种数据
  587. proxy
  588. .post("/dictTenantData/page", {
  589. pageNum: 1,
  590. pageSize: 999,
  591. tenantId: tenantId,
  592. dictCode: "account_currency",
  593. })
  594. .then((res) => {
  595. currencyType.value = res.rows;
  596. });
  597. proxy
  598. .post("/accountRequestFunds/page", {
  599. pageNum: 1,
  600. pageSize: 999,
  601. type: "1",
  602. writeOffStatus: "0",
  603. })
  604. .then((res) => {
  605. advanceList.value = res.rows;
  606. });
  607. proxy
  608. .get("/tenantUser/list", {
  609. pageNum: 1,
  610. pageSize: 10000,
  611. tenantId: useUserStore().user.tenantId,
  612. })
  613. .then((res) => {
  614. if (res.rows && res.rows.length > 0) {
  615. userList.value = res.rows.map((item) => {
  616. return {
  617. deptId: item.deptId,
  618. label: item.nickName,
  619. value: item.userId,
  620. };
  621. });
  622. }
  623. });
  624. };
  625. getDictData();
  626. const recursive = (data) => {
  627. data.map((item) => {
  628. item.label = item.deptName;
  629. item.id = item.corporationId;
  630. if (item.children) {
  631. recursive(item.children);
  632. } else {
  633. item.children = [];
  634. }
  635. });
  636. };
  637. // 接收父组件的传值
  638. const props = defineProps({
  639. queryData: String,
  640. });
  641. // 计算请款总金额
  642. const handleChangeAmount = () => {
  643. let sum = 0;
  644. for (let i = 0; i < formData.data.accountRequestFundsDetailList.length; i++) {
  645. const e = formData.data.accountRequestFundsDetailList[i];
  646. if (e.amount) {
  647. sum = Number(parseFloat(Number(sum) + Number(e.amount)).toFixed(2))
  648. }
  649. }
  650. formData.data.total = sum;
  651. };
  652. // 上传附件
  653. const uploadData = ref({});
  654. const fileList = ref([]);
  655. const handleBeforeUpload = async (file) => {
  656. const res = await proxy.post("/fileInfo/getSing", { fileName: file.name });
  657. uploadData.value = res.uploadBody;
  658. file.id = res.id;
  659. file.fileName = res.fileName;
  660. file.fileUrl = res.fileUrl;
  661. file.uploadState = true;
  662. return true;
  663. };
  664. const handleSuccess = (any, UploadFile) => {
  665. UploadFile.raw.uploadState = false;
  666. };
  667. const onPreviewFile = (file) => {
  668. window.open(file.raw.fileUrl, "_blank");
  669. };
  670. const getFormData = () => {
  671. return formData.data;
  672. };
  673. // 向父组件暴露
  674. defineExpose({
  675. getFormData,
  676. handleSubmit,
  677. });
  678. const judgeStatus = () => {
  679. if (props.queryData.recordList && props.queryData.recordList.length > 0) {
  680. let data = props.queryData.recordList.filter((item) => item.status === 2 && item.nodeType !== 1);
  681. if (data && data.length > 0) {
  682. return true;
  683. }
  684. }
  685. return false;
  686. };
  687. const oldType = ref("");
  688. const changeType = () => {
  689. if (formData.data.type === "3" || oldType.value === "3") {
  690. for (var text in formData.data) {
  691. if (text === "advanceId") {
  692. formData.data.advanceId = "";
  693. } else if (text === "corporationId") {
  694. formData.data.corporationId = proxy.deepClone(formData.data.corporationId);
  695. } else if (text === "type") {
  696. formData.data.type = proxy.deepClone(formData.data.type);
  697. } else if (text === "paymentTime") {
  698. formData.data.paymentTime = proxy.deepClone(formData.data.paymentTime);
  699. } else if (text === "accountRequestFundsDetailList") {
  700. formData.data.accountRequestFundsDetailList = [];
  701. } else if (text === "fileList") {
  702. formData.data.fileList = [];
  703. } else {
  704. delete formData.data[text];
  705. }
  706. }
  707. }
  708. oldType.value = proxy.deepClone(formData.data.type);
  709. };
  710. const openPrint = ref(false);
  711. const printDetails = ref({});
  712. const presentTime = ref("");
  713. const changeAdvanceId = (val) => {
  714. if (val) {
  715. proxy.post("/accountRequestFunds/detail", { id: val }).then((res) => {
  716. printDetails.value = res;
  717. if (res.flowInfoId) {
  718. proxy.post("/flowExample/getApprovalRecord", { id: res.flowInfoId }).then((record) => {
  719. printDetails.value.recordList = record.recordList;
  720. });
  721. }
  722. formData.data.departmentId = res.departmentId;
  723. formData.data.currency = res.currency;
  724. formData.data.paymentRemarks = res.paymentRemarks;
  725. proxy.post("/fileInfo/getList", { businessIdList: [val] }).then((resFile) => {
  726. formData.data.fileList = resFile[val] || [];
  727. if (formData.data.fileList && formData.data.fileList.length > 0) {
  728. fileList.value = formData.data.fileList.map((item) => {
  729. return {
  730. raw: item,
  731. name: item.fileName,
  732. url: item.fileUrl,
  733. };
  734. });
  735. let electronicInvoiceText = "";
  736. for (let i = 0; i < resFile[val].length; i++) {
  737. if (i === 0) {
  738. electronicInvoiceText = resFile[val][0].fileName;
  739. } else {
  740. electronicInvoiceText = electronicInvoiceText + ", " + resFile[val][i].fileName;
  741. }
  742. }
  743. printDetails.value.electronicInvoiceText = electronicInvoiceText;
  744. }
  745. });
  746. formData.data.accountRequestFundsDetailList = res.accountRequestFundsDetailList.map((item) => {
  747. return {
  748. costType: item.costType,
  749. amount: item.amount,
  750. contractId: item.contractId,
  751. advanceAmount: item.amount,
  752. remarks: item.remarks,
  753. };
  754. });
  755. handleChangeAmount();
  756. formData.data.advanceAmounts = res.total;
  757. formData.data.quantity = res.quantity;
  758. formData.data.paymentMethod = res.paymentMethod;
  759. formData.data.accountManagementId = res.accountManagementId;
  760. formData.data.name = res.name;
  761. formData.data.accountOpening = res.accountOpening;
  762. formData.data.openingBank = res.openingBank;
  763. formData.data.interbankNumber = res.interbankNumber;
  764. });
  765. }
  766. };
  767. const clickDownload = () => {
  768. proxy.getPdf("请款PDF文件");
  769. };
  770. const clickPrint = () => {
  771. if (formData.data.advanceId) {
  772. presentTime.value = moment().format("yyyy-MM-DD HH:mm:ss");
  773. openPrint.value = true;
  774. } else {
  775. ElMessage("请选择关联预支");
  776. }
  777. };
  778. const computeMoney = (label) => {
  779. let amount = 0;
  780. if (printDetails.value.accountRequestFundsDetailList && printDetails.value.accountRequestFundsDetailList.length > 0) {
  781. for (let i = 0; i < printDetails.value.accountRequestFundsDetailList.length; i++) {
  782. if (printDetails.value.accountRequestFundsDetailList[i][label]) {
  783. amount = Number(parseFloat(Number(amount) + Number(printDetails.value.accountRequestFundsDetailList[i][label])).toFixed(2));
  784. }
  785. }
  786. }
  787. return amount;
  788. };
  789. const toDx = (n) => {
  790. //阿拉伯数字转换函数
  791. switch (n) {
  792. case "0":
  793. return "零";
  794. case "1":
  795. return "壹";
  796. case "2":
  797. return "贰";
  798. case "3":
  799. return "叁";
  800. case "4":
  801. return "肆";
  802. case "5":
  803. return "伍";
  804. case "6":
  805. return "陆";
  806. case "7":
  807. return "柒";
  808. case "8":
  809. return "捌";
  810. case "9":
  811. return "玖";
  812. }
  813. };
  814. const NumberToChinese = (m) => {
  815. let unit = ["仟", "佰", "拾", "", "仟", "佰", "拾", "", "角", "分", "厘"];
  816. m *= 1000;
  817. m = Number(parseFloat(m).toFixed(0));
  818. m += "";
  819. var x = m.length;
  820. var result = "";
  821. for (var i = 0; i < x; i++) {
  822. if (i == 3) {
  823. result = "元" + result;
  824. } else if (i == 7) {
  825. result = "万" + result;
  826. }
  827. if (m.charAt(x - i - 1) == 0) {
  828. if (i != 0 && i != 1 && i != 2) {
  829. if (result.charAt(0) != "零" && result.charAt(0) != "元" && result.charAt(0) != "万") {
  830. result = "零" + result;
  831. }
  832. }
  833. continue;
  834. }
  835. result = toDx(m.charAt(x - i - 1)) + unit[unit.length - i - 1] + result;
  836. }
  837. result += result.charAt(result.length - 1) == "元" ? "整" : "";
  838. return result;
  839. };
  840. const computeBalance = () => {
  841. let balance = 0;
  842. let advanceAmount = computeMoney("advanceAmount");
  843. let amount = computeMoney("amount");
  844. if (amount) {
  845. balance = Number(amount);
  846. }
  847. if (advanceAmount) {
  848. balance = Number(parseFloat(Number(balance) - Number(advanceAmount)).toFixed(2));
  849. }
  850. return balance;
  851. };
  852. </script>
  853. <style lang="scss" scoped>
  854. ._t {
  855. margin-bottom: 5px;
  856. font-size: 14px;
  857. }
  858. ::v-deep(.el-input-number .el-input__inner) {
  859. text-align: left;
  860. }
  861. </style>