financialAccount.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684
  1. <template>
  2. <div>
  3. <basic-container>
  4. <avue-crud
  5. ref="crud"
  6. :data="data"
  7. :option="option"
  8. :table-loading="loading"
  9. @row-update="rowUpdate"
  10. @row-del="rowDel"
  11. @saveColumn="saveColumn"
  12. @resetColumn="resetColumn"
  13. >
  14. <template slot="menuLeft" slot-scope="{size}">
  15. <el-button type="primary"
  16. icon="el-icon-plus"
  17. size="small"
  18. :loading="submitButton"
  19. @click="entering"
  20. >录入
  21. </el-button>
  22. </template>
  23. <template slot-scope="{row,index}" slot="menu">
  24. <el-button
  25. type="text"
  26. size="small"
  27. icon="el-icon-edit"
  28. @click="rowCell(row,index)"
  29. >{{ row.$cellEdit ? '保存' : '修改' }}
  30. </el-button>
  31. <el-button
  32. type="text"
  33. icon="el-icon-delete"
  34. size="small"
  35. @click="rowDel(row,index)"
  36. >删除</el-button>
  37. </template>
  38. <template slot-scope="{row,index}" slot="corpId">
  39. <span v-if="row.$cellEdit && category != 2" class="required_fields" style="float: left;line-height: 32px">*</span>
  40. <span v-if="row.$cellEdit && category != 2" style="display: flex">
  41. <el-select
  42. v-model="corpId"
  43. placeholder="请选择"
  44. size="small"
  45. style="width:60%"
  46. filterable
  47. >
  48. <el-option
  49. v-for="item in corpOption"
  50. :key="item.id"
  51. :label="item.cname"
  52. :value="item.id"
  53. />
  54. </el-select>
  55. <el-button
  56. icon="el-icon-search"
  57. size="small"
  58. @click="openDialog(row, index, 1)"
  59. ></el-button>
  60. </span>
  61. <span v-else>{{corpsName}}</span>
  62. </template>
  63. <template slot-scope="{row,index}" slot="costType">
  64. <breakdown-select
  65. v-if="row.$cellEdit"
  66. v-model="row.costType"
  67. style="width: 90%"
  68. :configuration="configuration"
  69. @selectValue="(value) => {getFeeValue(row, value)}"
  70. >
  71. </breakdown-select>
  72. <span v-else>{{ row.costName }}</span>
  73. </template>
  74. <template slot-scope="{row,index}" slot="billNo">
  75. <el-select placeholder="请选择"
  76. v-if="row.$cellEdit"
  77. v-model="row.billNo"
  78. size="small"
  79. filterable
  80. allow-create
  81. default-first-option
  82. clearable>
  83. <el-option
  84. v-for="item in row.billNoList"
  85. :key="item"
  86. :label="item"
  87. :value="item"
  88. ></el-option>
  89. </el-select>
  90. <span v-else>{{ row.billNo }}</span>
  91. </template>
  92. <template slot-scope="{row,index}" slot="taxRate">
  93. <el-input
  94. v-model="row.taxRate"
  95. v-if="row.$cellEdit"
  96. size="small"
  97. oninput='this.value=this.value.replace(/[^(\d.)]/g,"").replace(/^(\d+)\.(\d\d\d\d\d\d).*$/, "$1.$2")'
  98. autocomplete="off"
  99. >
  100. <i slot="suffix" style="margin-right: 10px;top:6px">%</i>
  101. </el-input>
  102. <span v-else>{{ row.taxRate }}</span>
  103. </template>
  104. <template slot-scope="{row,index}" slot="currency">
  105. <span v-if="row.$cellEdit" class="required_fields">*</span>
  106. <el-select v-if="row.$cellEdit" v-model="row.currency" size="small" placeholder="请选择" style="width: 90%" @change="currencyChange(row)" clearable filterable>
  107. <el-option v-for="(item,index) in currencyDic" :key="index" :label="item.dictValue" :value="item.dictValue"></el-option>
  108. </el-select>
  109. <span v-else>{{ row.currency }}</span>
  110. </template>
  111. <template slot-scope="{row,index}" slot="unit">
  112. <el-select v-if="row.$cellEdit" v-model="row.unit" size="small" style="width: 90%" placeholder="请选择" clearable filterable>
  113. <el-option v-for="(item,index) in unitDic" :key="index" :label="item.dictValue" :value="item.dictValue"></el-option>
  114. </el-select>
  115. <span v-else>{{ row.unit }}</span>
  116. </template>
  117. <template slot-scope="{row,index}" slot="price">
  118. <el-input-number
  119. v-if="row.$cellEdit"
  120. v-model="row.price"
  121. size="small"
  122. :controls="false"
  123. :precision="2"
  124. @input="amountChange(row)"
  125. style="width: 100%"
  126. />
  127. <span v-else>{{ Number(row.price).toFixed(2) }}</span>
  128. </template>
  129. <template slot-scope="{row,index}" slot="quantity">
  130. <el-input-number
  131. v-if="row.$cellEdit"
  132. v-model="row.quantity"
  133. size="small"
  134. :controls="false"
  135. :precision="0"
  136. @input="amountChange(row)"
  137. style="width: 100%"
  138. />
  139. <span v-else>{{ Number(row.quantity).toFixed(2) }}</span>
  140. </template>
  141. <template slot-scope="{row,index}" slot="amount">
  142. <el-input-number
  143. v-if="row.$cellEdit"
  144. v-model="row.amount"
  145. size="small"
  146. :controls="false"
  147. :precision="2"
  148. style="width: 100%"
  149. />
  150. <span v-else>{{ Number(row.amount).toFixed(2) }}</span>
  151. </template>
  152. </avue-crud>
  153. <div class="dialogButton">
  154. <el-button size="small" :loading="submitButton" @click="$emit('choceFun')">取消</el-button>
  155. <el-button type="primary" size="small" :loading="submitButton" @click="submit()">确定</el-button>
  156. </div>
  157. </basic-container>
  158. <containerTitle v-if="billId" title="历史账单"></containerTitle>
  159. <basic-container v-if="billId">
  160. <avue-crud :option="historyOption"
  161. :data="historyDataList"
  162. ref="historyCrud"
  163. v-model="historyForm"
  164. :page.sync="page"
  165. :table-loading="historyLoading"
  166. @on-load="onLoad">
  167. </avue-crud>
  168. </basic-container>
  169. <el-dialog
  170. title="客户、供应商"
  171. :visible.sync="corpVisible"
  172. width="80%"
  173. top="5vh"
  174. append-to-body
  175. @closed="closeCorp"
  176. class="el-dialogDeep"
  177. v-dialog-drag
  178. >
  179. <span>
  180. <el-row>
  181. <el-col :span="4">
  182. <el-scrollbar>
  183. <basic-container>
  184. <avue-tree
  185. :option="corpTreeOption"
  186. :data="treeData"
  187. @node-click="corpNodeClick"
  188. :style="treeStyle"
  189. />
  190. </basic-container>
  191. </el-scrollbar>
  192. </el-col>
  193. <el-col :span="20">
  194. <avue-crud
  195. :option="KHOption"
  196. :data="corpData"
  197. ref="crud"
  198. :page.sync="corpPage"
  199. :search.sync="corpSearch"
  200. @search-change="corpSearchChange"
  201. @search-reset="corpSearchReset"
  202. @selection-change="selectionChange"
  203. @current-change="corpCurrentChange"
  204. @size-change="corpSizeChange"
  205. @on-load="corpOnLoad"
  206. @tree-load="corpTreeLoad"
  207. @saveColumn="saveColumn"
  208. @resetColumn="resetColumn"
  209. @refresh-change="corpRefreshChange"
  210. :table-loading="dialogLoading"
  211. >
  212. </avue-crud>
  213. </el-col>
  214. </el-row>
  215. </span>
  216. <span slot="footer" class="dialog-footer">
  217. <el-button @click="corpVisible = false">取 消</el-button>
  218. <el-button
  219. type="primary"
  220. @click="importCorp"
  221. :disabled="selectionList.length != 1"
  222. >确 定</el-button
  223. >
  224. </span>
  225. </el-dialog>
  226. </div>
  227. </template>
  228. <script>
  229. import {applyLoan, paymentApply} from "@/api/financialManagement/paymentRequest";
  230. import option from "./config/option.json"
  231. import historyOption from "../bill/config/application.json"
  232. import {getUserInfo} from "@/api/system/user";
  233. import { getBillList } from "@/api/financialManagement/paymentRequest";
  234. import {customerList, getDeptLazyTree} from "@/api/basicData/customerInformation";
  235. import { getDeptLazyTree as getFeeLazyTree, customerList as feeList } from "@/api/basicData/basicFeesDesc";
  236. import corpOption from './config/corpOption.json'
  237. export default {
  238. name: "financialAccount",
  239. props: {
  240. billId:{
  241. type:String
  242. },
  243. billType: {
  244. type: String
  245. },
  246. srcType: {
  247. type: Number,
  248. default: 1,
  249. },
  250. billData: {
  251. type: Object
  252. },
  253. choceFun: {
  254. type: Function
  255. },
  256. arrList: {
  257. type: Array,
  258. default: []
  259. },
  260. checkData: {
  261. type: Object,
  262. default: {
  263. url: null,
  264. pageStatus: null,
  265. pageLabel: null,
  266. checkType: null
  267. },
  268. },
  269. belongCompany: {
  270. type: String,
  271. }
  272. },
  273. data(){
  274. return {
  275. data: [],
  276. corpId:'',
  277. corpsName: '',
  278. option:option,
  279. loading:false,
  280. submitButton:false,
  281. currencyDic:[],
  282. unitDic:[],
  283. configuration: {
  284. multipleChoices: false,
  285. multiple: false,
  286. disabled: true,
  287. searchShow: true,
  288. collapseTags: false,
  289. placeholder: '请点击右边按钮选择',
  290. dicData: []
  291. },
  292. category: '',
  293. historyLoading:false,
  294. historyOption:historyOption,
  295. historyDataList:[],
  296. historyForm:{},
  297. page: {
  298. pageSize: 10,
  299. pagerCount: 1,
  300. total: 0,
  301. },
  302. corpOption: [], //客户
  303. feeOption: [], // 费用
  304. rowData: null,
  305. corpVisible: false,
  306. feeVisible: false,
  307. treeStyle:'height:'+(window.innerHeight - 315)+'px',
  308. corpTreeOption: {
  309. nodeKey: "id",
  310. lazy: true,
  311. addBtn: false,
  312. menu: false,
  313. size: "small",
  314. props: {
  315. labelText: "标题",
  316. label: "title",
  317. value: "value",
  318. children: "children"
  319. }
  320. },
  321. treeCorpId: '',
  322. selectionList: [],
  323. corpPage: {
  324. currentPage: 1,
  325. pageSize: 10,
  326. total: 0
  327. },
  328. corpSearch: {},
  329. dialogLoading: false,
  330. KHOption: corpOption,
  331. corpData: [],
  332. }
  333. },
  334. created() {
  335. this.option.height = window.innerHeight - 240;
  336. this.historyOption.searchShow = false
  337. customerList({
  338. size: 10000,
  339. current: 1
  340. }).then(res => {
  341. // this.corpOption = res.data.data.records? res.data.data.records: [];
  342. if (res.data.data.total > 0) {
  343. this.corpOption = res.data.data.records;
  344. if (Math.ceil(res.data.data.total / 10) > 1) {
  345. for (let i = 2; i <= Math.ceil(res.data.data.total / 10); i++) {
  346. customerList({current: i, size: 10}).then(e => {
  347. this.corpOption = this.corpOption.concat(e.data.data.records);
  348. });
  349. }
  350. }
  351. }
  352. })
  353. this.loading = true;
  354. feeList({size: 10000, current: 1}).then(res => {
  355. this.feeOption = res.data.data.records? res.data.data.records: [];
  356. this.init()
  357. }).finally(() => {
  358. this.loading = false;
  359. })
  360. getUserInfo().then(res=>{
  361. this.category = res.data.data.billType
  362. if (this.category == 2) {
  363. }
  364. })
  365. //币别
  366. this.getWorkDicts("currency").then(res => {
  367. this.currencyDic = res.data.data
  368. })
  369. this.getWorkDicts("unit").then(res => {
  370. this.unitDic = res.data.data
  371. })
  372. },
  373. mounted() {
  374. // this.init()
  375. },
  376. watch:{
  377. billId(val, oldVal) {
  378. if(val != oldVal){
  379. this.onLoad(this.page)
  380. }
  381. },
  382. },
  383. methods:{
  384. init(){
  385. if(this.arrList.length === 0){
  386. this.corpId = this.billData.corpId
  387. this.corpsName = this.billData.corpsName[0].cname
  388. this.feeOption.forEach(item => {
  389. if (this.billData.costType == item.id) {
  390. this.$set(this.billData, 'costName', item.cname)
  391. }
  392. })
  393. this.data.push(this.billData)
  394. }else{
  395. this.billData = this.arrList[0]
  396. this.corpId = this.arrList[0].corpId
  397. this.corpsName = this.arrList[0].corpsName[0].cname
  398. this.arrList.forEach(item=>{
  399. this.feeOption.forEach(e => {
  400. if (item.costType == e.id) {
  401. this.$set(item, 'costName', e.cname)
  402. }
  403. })
  404. this.data.push(item)
  405. })
  406. }
  407. //删除 提单号
  408. if(this.billData.optionType !== "JK"){
  409. this.option.column.forEach(item =>{
  410. if(item.prop === "billNo"){
  411. item.hide = true
  412. }else{
  413. item.hide = false
  414. }
  415. })
  416. }
  417. },
  418. currencyChange(row){
  419. this.currencyDic.forEach(item =>{
  420. if(item.dictValue === row.currency){
  421. row.exchangeRate = item.remark
  422. }
  423. })
  424. },
  425. rowCell(row,index){
  426. // this.$refs.crud.rowCell(row, index)
  427. if (row.$cellEdit == true) {
  428. this.$set(row, '$cellEdit', false)
  429. } else {
  430. this.$set(row, '$cellEdit', true)
  431. }
  432. },
  433. rowDel(row,index){
  434. this.$confirm("确定将选择数据删除?", {
  435. confirmButtonText: "确定",
  436. cancelButtonText: "取消",
  437. type: "warning"
  438. }).then(() => {
  439. this.data.splice(index, 1);
  440. })
  441. },
  442. rowUpdate(row, index, done, loading) {
  443. done(row);
  444. },
  445. entering(){
  446. if(this.data.length !== 0){
  447. //取第一条数据的 合同号 以及客户
  448. let params = {
  449. ...this.billData,
  450. srcOrderno:this.data[0].srcOrderno,
  451. corpId:this.data[0].corpId
  452. }
  453. this.$refs.crud.rowCellAdd(params);
  454. }else{
  455. this.$refs.crud.rowCellAdd(this.billData);
  456. }
  457. },
  458. onLoad(page,params = {}) {
  459. this.historyLoading = true;
  460. params.srcParentId = this.billId
  461. params.flag = 1
  462. getBillList(page.currentPage, page.pageSize,params).then(res=>{
  463. this.historyDataList = res.data.data.records
  464. }).finally(()=>{
  465. this.historyLoading = false;
  466. })
  467. },
  468. submit(){
  469. for(let i = 0;i<this.data.length;i++){
  470. if (this.corpId === (null || "")) {
  471. return this.$message.error(`请输入第${i + 1}行的客户`);
  472. }
  473. if (this.data[i].costType === (null || "")) {
  474. return this.$message.error(`请输入第${i + 1}行的费用名称`);
  475. }
  476. if (this.data[i].accDate === (null || "")) {
  477. return this.$message.error(`请输入第${i + 1}行的合同日期`);
  478. }
  479. if (this.data[i].amount === (null || "")) {
  480. return this.$message.error(`请输入第${i + 1}行的金额`);
  481. }
  482. if (this.data[i].currency === (null || "")) {
  483. return this.$message.error(`请输入第${i + 1}行的币别`);
  484. }
  485. if (this.data[i].exchangeRate === (null || "")) {
  486. return this.$message.error(`请输入第${i + 1}行的汇率`);
  487. }
  488. if (this.data[i].taxRate === (null || "")) {
  489. return this.$message.error(`请输入第${i + 1}行的税率`);
  490. }
  491. }
  492. this.submitButton = true
  493. const itemsList = this.data.map(item => {
  494. item.corpId = this.corpId;
  495. item.tradeType = this.billData.optionType?this.billData.optionType: item.tradeType;
  496. item.srcType = item.srcType? item.srcType: this.srcType;
  497. return item;
  498. })
  499. const params = {
  500. url: this.checkData.url,
  501. pageStatus: this.checkData.pageStatus,
  502. pageLabel: this.checkData.pageLabel,
  503. checkType: this.checkData.checkType,
  504. billType : this.billType,
  505. DC : this.billData.itemType === "采购"?"C":"D", //账单明细会根据D C区分采购 销售搜索
  506. itemsList: itemsList,
  507. belongCompany: this.belongCompany // 所属公司
  508. }
  509. // 采购申请货款 销售申请退款 都会走申请 走审核 => 付款申请
  510. if(this.billType === "申请"){
  511. applyLoan(params).then(res =>{
  512. if(res.data.success){
  513. this.$message.success("操作成功!")
  514. this.$emit("choceFun");
  515. this.$emit("submit")
  516. //跳转付款申请页面
  517. // if(this.$store.getters.pqStatus){
  518. // this.$alert("无法自动跳,因为付费申请页面已存在!", "温馨提示", {
  519. // confirmButtonText: "确定",
  520. // type: 'warning',
  521. // callback: action => {
  522. // }
  523. // });
  524. // }else{
  525. // //关闭一下存在的列表页 跳转
  526. // this.$router.$avueRouter.closeTag('/financialManagement/paymentRequest/index');
  527. // this.$router.push({
  528. // path: "/financialManagement/paymentRequest/index",
  529. // query: {params: res.data.data.id},
  530. // });
  531. // }
  532. }
  533. }).finally(()=>{
  534. this.submitButton = false
  535. })
  536. }
  537. //采购退款结算 销售收款结算 不需申请请核 直接结算 => 结算
  538. if(this.billType === "收费"){
  539. paymentApply(params).then(res=>{
  540. if(res.data.success){
  541. this.$message.success("操作成功!")
  542. this.$emit("choceFun");
  543. this.$emit("submit")
  544. }
  545. }).finally(()=>{
  546. this.submitButton = false
  547. })
  548. }
  549. },
  550. saveColumn(){
  551. },
  552. resetColumn(){
  553. },
  554. amountChange(row) {
  555. if (!row.quantity) {
  556. row.quantity = 0;
  557. }
  558. if (!row.price) {
  559. row.price = 0;
  560. }
  561. row.amount = Number(row.price) * Number(row.quantity)
  562. },
  563. // 客户、费用弹窗
  564. openDialog(row, index, type) {
  565. this.rowData = {
  566. ...row,
  567. index
  568. }
  569. // 1客户 2费用
  570. if (type == 1) {
  571. this.corpTreeOption.treeLoad = function(node, resolve) {
  572. const parentId = node.level === 0 ? 0 : node.data.id;
  573. getDeptLazyTree({
  574. parentId: parentId,
  575. corpType: "KG"
  576. }).then(res => {
  577. resolve(
  578. res.data.data.map(item => {
  579. return {
  580. ...item,
  581. leaf: !item.hasChildren
  582. };
  583. })
  584. );
  585. });
  586. };
  587. this.corpVisible = !this.corpVisible;
  588. } else if (type == 2) {
  589. this.feeVisible = !this.feeVisible;
  590. }
  591. },
  592. selectionChange(list) {
  593. this.selectionList = list;
  594. },
  595. closeCorp() {
  596. this.selectionList = [];
  597. this.treeCorpId = "";
  598. this.reData = null;
  599. },
  600. corpNodeClick(data) {
  601. this.treeCorpId = data.id;
  602. this.corpPage.currentPage = 1;
  603. this.corpOnLoad(this.corpPage);
  604. },
  605. //列表内展开树节点
  606. corpTreeLoad(tree, treeNode, resolve) {
  607. const parentId = tree.id;
  608. customerList({ parentId: parentId }).then(res => {
  609. resolve(res.data.data.records);
  610. });
  611. },
  612. //点击搜索按钮触发
  613. corpSearchChange(params, done) {
  614. this.corpPage.currentPage = 1;
  615. this.corpOnLoad(this.corpPage, params);
  616. done();
  617. },
  618. corpSearchReset() {
  619. this.treeCorpId = null;
  620. },
  621. corpSizeChange(val) {
  622. this.corpPage.pageSize = val;
  623. this.corpOnLoad();
  624. },
  625. corpCurrentChange(val) {
  626. this.corpPage.currentPage = val;
  627. this.corpOnLoad();
  628. },
  629. corpRefreshChange() {
  630. this.corpOnLoad(this.corpPage, this.corpSearch);
  631. },
  632. corpOnLoad(page, params = { parentId: 0 }) {
  633. let queryParams = Object.assign({}, params, {
  634. size: page.pageSize,
  635. current: page.currentPage,
  636. corpsTypeId: this.treeDeptId,
  637. corpType: 'KG'
  638. });
  639. this.dialogLoading = true;
  640. customerList(queryParams)
  641. .then(res => {
  642. this.corpData = res.data.data.records;
  643. this.corpPage.total = res.data.data.total;
  644. if (this.corpPage.total) {
  645. this.KHOption.height = window.innerHeight - 350;
  646. }
  647. })
  648. .finally(() => {
  649. this.dialogLoading = false;
  650. });
  651. },
  652. importCorp() {
  653. this.corpData.forEach((item, index) => {
  654. if (index == this.rowData.index) {
  655. item.corpId = this.selectionList[0].id;
  656. }
  657. })
  658. this.corpVisible = false;
  659. },
  660. getFeeValue(row, value) {
  661. this.$set(row, 'costName', value.cname)
  662. }
  663. }
  664. }
  665. </script>
  666. <style scoped lang="scss">
  667. .required_fields{
  668. color: #F56C6C;
  669. display:inline-block;
  670. width: 7%
  671. }
  672. </style>