receipt_trave_component.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. /*
  2. * @description: 费用-差旅组件
  3. * @Author: CP
  4. * @Date: 2020-11-16 14:52:08
  5. * @FilePath: \cld\global\vue\fee\receipt_trave_component.js
  6. */
  7. Vue.component("trave", {
  8. data: function () {
  9. return {
  10. // 行程时间
  11. traveDay: 0,
  12. tripTime: "",
  13. regionOption: region,
  14. // regionLeve2Option: region[0].child,
  15. // arrivalLeve2Option: region[0].child,
  16. regionLeve2Option: region[defaultTraveProvinceIndex].child,
  17. arrivalLeve2Option: region[defaultTraveProvinceIndex].child,
  18. // 出发地 省 市
  19. // departureProvince: region[0].name,
  20. // departureCity: region[0].child[0].name,
  21. departureProvince: defaultTraveProvince,
  22. departureCity: region[defaultTraveProvinceIndex].child[0].name,
  23. // 结束地 省 市
  24. // arrivalProvince: region[0].name,
  25. // arrivalCity: region[0].child[0].name,
  26. arrivalProvince: defaultTraveProvince,
  27. arrivalCity: region[defaultTraveProvinceIndex].child[0].name,
  28. // 目的地数组
  29. arrivalList: [],
  30. tripTimeEdi: "",
  31. departureProvinceEdi: '',
  32. departureCityEdi: '',
  33. arrivalProvinceEdi: '',
  34. arrivalCityEdi: '',
  35. ediIndex: '',
  36. // arrivalListEdi: [],
  37. }
  38. },
  39. props: ['traveItem', 'alertDia', 'traveList', 'traveExplain'],
  40. computed: {
  41. travePrice: function () {
  42. return travePrice(this.traveList);
  43. }
  44. },
  45. methods: {
  46. //行程时间验证
  47. changeCount: function (event) {
  48. this.tripTime = event.target.value;
  49. this.tripTimeEdi = event.target.value;
  50. let dateArray = event.target.value.split(" - ");
  51. if (dateArray.length == 2) {
  52. let dateFormat = /^(\d{4})-(\d{2})-(\d{2})$/;
  53. if (!dateFormat.test(dateArray[0])) {
  54. this.alertDia("差旅行程时间填写有误");
  55. return
  56. }
  57. if (!dateFormat.test(dateArray[1])) {
  58. this.alertDia("差旅行程时间填写有误");
  59. return
  60. }
  61. }
  62. // if(ValidTraveDate(dateArray)){
  63. // this.alertDia("差旅行程时间填写有误");
  64. // return
  65. // }
  66. traveDay = (Math.abs(Date.parse(dateArray[0]) - Date.parse(dateArray[1]))) / (1000 * 60 * 60 * 24) + 1;
  67. if (!isNaN(traveDay)) {
  68. this.traveDay = traveDay;
  69. let alertDia = this.alertDia;
  70. // 验证时间
  71. $.ajax({
  72. type: "GET",
  73. url: "/json/trave/date/all",
  74. dataType: "json",
  75. processData: false,
  76. contentType: false,
  77. }).success(function (sortList) {
  78. let item = new Array(new Date(Math.round(new Date(dateArray[0]).getTime() / 1000 - 28800)).getTime(), new Date(Math.round(new Date(dateArray[1]).getTime() / 1000 - 28800)).getTime());
  79. sortList.push(item);
  80. let TraveStatus = isTraveDate(sortList);
  81. if (TraveStatus == 2) {
  82. alertDia("差旅行程日期段-有重复");
  83. }
  84. }).fail(function (msg) {
  85. alertDia("历史差旅时间获取失败");
  86. });
  87. }
  88. // this.traveDay=new Date(dateArray[1]).getDate()-new Date(dateArray[0]).getDate()+1;
  89. },
  90. changeRegionLeve2: function (event, model) {
  91. this.regionOption.forEach(element => {
  92. if (element.name == event.target.value) {
  93. if (model == "departureCity") {
  94. this.regionLeve2Option = element.child;
  95. this.departureCity = element.child[0].name;
  96. this.departureCityEdi = element.child[0].name;
  97. this.arrivalProvinceEdi = element.name;
  98. this.arrivalProvince = element.name;
  99. this.arrivalLeve2Option = element.child;
  100. this.arrivalCity = element.child[0].name;
  101. this.arrivalCityEdi = element.child[0].name;
  102. } else if (model == "arrivalCity") {
  103. this.arrivalLeve2Option = element.child;
  104. this.arrivalCity = element.child[0].name;
  105. this.arrivalCityEdi = element.child[0].name;
  106. }
  107. return
  108. }
  109. });
  110. },
  111. changeArrivalCity: function (event) {
  112. this.arrivalCity = event.target.value
  113. this.arrivalCityEdi = event.target.value
  114. },
  115. // 行程单相关
  116. // 打开行程单
  117. openTrip: function () {
  118. this.arrivalList = [];
  119. this.tripTime = "";
  120. },
  121. deleteTrip(index) {
  122. this.traveList.splice(index, 1)
  123. },
  124. addTrip: function () {
  125. if (this.tripTime == "") {
  126. this.alertDia("请选择行程时间");
  127. return
  128. }
  129. // 构建行程信息
  130. tripList = [];
  131. // 出发地
  132. var newTripItem = NewTraveItem();
  133. tripList.push({
  134. province: this.departureProvince,
  135. city: this.departureCity,
  136. tripItem: newTripItem,
  137. subtotal: 0,
  138. });
  139. // 目的地
  140. this.arrivalList.forEach(element => {
  141. var newTripItem = NewTraveItem();
  142. tripList.push({
  143. province: element.arrivalProvince,
  144. city: element.arrivalCity,
  145. tripItem: newTripItem,
  146. subtotal: 0,
  147. });
  148. });
  149. // 结束地
  150. var newTripItem = NewTraveItem();
  151. tripList.push({
  152. province: this.arrivalProvince,
  153. city: this.arrivalCity,
  154. tripItem: newTripItem,
  155. subtotal: 0.00,
  156. });
  157. // 构建差旅信息
  158. trave = {
  159. tripTime: this.tripTime,
  160. tripList: tripList,
  161. total: 0.00,
  162. };
  163. this.traveList.push(trave);
  164. $('#route-add').modal('hide')
  165. },
  166. openEdiTrip(index) {
  167. this.ediIndex = index;
  168. let tripData = this.traveList[index];
  169. this.tripTimeEdi = tripData.tripTime;
  170. // 出发地
  171. this.departureProvinceEdi = tripData.tripList[0].province;
  172. this.departureCityEdi = tripData.tripList[0].city;
  173. // 结束
  174. let endIndex = tripData.tripList.length - 1
  175. this.arrivalProvinceEdi = tripData.tripList[endIndex].province;
  176. this.arrivalCityEdi = tripData.tripList[endIndex].city;
  177. // 目的地
  178. this.arrivalList = [];
  179. tripData.tripList.forEach((element, index) => {
  180. // 获得目的城市下拉菜单
  181. let arrivalCityOption = [];
  182. this.regionOption.forEach(el => {
  183. if (el.name == element.province) {
  184. arrivalCityOption = el.child;
  185. return
  186. }
  187. });
  188. if (index !== 0 && index !== endIndex) {
  189. this.arrivalList.push({
  190. "arrivalProvince": element.province,
  191. "arrivalCity": element.city,
  192. "arrivalCityOption": arrivalCityOption
  193. });
  194. }
  195. });
  196. },
  197. ediTrip() {
  198. if (this.tripTime == "") {
  199. this.alertDia("请选择行程时间");
  200. return
  201. }
  202. // 构建行程信息
  203. tripList = [];
  204. // 出发地
  205. var newTripItem = NewTraveItem();
  206. tripList.push({
  207. province: this.departureProvinceEdi,
  208. city: this.departureCityEdi,
  209. tripItem: newTripItem,
  210. subtotal: 0,
  211. });
  212. // 目的地
  213. this.arrivalList.forEach(element => {
  214. var newTripItem = NewTraveItem();
  215. tripList.push({
  216. province: element.arrivalProvince,
  217. city: element.arrivalCity,
  218. tripItem: newTripItem,
  219. subtotal: 0,
  220. });
  221. });
  222. // 结束地
  223. var newTripItem = NewTraveItem();
  224. tripList.push({
  225. province: this.arrivalProvinceEdi,
  226. city: this.arrivalCityEdi,
  227. tripItem: newTripItem,
  228. subtotal: 0.00,
  229. });
  230. // 构建差旅信息
  231. trave = {
  232. tripTime: this.tripTime,
  233. tripList: tripList,
  234. total: 0.00,
  235. };
  236. this.traveList[this.ediIndex] = trave;
  237. // 更新完成
  238. this.ediIndex = '';
  239. this.tripTimeEdi = '';
  240. this.departureProvinceEdi = '';
  241. this.departureCityEdi = '';
  242. this.arrivalProvinceEdi = '';
  243. this.arrivalCityEdi = '';
  244. this.arrivalList = [];
  245. $('#route-edi').modal('hide')
  246. },
  247. addArrivalDom: function (option) {
  248. // dom = {
  249. // "arrivalProvince": region[0].name,
  250. // "arrivalCity": region[0].child[0].name,
  251. // "arrivalCityOption": region[0].child,
  252. // }
  253. //1.没有目的地的时候
  254. let arrivalProvince = this.departureProvince;
  255. let arrivalCity = this.departureCity;
  256. let childIndexValue = this.departureProvince;
  257. if (option == "edi") {
  258. arrivalProvince = this.departureProvinceEdi;
  259. arrivalCity = this.departureCityEdi;
  260. childIndexValue = this.departureProvinceEdi;
  261. }
  262. if (this.arrivalList.length !== 0) {
  263. childIndexValue = this.arrivalList[this.arrivalList.length - 1].arrivalProvince
  264. arrivalProvince = childIndexValue;
  265. arrivalCity = this.arrivalList[this.arrivalList.length - 1].arrivalCity;
  266. }
  267. let index = 0;
  268. region.forEach((element, i) => {
  269. if (element.name === childIndexValue) {
  270. index = i;
  271. return;
  272. }
  273. });
  274. dom = {
  275. "arrivalProvince": arrivalProvince,
  276. "arrivalCity": arrivalCity,
  277. "arrivalCityOption": region[index].child,
  278. }
  279. this.arrivalList.push(dom);
  280. },
  281. delArrivalDom: function (index) {
  282. this.arrivalList.splice(index, 1)
  283. },
  284. changeArrivalLeve2: function (event, index) {
  285. this.regionOption.forEach(element => {
  286. if (element.name == event.target.value) {
  287. this.arrivalList[index].arrivalCityOption = element.child;
  288. this.arrivalList[index].arrivalCity = element.child[0].name;
  289. return
  290. }
  291. });
  292. },
  293. computeTraveItem: function (event) {
  294. this.traveItem.forEach((element, index) => {
  295. let sum = 0;
  296. // 每一列求和
  297. this.traveList.forEach(el => {
  298. el.tripList.forEach(elementlv2 => {
  299. elementlv2.tripItem.forEach(elementlv3 => {
  300. if (element.name == elementlv3.name) {
  301. sum += Number(elementlv3.price);
  302. }
  303. });
  304. });
  305. });
  306. this.traveItem[index].price = sum.toFixed(2);
  307. });
  308. // 每一个小目的地合计
  309. this.traveList.forEach((el, index) => {
  310. let total = 0;
  311. el.tripList.forEach((elementlv2, indexlv2) => {
  312. let sum = 0;
  313. elementlv2.tripItem.forEach(elementlv3 => {
  314. sum += Number(elementlv3.price);
  315. });
  316. total += sum
  317. this.traveList[index].tripList[indexlv2].subtotal = sum.toFixed(2);
  318. });
  319. this.traveList[index].total = total.toFixed(2);
  320. });
  321. },
  322. },
  323. template:
  324. `
  325. <div>
  326. <div class="seTable">
  327. <table class="table table-bordered table-condensed mb-0">
  328. <tbody>
  329. <tr>
  330. <th colspan="2" class="taC">差旅相关费用</th>
  331. </tr>
  332. <tr>
  333. <td colspan="2">
  334. <!--行程1-->
  335. <table v-for="(trave,index) in traveList" class="table table-bordered table-condensed table-hover"
  336. style="margin-bottom: 5px;">
  337. <tr>
  338. <th colspan="3" class="taC">行程{{ index+1 }}#
  339. {{ trave.tripTime }}
  340. <div class="fR ">
  341. <a href="javascript:void(0)" @click="deleteTrip(index)" class="text-danger" data-toggle="modal">删除</a>
  342. <a href="#route-edi" @click="openEdiTrip(index)" data-toggle="modal">编辑</a>
  343. </div>
  344. </th>
  345. </tr>
  346. <tbody v-for="(trip,i) in trave.tripList">
  347. <tr>
  348. <th colspan="3" class="ta"><i class="contactsMark icon-">P</i> {{trip.province}}-{{trip.city}}</th>
  349. </tr>
  350. <tr v-for="item in trip.tripItem" v-if="i!==trave.tripList.length-1" >
  351. <th width="90">{{item.name}}</th>
  352. <td class="taR" width="100">
  353. ¥<input type="number" v-model="item.price" @input="computeTraveItem" pattern="[0-9]" step="0.01" min="0" class="span1">
  354. </td>
  355. <th>
  356. <textarea required v-model="item.remark" rows="2" style="width: 99%; margin-bottom: 0" ></textarea>
  357. </th>
  358. </tr>
  359. </tbody>
  360. </table>
  361. </td>
  362. </tr>
  363. <tr>
  364. <th colspan="2" class="taC"><a href="#route-add" @click="openTrip" data-toggle="modal"
  365. class="button">添加新行程</a></th>
  366. </tr>
  367. <tr>
  368. <th colspan="2" class="taC">差旅相关费用合计</th>
  369. </tr>
  370. <tr v-for="item in traveItem" >
  371. <th>{{ item.name }}</th>
  372. <td class="taR" width="200">¥{{ item.price }}</td>
  373. </tr>
  374. <tr class="warning">
  375. <td class="taR"><b>差旅相关费用合计</b></td>
  376. <td class="colGreed taR"><b style="font-size: 24px">¥{{travePrice}}</b></td>
  377. </tr>
  378. <tr>
  379. <th colspan="2" class="taC">报销说明</th>
  380. </tr>
  381. <tr>
  382. <th colspan="2" v-for="item in traveExplain" >
  383. <textarea required rows="6" style="width: 99%" v-model="item.traveExplain" placeholder="差旅相关费用额外说明"></textarea>
  384. </th>
  385. </tr>
  386. </tbody>
  387. </table>
  388. </div>
  389. <div class="seCensor receipt-censor">
  390. <div class="title">报销单填写说明</div>
  391. <div class="detail">
  392. <p>1
  393. 请按先后发生顺序填写报销明细,交通费(市内交通费及往来交通费)、邮寄费需在批注明注明费用明细(例:珠海-广州70元-佛山20元);</p>
  394. <p>2 出差补助30元/天,不需提供发票,只需在报销单上填写清楚;</p>
  395. <p>
  396. 3 <b>产生费用所在办事处</b> 默认使用您所在的第一个办事处。
  397. </p>
  398. </div>
  399. <div class="itinerary">
  400. <h2 class="itineraryTitle">总行程单</h2>
  401. <div class="itineraryCon">
  402. <ul v-for="(trave,index) in traveList" >
  403. <li class="sub-title">行程{{ index+1 }}# {{ trave.tripTime }}</li>
  404. <li v-for="(trip,i) in trave.tripList" >
  405. <div class="itineraryList">
  406. <div class="addressName">
  407. <i class="contactsMark icon-">P</i> <b>{{trip.city}}</b>
  408. </div>
  409. <div class="pointLine " v-if="i!==trave.tripList.length-1" >
  410. <div class="timeList">
  411. <div class="priceList">
  412. <span class="priceTitle">小计</span>
  413. <span class="price">¥{{ trip.subtotal }}</span>
  414. </div>
  415. </div>
  416. </div>
  417. </div>
  418. </li>
  419. <li class="sub-title">行程{{ index+1 }}# 合计:{{ trave.total }}</li>
  420. </ul>
  421. </div>
  422. </div>
  423. </div>
  424. <!--弹出 编辑行程 -->
  425. <div class="modal hide fade" id="route-edi">
  426. <div class="modal-dialog">
  427. <div class="modal-content">
  428. <div class="modal-header">
  429. <h3>编辑行程</h3>
  430. </div>
  431. <div class="modal-body saeaList">
  432. <table class="table table-bordered table-condensed">
  433. <tr>
  434. <th class="taC" colspan="2">行程</th>
  435. </tr>
  436. <tr>
  437. <th>出发/结束日期</th>
  438. <td><input class="datepicker-here span3" placeholder="按时间筛选" type="text" data-range="true"
  439. data-multiple-dates-separator=" - " data-language="zh" @blur.prevent="changeCount" v-model="tripTimeEdi" >
  440. &nbsp;&nbsp;旅程合计:<b class="colRed">{{ traveDay }}</b>天
  441. </td>
  442. </tr>
  443. <tr>
  444. <th><span>┌</span> 出发地</th>
  445. <td>
  446. <select v-model="departureProvinceEdi" @change="changeRegionLeve2($event,'departureCity')" >
  447. <option v-for="option in regionOption" :value="option.name" >{{option.name}}</option>
  448. </select>
  449. <select v-model="departureCityEdi" @change="changeArrivalCity($event)">
  450. <option v-for="option in regionLeve2Option">{{option.name}}</option>
  451. </select>
  452. <a href="javascript:void(0)" @click="addArrivalDom('edi')" >+添加目的地</a>
  453. </td>
  454. </tr>
  455. <tr v-for="(item,index) in arrivalList" >
  456. <th><span class="">├</span> 目的地</th>
  457. <td>
  458. <select v-model="item.arrivalProvince" @change="changeArrivalLeve2($event,index)" >
  459. <option v-for="option in regionOption" :value="option.name" >{{option.name}}</option>
  460. </select>
  461. <select v-model="item.arrivalCity">
  462. <option v-for="option in item.arrivalCityOption">{{option.name}}</option>
  463. </select> <a href="javascript:void(0)" @click="delArrivalDom(index)">-移除</a>
  464. </td>
  465. </tr>
  466. <tr>
  467. <th><span class="">└</span> 结束</th>
  468. <td>
  469. <select v-model="arrivalProvinceEdi" @change="changeRegionLeve2($event,'arrivalCity')" >
  470. <option v-for="option in regionOption" :value="option.name" >{{option.name}}</option>
  471. </select>
  472. <select v-model="arrivalCityEdi">
  473. <option v-for="option in arrivalLeve2Option">{{option.name}}</option>
  474. </select>
  475. </td>
  476. </tr>
  477. </table>
  478. </div>
  479. <div class="modal-footer">
  480. <a href="javascript:void(0)" class="button" @click="ediTrip" >确认</a>
  481. <a href="javascript:void(0)" class="button btn-gray" data-dismiss="modal" aria-hidden="true">关闭</a>
  482. </div>
  483. </div>
  484. </div>
  485. </div>
  486. <!--弹出 添加行程 -->
  487. <div class="modal hide fade" id="route-add">
  488. <div class="modal-dialog">
  489. <div class="modal-content">
  490. <div class="modal-header">
  491. <h3>添加行程</h3>
  492. </div>
  493. <div class="modal-body saeaList">
  494. <table class="table table-bordered table-condensed">
  495. <tr>
  496. <th class="taC" colspan="2">行程</th>
  497. </tr>
  498. <tr>
  499. <th>出发/结束日期</th>
  500. <td><input class="datepicker-here span3" placeholder="按时间筛选" type="text" data-range="true"
  501. data-multiple-dates-separator=" - " data-language="zh" @blur.prevent="changeCount" v-model="tripTime" >
  502. &nbsp;&nbsp;旅程合计:<b class="colRed">{{ traveDay }}</b>天
  503. </td>
  504. </tr>
  505. <tr>
  506. <th><span>┌</span> 出发地</th>
  507. <td>
  508. <select v-model="departureProvince" @change="changeRegionLeve2($event,'departureCity')" >
  509. <option v-for="option in regionOption" :value="option.name" >{{option.name}}</option>
  510. </select>
  511. <select v-model="departureCity" @change="changeArrivalCity($event)">
  512. <option v-for="option in regionLeve2Option">{{option.name}}</option>
  513. </select>
  514. <a href="javascript:void(0)" @click="addArrivalDom" >+添加目的地</a>
  515. </td>
  516. </tr>
  517. <tr v-for="(item,index) in arrivalList" >
  518. <th><span class="">├</span> 目的地</th>
  519. <td>
  520. <select v-model="item.arrivalProvince" @change="changeArrivalLeve2($event,index)" >
  521. <option v-for="option in regionOption" :value="option.name" >{{option.name}}</option>
  522. </select>
  523. <select v-model="item.arrivalCity">
  524. <option v-for="option in item.arrivalCityOption">{{option.name}}</option>
  525. </select> <a href="javascript:void(0)" @click="delArrivalDom(index)">-移除</a>
  526. </td>
  527. </tr>
  528. <tr>
  529. <th><span class="">└</span> 结束</th>
  530. <td>
  531. <select v-model="arrivalProvince" @change="changeRegionLeve2($event,'arrivalCity')" >
  532. <option v-for="option in regionOption" :value="option.name" >{{option.name}}</option>
  533. </select>
  534. <select v-model="arrivalCity">
  535. <option v-for="option in arrivalLeve2Option">{{option.name}}</option>
  536. </select>
  537. </td>
  538. </tr>
  539. </table>
  540. </div>
  541. <div class="modal-footer">
  542. <a href="javascript:void(0)" class="button" @click="addTrip" >确认</a>
  543. <a href="javascript:void(0)" class="button btn-gray" data-dismiss="modal" aria-hidden="true">关闭</a>
  544. </div>
  545. </div>
  546. </div>
  547. </div>
  548. <!--结束 弹出 添加行程 -->
  549. </div>
  550. `
  551. })