applyBudgetingApprove.vue 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998
  1. <template>
  2. <div v-loading="loading" class="budgeting">
  3. <div class="tableBody">
  4. <div class="titBox">
  5. <div class="ysxxBox">
  6. <h4>预算信息</h4>
  7. <span v-show="!isAudit" style="color:#999999">(说明:<span style="color:#E13737;font-size: 20px;">“*”</span>需提交明细附件)</span>
  8. </div>
  9. <div>单位:<span style="color: #684EFF;">元</span></div>
  10. </div>
  11. <div class="table">
  12. <div class="myTh">
  13. <div style="width: 10%;" />
  14. <div style="width: 20%;">项目</div>
  15. <div style="width: 5%;">序号</div>
  16. <div style="width: 15%;">子项</div>
  17. <div style="width: 15%;">预算金额</div>
  18. <div style="width: 15%;">附 件</div>
  19. <div style="width: 10%;">占比销售</div>
  20. <div style="width: 10%;">占比支出</div>
  21. </div>
  22. <div style="position: relative;">
  23. <div
  24. style="height: 100%;width:10%;text-align: center;color:#666666;"
  25. class="firstColum"
  26. >
  27. 成本
  28. </div>
  29. <div
  30. v-for="(item, index) in cbList"
  31. :key="index"
  32. class="feiyong"
  33. >
  34. <div style="width: 20%;;color:#666666 ;" class="myTd">
  35. {{ item.budgetType }}
  36. </div>
  37. <div style="width: 5%;;color:#666666 ;" class="myTd">
  38. {{ item.sortNo }}
  39. </div>
  40. <div style="width: 15%;;color:#666666 ;" class="myTd">
  41. <span
  42. v-show="item.needDetail === '0'"
  43. style="color: red;margin-right: 0.2vw;"
  44. >*</span>
  45. {{ item.budgetChildType }}
  46. </div>
  47. <div style="width: 15%;;color:#666666 ;" class="myTd">
  48. <input
  49. v-model="item.budgetAmount"
  50. placeholder="请填写金额整数"
  51. class="ysje"
  52. @change="handleNumChange"
  53. >
  54. <el-popover
  55. v-if="checkPop(item)"
  56. placement="top-start"
  57. title=""
  58. width="200"
  59. trigger="hover"
  60. >
  61. <div slot="reference">
  62. <i class="el-icon-warning" style="color: red" />
  63. </div>
  64. <span style="color: red">{{ item.content }}</span>
  65. </el-popover>
  66. </div>
  67. <div style="width: 15%;;color:#666666 ;" class="myTd">
  68. <!-- 上传附件 -->
  69. <el-upload
  70. class="upload-demo"
  71. :action="$constant.BASE_URI + '/FileController/upload'"
  72. :http-request="myRequest"
  73. :limit="1"
  74. :file-list="item.file"
  75. :on-remove="onRemove"
  76. >
  77. <img
  78. src="../../../projectDashboard/img/jia.svg"
  79. alt=""
  80. @click="getFileItem(item, index)"
  81. >
  82. <div slot="file" slot-scope="{file}">
  83. <a :href="file.url">{{ file.name }}</a>
  84. <span v-if="!isAudit" class="el-upload-list__item-actions">
  85. <i class="el-icon-delete" @click="handlePictureRemove(file,item.file)" />
  86. </span>
  87. </div>
  88. </el-upload>
  89. <span
  90. v-if="item.file.length === 0 && item.needDetail === '0'"
  91. style="color: #E13737;margin-left: 0.3vw;"
  92. >请上传明细附件</span>
  93. </div>
  94. <div style="width: 10%;;color:#666666 ;" class="myTd">
  95. {{ item.saleRate ? item.saleRate + '%' : '' }}
  96. </div>
  97. <div style="width: 10%;;color:#666666 ;" class="myTd">
  98. {{ item.costRate ? item.costRate + '%' : '' }}
  99. </div>
  100. </div>
  101. </div>
  102. <div class="firstTr feiyong">
  103. <div style="width: 10%;color: #E09F46;">
  104. 成本小计
  105. </div>
  106. <div style="width: 20%;" />
  107. <div style="width: 5%;" class="" />
  108. <div style="width: 15%;" class=" " />
  109. <div
  110. style="width: 15%;color: #E09F46;padding-left: 0.5vw;"
  111. class="sjfsys"
  112. >
  113. <div>
  114. {{ cbhj }}
  115. </div>
  116. </div>
  117. <div style="width: 15%;" />
  118. <div style="width: 10%;" class="sjfsys">
  119. <div>
  120. {{ cbhjSaleRate ? cbhjSaleRate + '%' : '' }}
  121. </div>
  122. </div>
  123. <div style="width: 10%;" class="sjfsys">
  124. <div>
  125. {{ cbhjCostRate ? cbhjCostRate + '%' : '' }}
  126. </div>
  127. </div>
  128. </div>
  129. <div style="position: relative;">
  130. <div
  131. style="height: 100%;width:10%;text-align: center;color:#666666;"
  132. class="firstColum"
  133. >
  134. 费用
  135. </div>
  136. <div
  137. v-for="(item, index) in fyList"
  138. :key="index"
  139. class="feiyong"
  140. >
  141. <!-- <div
  142. style="width: 10%;text-align: center;color:#666666;"
  143. class="firstColum"
  144. ></div> -->
  145. <div style="width: 20%;;color:#666666 ;" class="myTd">
  146. {{ item.budgetType }}
  147. </div>
  148. <div style="width: 5%;;color:#666666 ;" class="myTd">
  149. {{ item.sortNo }}
  150. </div>
  151. <div style="width: 15%;;color:#666666 ;" class="myTd">
  152. <span
  153. v-show="item.needDetail === '0'"
  154. style="color: red;margin-right: 0.2vw;"
  155. >*</span>
  156. {{ item.budgetChildType }}
  157. </div>
  158. <div style="width: 15%;;color:#666666 ;" class="myTd">
  159. <input
  160. v-model="item.budgetAmount"
  161. placeholder="请填写金额整数"
  162. class="ysje"
  163. @change="handleNumChange"
  164. >
  165. <el-popover
  166. v-if="checkPop(item)"
  167. placement="top-start"
  168. title=""
  169. width="200"
  170. trigger="hover"
  171. >
  172. <div slot="reference">
  173. <i class="el-icon-warning" style="color: red" />
  174. </div>
  175. <span style="color: red">{{ item.content }}</span>
  176. </el-popover>
  177. </div>
  178. <div style="width: 15%;;color:#666666 ;" class="myTd">
  179. <!-- 上传附件 -->
  180. <el-upload
  181. class="upload-demo"
  182. :action="$constant.BASE_URI + '/FileController/upload'"
  183. :http-request="fyRequest"
  184. :limit="1"
  185. :file-list="item.file"
  186. :on-remove="fyRemove"
  187. >
  188. <img
  189. src="../../../projectDashboard/img/jia.svg"
  190. alt=""
  191. @click="getfyFileItem(item, index)"
  192. >
  193. <div slot="file" slot-scope="{file}">
  194. <a :href="file.url">{{ file.name }}</a>
  195. <span v-if="!isAudit" class="el-upload-list__item-actions">
  196. <i class="el-icon-delete" @click="handlePictureRemoveFy(file,item.file)" />
  197. </span>
  198. </div>
  199. </el-upload>
  200. <span
  201. v-show="item.file.length === 0 && item.needDetail === '0'"
  202. style="color: #E13737;margin-left: 0.3vw;"
  203. >请上传明细附件</span>
  204. </div>
  205. <div style="width: 10%;;color:#666666 ;" class="myTd">
  206. {{ item.saleRate ? item.saleRate + '%' : '' }}
  207. </div>
  208. <div style="width: 10%;;color:#666666 ;" class="myTd">
  209. {{ item.costRate ? item.costRate + '%' : '' }}
  210. </div>
  211. </div>
  212. </div>
  213. <div class="firstTr feiyong">
  214. <div style="width: 10%;color: #E09F46;">
  215. 费用小计
  216. </div>
  217. <div style="width: 20%;" />
  218. <div style="width: 5%;" class="" />
  219. <div style="width: 15%;" class=" " />
  220. <div
  221. style="width: 15%;color: #E09F46;padding-left: 0.5vw;"
  222. class="sjfsys"
  223. >
  224. <div>
  225. {{ fyhj }}
  226. </div>
  227. </div>
  228. <div style="width: 15%;" />
  229. <div style="width: 10%;" class="sjfsys">
  230. <div>
  231. {{ fyhjSaleRate ? fyhjSaleRate + '%' : '' }}
  232. </div>
  233. </div>
  234. <div style="width: 10%;" class="sjfsys">
  235. <div>
  236. {{ fyhjCostRate ? fyhjCostRate + '%' : '' }}
  237. </div>
  238. </div>
  239. </div>
  240. <div class="firstTr feiyong">
  241. <div style="width: 10%;color: #E09F46;">
  242. 项目支出项总计
  243. </div>
  244. <div style="width: 20%;" />
  245. <div style="width: 5%;" class="" />
  246. <div style="width: 15%;" class=" " />
  247. <div
  248. style="width: 15%;color: #E09F46;padding-left: 0.5vw;"
  249. class="sjfsys"
  250. >
  251. <div>
  252. {{ costAll }}
  253. </div>
  254. </div>
  255. <!-- <div style="width: 15%;" />-->
  256. <!-- <div style="width: 10%;" class="sjfsys">-->
  257. <!-- <div>-->
  258. <!-- {{ profit }}-->
  259. <!-- </div>-->
  260. <!-- </div>-->
  261. <!-- <div style="width: 10%;" class="sjfsys">-->
  262. <!-- <div>-->
  263. <!-- {{ profitRate }}-->
  264. <!-- </div>-->
  265. <!-- </div>-->
  266. </div>
  267. <div class="lirunBox">
  268. <div class="lirun">
  269. <div
  270. style="width: 10%;color: #684EFF;padding-left: 2.5%;font-weight: 600"
  271. >
  272. 项目利润
  273. </div>
  274. <div style="width: 20%;" />
  275. <div style="width: 5%;" />
  276. <div style="width: 15%;" />
  277. <div
  278. style="width: 15%;color: #684EFF;font-size: 0.6vw;font-weight: 600;padding-left: 0.5vw;"
  279. >
  280. {{ profit }}
  281. </div>
  282. <div style="width: 15%;" />
  283. <div style="width: 10%;" />
  284. <div style="width: 10%;" />
  285. </div>
  286. <div class="lurunLine" />
  287. <div class="lirun">
  288. <div
  289. style="width: 10%;color: #684EFF;padding-left: 2.5%;font-weight: 600"
  290. >
  291. 利润率
  292. </div>
  293. <div style="width: 20%;" />
  294. <div style="width: 5%;" />
  295. <div style="width: 15%;" />
  296. <div
  297. style="width: 15%;color: #684EFF;font-size: 0.6vw;font-weight: 600;padding-left: 0.5vw;"
  298. >
  299. {{ profitRate ? profitRate + '%' : '' }}
  300. </div>
  301. <div style="width: 15%;" />
  302. <div style="width: 10%;" />
  303. <div style="width: 10%;" />
  304. </div>
  305. </div>
  306. </div>
  307. </div>
  308. <!-- <div v-show="!isAudit" class="btnBox">-->
  309. <!-- <div class="commit" @click="toClose">关 闭</div>-->
  310. <!-- <div v-if="(proData.realValidStatus === '0' || proData.realValidStatus === '3') && !isDetail" v-loading="loading" class="commit" @click="toSave('0')">暂 存</div>-->
  311. <!-- <div v-if="(proData.realValidStatus === '0' || proData.realValidStatus === '3') && !isDetail" v-loading="loading" class="submit" @click="toSave('1')">保 存</div>-->
  312. <!-- <div v-if="proData.realValidStatus === '2' && !isDetail" class="submit" @click="toApplyChange()">变更申请</div>-->
  313. <!-- </div>-->
  314. </div>
  315. </template>
  316. <script>
  317. import Base from '@/views/base/base.vue'
  318. import axios from 'axios'
  319. import qs from 'qs'
  320. import { upload } from '@/static/utils/channel'
  321. import Constant from '@/static/utils/constant'
  322. import BaseData from '@/views/base/baseData.vue'
  323. import { data } from 'autoprefixer'
  324. export default {
  325. name: 'Budgeting',
  326. mixins: [Base, BaseData],
  327. props: {
  328. proId: {
  329. type: String,
  330. default: ''
  331. },
  332. isDetail: {
  333. type: Boolean,
  334. default: false
  335. },
  336. isAudit: {
  337. type: String,
  338. default: ''
  339. }
  340. },
  341. data() {
  342. return {
  343. dc_key: ['PRO_TYPE'],
  344. proData: {},
  345. loading: false,
  346. fyIndex: '',
  347. fileList: [],
  348. cbIndex: '',
  349. fyList: [],
  350. cbList: [],
  351. cbhj: 0,
  352. cbhjSaleRate: 0,
  353. cbhjCostRate: 0,
  354. fyhj: 0,
  355. fyhjSaleRate: 0,
  356. fyhjCostRate: 0,
  357. costAll: 0,
  358. profit: 0,
  359. profitRate: 0,
  360. hasNewTemplate: false,
  361. dialogApplyVisible: false,
  362. applyTitle: '',
  363. referenceId: '',
  364. auditType: '',
  365. formType: '',
  366. hasF:false,
  367. }
  368. },
  369. methods: {
  370. initData(hasNewTemplate) {
  371. this.hasNewTemplate = hasNewTemplate || false
  372. this.loading = true
  373. this.initProType().then(() => {
  374. this.getProData()
  375. })
  376. },
  377. getProData() {
  378. const _this = this
  379. this.proMainRequest('getDashboardByProId', { proId: this.proId }).then(res => {
  380. this.proData = res.data || {}
  381. this.proData.proTypeName = _this.ProTypeMap[this.proData.proType]
  382. this.getBudgetData()
  383. })
  384. },
  385. getBudgetData() {
  386. if (this.isAudit) {
  387. this.getRecord()
  388. } else {
  389. this.baseRequest('checkRecord', { proId: this.proId }).then(res => {
  390. if (res.data) {
  391. // 有记录 取记录
  392. this.getRecord()
  393. } else {
  394. // 没有记录 取模板
  395. this.getTemplate()
  396. }
  397. })
  398. }
  399. },
  400. getRecord() {
  401. const _this = this
  402. if (_this.hasNewTemplate) {
  403. const postData1 = {
  404. proType: this.proData.proType,
  405. groupId: this.$common.currUser().groupId
  406. }
  407. const postData = {
  408. proId: this.proId,
  409. budgetType: '成本类'
  410. }
  411. const postData2 = {
  412. proId: this.proId,
  413. budgetType: '费用类'
  414. }
  415. Promise.all([
  416. axios({
  417. headers: {
  418. 'MVVM-Key': String(new Date().getTime()),
  419. xx: 'anything'
  420. },
  421. url: _this.$constant.BASE_URI + '/BudgetMakingController/getRecord',
  422. method: 'post',
  423. data: qs.stringify(postData),
  424. withCredentials: true
  425. }).then(res => {
  426. return res
  427. }),
  428. axios({
  429. headers: {
  430. 'MVVM-Key': String(new Date().getTime()),
  431. xx: 'anything'
  432. },
  433. url: _this.$constant.BASE_URI + '/BudgetMakingController/getRecord',
  434. method: 'post',
  435. data: qs.stringify(postData2),
  436. withCredentials: true
  437. }).then(res => {
  438. return res
  439. }),
  440. axios({
  441. headers: {
  442. 'MVVM-Key': String(new Date().getTime()),
  443. xx: 'anything'
  444. },
  445. url: _this.$constant.BASE_URI + '/BudgetTemplateController/getByProTypeEffect',
  446. method: 'post',
  447. data: qs.stringify(postData1),
  448. withCredentials: true
  449. }).then(res => {
  450. return res
  451. })
  452. ]).then(array => {
  453. const templateData1 = array[2].data.record1 || []
  454. const templateData2 = array[2].data.record2 || []
  455. const templateId = array[2].data.id
  456. const data1 = array[0].data || []
  457. const data2 = array[1].data || []
  458. templateData1.forEach(item => {
  459. item.file = []
  460. item.budgetFile = ''
  461. item.id = ''
  462. item.templateId = templateId
  463. const obj = data1.find(x => x.budgetChildType === item.budgetChildType)
  464. if (obj) {
  465. item.id = obj.id
  466. item.budgetAmount = obj.budgetAmount
  467. item.budgetFile = obj.budgetFile
  468. const file = []
  469. if (obj.budgetFile) {
  470. file.push({
  471. id: obj.budgetFile,
  472. name: obj.budgetFileName,
  473. url: _this.$constant.BASE_URI + '/FileController/download/' + obj.budgetFile
  474. })
  475. }
  476. item.file = file
  477. }
  478. })
  479. templateData2.forEach(item => {
  480. item.file = []
  481. item.budgetFile = ''
  482. item.id = ''
  483. item.templateId = templateId
  484. const obj = data2.find(x => x.budgetChildType === item.budgetChildType)
  485. if (obj) {
  486. item.id = obj.id
  487. item.budgetAmount = obj.budgetAmount
  488. item.budgetFile = obj.budgetFile
  489. const file = []
  490. if (obj.budgetFile) {
  491. file.push({
  492. id: obj.budgetFile,
  493. name: obj.budgetFileName,
  494. url: _this.$constant.BASE_URI + '/FileController/download/' + obj.budgetFile
  495. })
  496. }
  497. item.file = file
  498. }
  499. })
  500. this.handleTableData(templateData1, templateData2)
  501. })
  502. } else {
  503. const postData = {
  504. proId: this.proId,
  505. budgetType: '成本类'
  506. }
  507. const postData2 = {
  508. proId: this.proId,
  509. budgetType: '费用类'
  510. }
  511. Promise.all([
  512. axios({
  513. headers: {
  514. 'MVVM-Key': String(new Date().getTime()),
  515. xx: 'anything'
  516. },
  517. url: _this.$constant.BASE_URI + '/BudgetMakingController/getRecord',
  518. method: 'post',
  519. data: qs.stringify(postData),
  520. withCredentials: true
  521. }).then(res => {
  522. return res
  523. }),
  524. axios({
  525. headers: {
  526. 'MVVM-Key': String(new Date().getTime()),
  527. xx: 'anything'
  528. },
  529. url: _this.$constant.BASE_URI + '/BudgetMakingController/getRecord',
  530. method: 'post',
  531. data: qs.stringify(postData2),
  532. withCredentials: true
  533. }).then(res => {
  534. return res
  535. })
  536. ]).then(array => {
  537. const data1 = array[0].data || []
  538. const data2 = array[1].data || []
  539. data1.forEach(item => {
  540. const file = []
  541. if (item.budgetFile) {
  542. file.push({
  543. id: item.budgetFile,
  544. name: item.budgetFileName,
  545. url: _this.$constant.BASE_URI + '/FileController/download/' + item.budgetFile
  546. })
  547. }
  548. item.file = file
  549. })
  550. data2.forEach(item => {
  551. const file = []
  552. if (item.budgetFile) {
  553. file.push({
  554. id: item.budgetFile,
  555. name: item.budgetFileName,
  556. url: _this.$constant.BASE_URI + '/FileController/download/' + item.budgetFile
  557. })
  558. }
  559. item.file = file
  560. })
  561. this.handleTableData(data1, data2)
  562. })
  563. }
  564. },
  565. getTemplate() {
  566. const postData = {
  567. proType: this.proData.proType,
  568. groupId: this.$common.currUser().groupId
  569. }
  570. this.budgetTemplateRequest('getByProTypeEffect', postData).then(res => {
  571. if (res.data) {
  572. const data1 = res.data.record1 || []
  573. const data2 = res.data.record2 || []
  574. const templateId = res.data.id
  575. data1.forEach(item => {
  576. item.file = []
  577. item.budgetFile = ''
  578. item.id = ''
  579. item.templateId = templateId
  580. })
  581. data2.forEach(item => {
  582. item.file = []
  583. item.budgetFile = ''
  584. item.id = ''
  585. item.templateId = templateId
  586. })
  587. this.handleTableData(data1, data2)
  588. } else {
  589. this.loading = false
  590. }
  591. })
  592. },
  593. handleTableData(data1, data2) {
  594. this.cbList = []
  595. this.fyList = []
  596. this.costAll = 0
  597. this.profit = 0
  598. this.profitRate = 0
  599. let pa1 = 0;
  600. let pa2 = 0;
  601. // 销售金额
  602. const saleAmount = this.proData.signStatus === '3' ? parseInt(this.proData.totalAmount || 0) : parseInt(this.proData.preSales || 0)
  603. // 成本小计
  604. let costTotal = 0
  605. data1.forEach(item => {
  606. costTotal += parseInt(item.budgetAmount || 0)
  607. })
  608. // 费用小计
  609. let costTotal2 = 0
  610. data2.forEach(item => {
  611. costTotal2 += parseInt(item.budgetAmount || 0)
  612. })
  613. // 项目支出项总计
  614. const costAll = costTotal + costTotal2
  615. // 项目利润
  616. const profit = saleAmount - costAll
  617. // 利润率
  618. const profitRate = ((profit / saleAmount) * 100).toFixed(2)
  619. // 成本列表
  620. data1.forEach(item => {
  621. if (item.budgetAmount && saleAmount) {
  622. item.saleRate = ((parseInt(item.budgetAmount || 0) / saleAmount) * 100).toFixed(2)
  623. }
  624. if (item.budgetAmount && costAll) {
  625. item.costRate = ((parseInt(item.budgetAmount || 0) / costAll) * 100).toFixed(2)
  626. }
  627. if(item.budgetAmount){
  628. pa1 = pa1+1
  629. }
  630. this.cbList.push(item)
  631. })
  632. // 成本小计
  633. this.cbhj = costTotal
  634. this.cbhjSaleRate = saleAmount ? ((costTotal / saleAmount) * 100).toFixed(2) : 0
  635. this.cbhjCostRate = costAll ? ((costTotal / costAll) * 100).toFixed(2) : 0
  636. // 费用列表
  637. data2.forEach(item => {
  638. if(item.budgetAmount){
  639. pa2= pa2+1
  640. }
  641. if (item.budgetAmount && saleAmount) {
  642. item.saleRate = ((parseInt(item.budgetAmount || 0) / saleAmount) * 100).toFixed(2)
  643. }
  644. if (item.budgetAmount && costAll) {
  645. item.costRate = ((parseInt(item.budgetAmount || 0) / costAll) * 100).toFixed(2)
  646. }
  647. this.fyList.push(item)
  648. })
  649. // 费用小计
  650. this.fyhj = costTotal2
  651. this.fyhjSaleRate = saleAmount ? ((costTotal2 / saleAmount) * 100).toFixed(2) : 0
  652. this.fyhjCostRate = costAll ? ((costTotal2 / costAll) * 100).toFixed(2) : 0
  653. this.costAll = costAll
  654. this.profit = profit
  655. this.profitRate = profitRate
  656. this.loading = false
  657. if(data1.length===pa1&&data2.length===pa2){
  658. this.hasF = false
  659. }else{
  660. this.hasF = true
  661. }
  662. this.$emit('handleInfo',this.hasF)
  663. },
  664. handleNumChange() {
  665. this.handleTableData(this.cbList, this.fyList)
  666. },
  667. getFileItem(item, index) {
  668. this.cbIndex = index
  669. },
  670. getfyFileItem(item, index) {
  671. this.fyIndex = index
  672. },
  673. onRemove(file, fileList) {
  674. const index = this.cbList.findIndex(x => x.budgetFile === file.id)
  675. this.cbList[index].file = []
  676. },
  677. handlePictureRemove: function(file, fileList) {
  678. // console.log(file, fileList)
  679. const index2 = fileList.indexOf(file)
  680. const index = this.cbList.findIndex(x => x.budgetFile === file.id)
  681. fileList.splice(index, 1)
  682. this.cbList[index].budgetFile = ''
  683. this.cbList[index].file = []
  684. },
  685. handlePictureRemoveFy: function(file, fileList) {
  686. // console.log(file, fileList)
  687. const index = this.fyList.findIndex(x => x.budgetFile === file.id)
  688. fileList.splice(index, 1)
  689. this.fyList[index].budgetFile = ''
  690. this.fyList[index].file = []
  691. },
  692. myRequest(param) {
  693. this.loading = true
  694. upload(param, true).then((res) => {
  695. if (res.key === 200) {
  696. this.cbList[this.cbIndex].budgetFile = res.data
  697. this.cbList[this.cbIndex].file.push({ id: res.data, name: res.name, url: res.url })
  698. } else {
  699. this.$message.error('文件上传失败')
  700. }
  701. this.loading = false
  702. })
  703. },
  704. fyRemove(file, fileList) {
  705. const index = this.fyList.findIndex(x => x.budgetFile === file.id)
  706. this.fyList[index].file = []
  707. },
  708. fyRequest(param) {
  709. this.loading = true
  710. upload(param, true).then((res) => {
  711. if (res.key === 200) {
  712. this.fyList[this.fyIndex].budgetFile = res.data
  713. this.fyList[this.fyIndex].file.push({ id: res.data, name: res.name, url: res.url })
  714. } else {
  715. this.$message.error('文件上传失败')
  716. }
  717. this.loading = false
  718. })
  719. },
  720. toApplyChange() {
  721. const _this = this
  722. const postData = {
  723. proId: _this.proId
  724. }
  725. _this.loading = true
  726. _this.baseRequest('checkAudit', postData).then(res => {
  727. _this.loading = false
  728. if (res.data.key === 200) {
  729. this.referenceId = _this.proId
  730. this.auditType = Constant.AUDIT_TYPE.PRO_BUDGET_CHANGE
  731. this.applyTitle = '预算变更申请'
  732. this.formType = 'BudgetChange'
  733. this.dialogApplyVisible = true
  734. } else if (res.data.key === 503) {
  735. _this.$message({
  736. type: 'error',
  737. message: res.data.msg
  738. })
  739. }
  740. })
  741. },
  742. toSave(type) {
  743. const _this = this
  744. const list = []
  745. list.push(..._this.cbList)
  746. list.push(..._this.fyList)
  747. if (type !== '0') {
  748. const obj = list.find(x => x.needDetail === '0' && !x.budgetFile)
  749. if (obj) {
  750. _this.$message({
  751. type: 'warning',
  752. message: '带*号子项需上传附件'
  753. })
  754. return
  755. }
  756. }
  757. if (this.loading) return
  758. this.loading = true
  759. setTimeout(() => {
  760. this.loading = false
  761. }, this.$constant.DATE_PATTERN.OUT_TIME)
  762. const postData = {
  763. list: JSON.stringify(list),
  764. type: type,
  765. userId: _this.$common.currUser().id,
  766. groupId: _this.$common.currUser().groupId,
  767. proId: _this.proId
  768. }
  769. _this.loading = true
  770. _this.baseRequest('addOrEdit', postData).then(res => {
  771. _this.loading = false
  772. if (res.data.key === 200) {
  773. // _this.$message({
  774. // type: 'success',
  775. // message: '提交成功'
  776. // })
  777. // _this.$emit('closeDialog')
  778. } else if (res.data.key === 503) {
  779. _this.$message({
  780. type: 'error',
  781. message: res.data.msg
  782. })
  783. }
  784. })
  785. },
  786. toClose() {
  787. this.$emit('closeDialog')
  788. },
  789. handleApplyClose() {
  790. this.dialogApplyVisible = false
  791. },
  792. handleApplyCommit() {
  793. this.dialogApplyVisible = false
  794. this.toSave('2')
  795. },
  796. checkPop(item) {
  797. console.log(item)
  798. if (item.upperLimit && item.upperLimitValue) {
  799. console.log(item.budgetAmount)
  800. console.log(item.upperLimitValue)
  801. console.log(item.budgetAmount > item.upperLimitValue)
  802. if (item.upperLimit === '定额' && item.budgetAmount > item.upperLimitValue) {
  803. item.content = '该项预算已超出预算设定的定额' + item.upperLimitValue
  804. return true
  805. }
  806. if (item.upperLimit === '占比销售额') {
  807. const all = this.proData.signStatus === '3' ? this.proData.totalAmount : this.proData.preSales
  808. if (((item.budgetAmount / all) * 100).toFixed(2) > item.upperLimitValue) {
  809. item.content = '该项预算已超出预算设定的占比销售额' + item.upperLimitValue + '%'
  810. return true
  811. }
  812. }
  813. return false
  814. } else {
  815. return false
  816. }
  817. },
  818. proMainRequest(opUrl, postData) {
  819. return this.$channel.globleRequest('ProMainDashboardController', opUrl, postData, 'project')
  820. },
  821. budgetTemplateRequest(opUrl, postData) {
  822. return this.$channel.globleRequest('BudgetTemplateController', opUrl, postData, 'project')
  823. },
  824. baseRequest(opUrl, postData) {
  825. return this.$channel.globleRequest('BudgetMakingController', opUrl, postData, 'project')
  826. }
  827. }
  828. }
  829. </script>
  830. <style lang="scss">
  831. .budgeting {
  832. .tit {
  833. margin: 0 1vw;
  834. padding-bottom: 1vw;
  835. color: #51449d;
  836. font-size: 0.8vw;
  837. border-bottom: 1.5px solid #cccccc;
  838. }
  839. .ObjBox {
  840. margin: 0 1vw;
  841. .dashboard {
  842. background: #f5f5f5;
  843. display: grid;
  844. grid-template-columns: 1fr 1fr;
  845. gap: 1.25vw;
  846. padding: 1.25vw 0.83vw;
  847. color: #999999;
  848. }
  849. }
  850. .tableBody {
  851. margin: 0 1vw;
  852. .titBox {
  853. display: flex;
  854. justify-content: space-between;
  855. align-items: center;
  856. .ysxxBox {
  857. display: flex;
  858. align-items: center;
  859. }
  860. }
  861. .table {
  862. width: 100%;
  863. // margin: 1vw 4%;
  864. // min-height: 90%;
  865. background: white;
  866. border-radius: 2px;
  867. padding-bottom: 1vw;
  868. width: 98%;
  869. margin: 0 1%;
  870. font-size: 12px;
  871. .myTh {
  872. width: 100%;
  873. background: #f5f5f5;
  874. padding: 0.5vw 0;
  875. color: #999999;
  876. border-bottom: 1px solid rgba(153, 153, 153, 0.3);
  877. display: flex;
  878. div {
  879. text-align: left;
  880. }
  881. }
  882. .firstTr {
  883. width: 100%;
  884. padding: 0.5vw 0;
  885. display: flex;
  886. justify-items: center;
  887. align-items: center;
  888. text-align: center;
  889. border-bottom: 1.5px solid rgba(153, 153, 153, 0.3);
  890. }
  891. .firstColum {
  892. position: absolute;
  893. display: flex;
  894. align-items: center;
  895. justify-content: center;
  896. }
  897. .feiyong {
  898. width: 100%;
  899. // padding: 0.5vw 0;
  900. display: flex;
  901. .yszb {
  902. display: flex;
  903. color: rgba(153, 153, 153, 1);
  904. div {
  905. width: 50%;
  906. text-align: left;
  907. }
  908. }
  909. .sjfsys {
  910. display: flex;
  911. justify-content: flex-start;
  912. color: #e09f46;
  913. }
  914. .myTd {
  915. position: relative;
  916. left: 10%;
  917. border-bottom: 1px solid rgba(153, 153, 153, 0.3);
  918. padding: 0.5vw 0;
  919. display: flex;
  920. align-items: center;
  921. }
  922. .sjfsHjZb {
  923. text-align: center !important;
  924. }
  925. .ysje {
  926. border: 1px solid #cccccc;
  927. width: 90%;
  928. border-radius: 2px;
  929. padding: 5px;
  930. font-size: 12px;
  931. &::-webkit-input-placeholder {
  932. font-size: 12px;
  933. color: #cccccc;
  934. }
  935. }
  936. }
  937. .chengben {
  938. border: none !important;
  939. }
  940. .lirunBox {
  941. background: #f4f2ff;
  942. padding: 0.5vw;
  943. .lirun {
  944. width: 100%;
  945. margin: 0.5vw 0;
  946. display: flex;
  947. }
  948. .lurunLine {
  949. width: 95%;
  950. margin-left: 2.5%;
  951. height: 1.7px;
  952. background: rgba(142, 129, 213, 0.7);
  953. }
  954. }
  955. }
  956. }
  957. .btnBox {
  958. display: flex;
  959. position: absolute;
  960. bottom: -2vw;
  961. right: 0;
  962. .commit {
  963. background: #e3defc;
  964. color: #684eff;
  965. border-radius: 0.2vw;
  966. padding: 0.4vw 1vw;
  967. margin-right: 0.5vw;
  968. cursor: pointer;
  969. }
  970. .submit {
  971. background: #684eff;
  972. color: white;
  973. border: 1px solid #8e81d5;
  974. border-radius: 0.2vw;
  975. padding: 0.4vw 1vw;
  976. cursor: pointer;
  977. }
  978. .commit:hover {
  979. background: #eae9ef;
  980. color: #503dbc;
  981. }
  982. .submit:hover {
  983. background: #7a64f8;
  984. color: white;
  985. border: 1px solid #7f75b6;
  986. }
  987. }
  988. // .upload-demo {
  989. // .el-upload {
  990. // display: none !important;
  991. // }
  992. // }
  993. }
  994. </style>