edit.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616
  1. <template>
  2. <div>
  3. <Toptitle :title="type==1?'新增费用单据':type==2?'编辑费用单据':'费用单据详情'">
  4. <Button @click="back" style="margin-right:20px" type="primary">返回</Button>
  5. <Button type="primary" @click="postData" v-if='type!=3'>保存</Button>
  6. </Toptitle>
  7. <Form :label-width='100' class="top_order">
  8. <FormItem label="费用单据号:" style="width:400px">
  9. <span v-if="type==3">{{formData.cost_no}}</span>
  10. <Input disabled placeholder="自动生成费用单据" v-model="formData.cost_no" style='width:200px' v-else/>
  11. </FormItem>
  12. <FormItem label="相关项目:" style="width:500px">
  13. <span v-if="type==3">{{formData.order_no}}</span>
  14. <div style="display:flex;width:100%;" v-else >
  15. <Select v-model="formData.order_no" filterable clearable style="width:200px" >
  16. <Option v-for="(item,index) in projectTitleList" :key="index" :value="item.project_number" :label="item.project_name"></Option>
  17. </Select>
  18. <Button style="margin-left:20px" type="primary" @click="showProjectModal=true">选择项目</Button>
  19. </div>
  20. </FormItem>
  21. <FormItem label='供应商:' style="width:400px">
  22. <span v-if="type==3">{{formData.supply_title}}</span>
  23. <div v-else style='display:flex;width:300px'>
  24. <Select filterable clearable v-model="formData.supply_id" >
  25. <Option v-for="(item,index) in suppliersList" :key="index" :value="item.id" :label="item.title"></Option>
  26. </Select><Button type="primary" style="margin-left:20px" @click="showSupplierModal=true">选择供应商</Button>
  27. </div>
  28. </FormItem>
  29. <FormItem label="制单日期:" style="width:400px">
  30. <span v-if="type==3">{{formData.order_time}}</span>
  31. <DatePicker type="date" placeholder="年/月/日" style="width: 200px" v-model="formData.order_time" v-else></DatePicker>
  32. </FormItem>
  33. <FormItem label='备注:' style="width:300px">
  34. <span v-if="type==3">{{formData.remark}}</span>
  35. <Input clearable v-model="formData.remark" v-else/>
  36. </FormItem>
  37. </Form>
  38. <div class="before_table">
  39. <Button type="primary" @click="addPrice" v-if='type!=3'>增行</Button>
  40. </div>
  41. <Table :data='tableData' :columns='type==3?detailTableColumns:tableColumns' border :max-height="type==3?'300':'500'" show-summary :summary-method="handleSummary">
  42. <template slot="set" slot-scope="{index}">
  43. <a @click='del(index)'>删除</a>
  44. </template>
  45. <template slot="name" slot-scope="{index}">
  46. <Input v-model="tableData[index].name" placeholder="请输入费用内容" @on-focus='handleFocusName(index)'/>
  47. </template>
  48. <template slot="price" slot-scope="{index}">
  49. <Input v-model="tableData[index].price" @on-change='changePrice($event,index)' @on-focus="priceFocus(index)" @on-blur='priceBlur(index)' type="number"/>
  50. </template>
  51. <template slot="total_price" slot-scope="{index}">
  52. <Input v-model="tableData[index].total_price" @on-change='changeTotalPrice($event,index)' @on-focus="totalPriceFocus(index)" @on-blur='totalPriceBlur(index)' type="number"/>
  53. </template>
  54. <template slot="num" slot-scope="{index}">
  55. <Input v-model="tableData[index].num" @on-change='changeNum($event,index)' @on-blur='priceBlurNum(index)' @on-focus='handleFocusNum(index)' type="number"/>
  56. </template>
  57. <template slot="remark" slot-scope="{index}">
  58. <Input v-model="tableData[index].remark" placeholder="请输入费用备注"/>
  59. </template>
  60. </Table>
  61. <Form v-if="type==3" class="top_order">
  62. <FormItem label='制单人:' style="width:30%">
  63. <span>{{formData.user_name}}</span>
  64. </FormItem>
  65. <FormItem label='创建时间:' style="width:30%">
  66. <span>{{formData.crt_time}}</span>
  67. </FormItem>
  68. <FormItem label='修改时间:' style="width:30%">
  69. <span>{{formData.upd_time}}</span>
  70. </FormItem>
  71. <FormItem label='审批人:' style="width:30%">
  72. <span>{{formData.check_name}}</span>
  73. </FormItem>
  74. <FormItem label='审批时间:' style="width:30%">
  75. <span>{{formData.check_time}}</span>
  76. </FormItem>
  77. </Form>
  78. <Modal v-model="showProjectModal"
  79. title="选择项目"
  80. width='80'
  81. @on-ok="handleProjectSelect"
  82. @on-cancel="showProjectModal=false">
  83. <div class="modal_content">
  84. <div class="modal_content_center">
  85. <Form class="modal_content_center_top" :label-width='120'>
  86. <FormItem label='项目编号:'>
  87. <Input type="text"
  88. v-model="modalProjectData.project_number"
  89. style="width:180px"
  90. placeholder="请输入项目编码"
  91. clearable
  92. />
  93. </FormItem>
  94. <FormItem label='项目名称:'>
  95. <Input type="text"
  96. v-model="modalProjectData.project_name"
  97. style="width:180px"
  98. placeholder="请输入项目名称"
  99. clearable
  100. />
  101. </FormItem>
  102. <FormItem label='项目简称:'>
  103. <Input type="text"
  104. v-model="modalProjectData.abbreviation"
  105. style="width:180px"
  106. placeholder="请输入项目简称"
  107. clearable
  108. />
  109. </FormItem>
  110. <FormItem :label-width='40'>
  111. <Button @click="initProjectModal()"
  112. type="primary"
  113. style="margin:0 10px;">搜索</Button>
  114. </FormItem>
  115. </Form>
  116. <div class="modal_content_center_body">
  117. <Table :columns="modalProjectTableColumns"
  118. height="520"
  119. border
  120. :loading="modalProjectTableLoading"
  121. :data="modalProjectData.tableData">
  122. </Table>
  123. <div class="modal_content_center_footer">
  124. <Page :page-size-opts="[10, 20, 30, 40,100]"
  125. @on-page-size-change='changeProjectModalSize'
  126. @on-change='changeProjectModalPage'
  127. :current='modal_project_page_index'
  128. show-total
  129. :total="modal_project_total"
  130. show-sizer
  131. :page-size='modal_project_page_size' />
  132. </div>
  133. </div>
  134. </div>
  135. </div>
  136. </Modal>
  137. <Modal v-model="showSupplierModal"
  138. title="选择供应商"
  139. width='80'
  140. @on-ok="handleSupplierSelect"
  141. @on-cancel="showSupplierModal=false">
  142. <div class="modal_content" style="display:flex;">
  143. <div class="modal_content_left">
  144. <Tree :data="modalSupplierData.treeData"
  145. children-key='sub'
  146. style="width:100%;"
  147. @on-select-change="handleSupplierTreeSlect"
  148. class="demo-tree-render"></Tree>
  149. </div>
  150. <div class="modal_content_center" style="width:85%">
  151. <Form class="modal_content_center_top" :label-width='120'>
  152. <FormItem label='供应商名称:'>
  153. <Input type="text"
  154. clearable
  155. v-model="modalSupplierData.title"
  156. style="width:180px"
  157. placeholder="请输入供应商名称" />
  158. <Button @click="initSupplierModal(modalSupplierData)"
  159. type="primary"
  160. style="margin:0 10px;">搜索</Button>
  161. </FormItem>
  162. </Form>
  163. <div class="modal_content_center_body">
  164. <Table :columns="modalSupplierTableColumns"
  165. height="520"
  166. border
  167. :loading="modalSupplierTableLoading"
  168. :data="modalSupplierData.tableData"
  169. >
  170. </Table>
  171. <div class="modal_content_center_footer">
  172. <Page :page-size-opts="[10, 20, 30, 40,100]"
  173. @on-page-size-change='changeSupplierModalSize'
  174. @on-change='changeSupplierModalPage'
  175. :current='modal_supplier_page_index'
  176. show-total
  177. :total="modal_supplier_total"
  178. show-sizer
  179. :page-size='modal_supplier_page_size' />
  180. </div>
  181. </div>
  182. </div>
  183. </div>
  184. </Modal>
  185. </div>
  186. </template>
  187. <script>
  188. export default {
  189. data(){
  190. return{
  191. modalSupplierData: {
  192. title: '',
  193. code: '',
  194. treeData: [
  195. {
  196. title: '供应商分类',
  197. expand: true,
  198. sub: [],
  199. render: (h, { root, node, data }) => {
  200. return h('span', {
  201. style: {
  202. display: 'inline-block',
  203. width: '100%'
  204. }
  205. }, [
  206. h('span', [
  207. h('Icon', {
  208. props: {
  209. type: 'ios-folder-outline'
  210. },
  211. style: {
  212. marginRight: '8px'
  213. }
  214. }),
  215. h('span', data.title)
  216. ]),
  217. h('span', {
  218. style: {
  219. display: 'inline-block',
  220. // float: 'right',
  221. marginRight: '32px'
  222. }
  223. })
  224. ]);
  225. },
  226. }
  227. ],
  228. tableData: [{}]
  229. },
  230. modalSupplierTableColumns: [
  231. {
  232. title: '选择', key: '', align: 'center', minWidth: 60,
  233. render: (h, params) => {
  234. let id = params.row.id;
  235. let flag = false;
  236. if (this.currentChoose.id == id) {
  237. flag = true
  238. } else {
  239. flag = false
  240. }
  241. let self = this
  242. return h('div', [
  243. h('Radio', {
  244. props: {
  245. value: flag
  246. },
  247. on: {
  248. 'on-change': () => {
  249. self.currentChoose = params.row;
  250. }
  251. }
  252. })
  253. ])
  254. }
  255. },
  256. { title: '供应商编码', key: 'code', align: 'center', minWidth: 100 },
  257. { title: '供应商名称', key: 'title', align: 'center', minWidth: 80, },
  258. { title: '负责人', key: 'contact', align: 'center', minWidth: 110, },
  259. { title: '联系方式', key: 'mobile', align: 'center', minWidth: 110, },
  260. ],
  261. currentChoose:{},
  262. showSupplierModal:false,
  263. modalSupplierTableLoading: false,
  264. modal_supplier_page_index: 1,
  265. modal_supplier_page_size: 10,
  266. modal_supplier_total: 0,
  267. suppliersList:[],
  268. modal_project_total:0,
  269. modalProjectTableLoading:false,
  270. currentChoose: {},
  271. modalProjectTableColumns: [
  272. {
  273. title: '选择', key: '', align: 'center', minWidth: 60,
  274. render: (h, params) => {
  275. let id = params.row.id;
  276. let flag = false;
  277. if (this.currentChoose.id == id) {
  278. flag = true
  279. } else {
  280. flag = false
  281. }
  282. let self = this
  283. return h('div', [
  284. h('Radio', {
  285. props: {
  286. value: flag
  287. },
  288. on: {
  289. 'on-change': () => {
  290. self.currentChoose = params.row;
  291. }
  292. }
  293. })
  294. ])
  295. }
  296. },
  297. { title: '项目编号', key: 'project_number', align: 'center', minWidth: 100 },
  298. { title: '项目名称', key: 'project_name', align: 'center', minWidth: 100 },
  299. { title: '项目简称', align: 'center', key: 'abbreviation', minWidth: 80},
  300. {
  301. title: '制单时间', key: 'crt_time', align: 'center', minWidth: 110,
  302. render: (h, params) => {
  303. const { row } = params
  304. return h('span', {}, this.func.replaceDate(row.crt_time))
  305. }
  306. },
  307. ],
  308. modal_project_page_index:1,
  309. modal_project_page_size:10,
  310. modalProjectData: {
  311. project_number:'',
  312. abbreviation:'',
  313. project_name: '',
  314. tableData: [{}]
  315. },
  316. showProjectModal:false,
  317. type:null,
  318. formData:{
  319. cost_no:'',
  320. order_no:'',
  321. order_time:new Date(),
  322. remark:'',
  323. supply_id:'',
  324. },
  325. timeData:{
  326. start_time:'',
  327. end_time:''
  328. },
  329. projectTitleList:[],
  330. tableData:[],
  331. tableColumns:[
  332. {title:'费用明细',align:'center',minWidth:100,key:'name',slot:'name'},
  333. {title:'数量',align:'center',minWidth:100,key:'num',slot:'num'},
  334. {title:'单价',align:'center',minWidth:100,key:'price',slot:'price'},
  335. {title:'金额',align:'center',minWidth:100,key:'total_price',slot:'total_price'},
  336. {title:'备注',align:'center',minWidth:100,key:'remark',slot:'remark'},
  337. {title:'操作',align:'center',minWidth:100,key:'set',slot:'set'},
  338. ],
  339. detailTableColumns:[
  340. {title:'费用明细',align:'center',minWidth:100,key:'name'},
  341. {title:'数量',align:'center',minWidth:100,key:'num'},
  342. {title:'单价',align:'center',minWidth:100,key:'price'},
  343. {title:'金额',align:'center',minWidth:100,key:'total_price'},
  344. {title:'备注',align:'center',minWidth:100,key:'remark'},
  345. ]
  346. }
  347. },
  348. created(){
  349. this.type=this.$route.query.type;
  350. //获取项目名称
  351. this.axios.get('/api/cut_order_list',{params:{order_type:1}}).then(res=>{
  352. this.projectTitleList = res.data.data
  353. })
  354. // 获取供应商列表
  355. this.axios({ method: 'get', url: '/api/supply_list', }).then((res) => { this.suppliersList = res.data.data }).catch((err) => { });
  356. this.initProjectModal();
  357. // 获取供应商分类
  358. this.axios({ method: 'get', url: '/api/basic_supply_list', }).then((res) => { this.modalSupplierData.treeData[0].sub = res.data }).catch((err) => { });
  359. this.initSupplierModal(this.modalSupplierData);
  360. this.axios.get('/api/warning_list').then(res => { this.warningList = res.data.data })
  361. },
  362. mounted(){
  363. if(this.type!=1){
  364. this.initData();
  365. }
  366. },
  367. methods:{
  368. changeSupplierModalSize (e) {
  369. this.modal_supplier_page_size = e
  370. this.initSupplierModal(this.modalSupplierData)
  371. },
  372. changeSupplierModalPage (e) {
  373. this.modal_supplier_page_index = e
  374. this.initSupplierModal(this.modalSupplierData)
  375. },
  376. initSupplierModal (searchData) {
  377. this.axios({
  378. method: 'get',
  379. url: '/api/supply_list',
  380. params: {
  381. page_index: this.modal_supplier_page_index,
  382. page_size: this.modal_supplier_page_size,
  383. title: searchData.title,
  384. code: searchData.code,
  385. }
  386. }).then((res) => {
  387. this.modal_supplier_total = res.data.total
  388. this.modalSupplierData.tableData = res.data.data
  389. }).catch((err) => { });
  390. },
  391. handleSupplierTreeSlect (arr, row) {
  392. this.modalSupplierData.code = row.code
  393. this.modal_supplier_page_index = 1;
  394. this.initSupplierModal(this.modalSupplierData)
  395. },
  396. handleSupplierSelect () {
  397. this.formData.supply_id = this.currentChoose.id
  398. },
  399. changeProjectModalSize (e) {
  400. this.modal_project_page_size = e
  401. this.initProjectModal()
  402. },
  403. changeProjectModalPage (e) {
  404. this.modal_project_page_index = e
  405. this.initProjectModal()
  406. },
  407. initProjectModal () {
  408. this.axios({
  409. method: 'get',
  410. url: '/api/cut_order_list',
  411. params:{
  412. page_index: this.modal_project_page_index,
  413. page_size: this.modal_project_page_size,
  414. order_type:1,
  415. project_number:this.modalProjectData.project_number,
  416. project_name:this.modalProjectData.project_name,
  417. abbreviation:this.modalProjectData.abbreviation
  418. }
  419. }).then((res) => {
  420. this.modal_project_total = res.data.total
  421. this.modalProjectData.tableData = res.data.data
  422. }).catch((err) => { });
  423. },
  424. handleProjectSelect () {
  425. this.formData.order_no = this.currentChoose.project_number;
  426. },
  427. initData(){
  428. this.axios.post('/api/cost_detail',{cost_no:this.$route.query.cost_no}).then(res=>{
  429. this.formData = JSON.parse(JSON.stringify(res.data));
  430. delete this.formData.list;
  431. this.formData.order_time = this.func.replaceDateNoHMS(res.data.order_time);
  432. this.formData.crt_time = this.func.replaceDate(res.data.crt_time);
  433. this.formData.upd_time = this.func.replaceDate(res.data.upd_time);
  434. this.formData.check_time = this.func.replaceDate(res.data.check_time);
  435. this.tableData = res.data.list;
  436. })
  437. },
  438. handleSummary ({ columns, data }) {
  439. const sums = {};
  440. columns.forEach((column, index) => {
  441. console.log(data)
  442. const key = column.key;
  443. if (index === 0) {
  444. sums[key] = {
  445. key,
  446. value: '总价'
  447. };
  448. return;
  449. }
  450. const values = data.map(item => Number(item[key]));
  451. if (key == 'total_price') {
  452. const v = values.reduce((prev, curr) => {
  453. const value = Number(curr);
  454. if (!isNaN(value)) {
  455. return prev + curr;
  456. } else {
  457. return prev;
  458. }
  459. }, 0);
  460. sums[key] = {
  461. key,
  462. value:v.toFixed(2)
  463. };
  464. } else {
  465. sums[key] = {
  466. key,
  467. value: ''
  468. };
  469. }
  470. });
  471. return sums;
  472. },
  473. changePrice(e,index){
  474. this.tableData[index].price = e.target.value;
  475. this.tableData[index].total_price = (this.tableData[index].num*this.tableData[index].price*1).toFixed(2);
  476. },
  477. changeTotalPrice(e,index){
  478. this.tableData[index].total_price = e.target.value;
  479. this.tableData[index].price = this.tableData[index].num!=0?(this.tableData[index].total_price/(this.tableData[index].num*1)).toFixed(3):'0.000';
  480. },
  481. changeNum(e,index){
  482. this.tableData[index].num = e.target.value;
  483. this.tableData[index].total_price = (this.tableData[index].num*this.tableData[index].price*1).toFixed(2);
  484. },
  485. handleFocusNum(index){
  486. this.tableData[index].num='';
  487. },
  488. handleFocusName(index){
  489. this.tableData[index].name='';
  490. },
  491. priceBlur(index){
  492. if(Number(this.tableData[index].price)<0){
  493. this.tableData[index].price='0.000';
  494. this.tableData[index].total_price='0.00';
  495. }else if(this.tableData[index].price===''){
  496. this.tableData[index].price='0.000';
  497. this.tableData[index].total_price='0.00';
  498. }else{
  499. this.tableData[index].price=Number(this.tableData[index].price).toFixed(3);
  500. this.tableData[index].total_price=Number(this.tableData[index].total_price).toFixed(2);
  501. return
  502. }
  503. },
  504. // totalPriceBlur(index),
  505. priceFocus(index){
  506. this.tableData[index].price = ''
  507. },
  508. totalPriceFocus(index){
  509. this.tableData[index].total_price = ''
  510. },
  511. priceBlurNum(index){
  512. if(this.tableData[index].num<0||this.tableData[index].num===''){
  513. this.tableData[index].num = 0;
  514. this.tableData[index].total_price='0.00';
  515. }else{
  516. this.tableData[index].total_price=Number(this.tableData[index].total_price).toFixed(2);
  517. return
  518. }
  519. },
  520. back(){
  521. this.$Modal.confirm({
  522. title: '是否确认取消',
  523. onOk: () => {
  524. this.$router.go(-1);
  525. },
  526. onCancel: () => {
  527. }
  528. });
  529. },
  530. postData(){
  531. let obj =JSON.parse(JSON.stringify(this.formData));
  532. let arr = this.tableData.filter(v=>{
  533. return v.name!='';
  534. })
  535. obj.order_time = obj.order_time?Date.parse(obj.order_time).toString().slice(0,10):'';
  536. if(this.type==1){
  537. this.axios.post('/api/cost_add',{...obj,children:arr}).then(res=>{
  538. if(res.code==200){
  539. this.$Message.success(res.msg);
  540. this.back();
  541. }
  542. })
  543. }else{
  544. this.axios.post('/api/cost_edit',{...obj,children:arr}).then(res=>{
  545. if(res.code==200){
  546. this.$Message.success(res.msg);
  547. this.back();
  548. }
  549. })
  550. }
  551. },
  552. // changeInput(e,index){
  553. // this.tableData[index].name = e.target.value;
  554. // },
  555. del(index){
  556. this.tableData.splice(index,1)
  557. },
  558. addPrice(){
  559. let obj = {};
  560. obj.price = '0.000';
  561. obj.name='';
  562. obj.num=0;
  563. obj.total_price='0.00';
  564. this.tableData.push(obj)
  565. console.log(this.tableData);
  566. },
  567. }
  568. }
  569. </script>
  570. <style lang="scss" scoped>
  571. .top_order{
  572. display: flex;
  573. flex-wrap: wrap;
  574. margin-top: 15px;
  575. .order_select{
  576. width: 600px;
  577. }
  578. }
  579. .before_table{
  580. display: flex;
  581. flex-direction: row-reverse;
  582. margin-bottom:15px
  583. }
  584. .modal_content {
  585. overflow: hidden;
  586. overflow-y: auto;
  587. .modal_content_left {
  588. width: 15%;
  589. }
  590. .modal_content_center {
  591. .modal_content_center_top {
  592. display: flex;
  593. flex-wrap: wrap;
  594. }
  595. .modal_content_center_body {
  596. padding-top: 20px;
  597. }
  598. .modal_content_center_footer {
  599. display: flex;
  600. justify-content: center;
  601. padding-top: 20px;
  602. }
  603. }
  604. }
  605. </style>