Payment.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. <template>
  2. <a-spin :spinning="confirmLoading">
  3. <j-form-container :disabled="formDisabled">
  4. <a-form-model
  5. ref="form"
  6. :model="model"
  7. :rules="validatorRules"
  8. slot="detail"
  9. >
  10. <a-row>
  11. <a-col :span="24">
  12. <a-form-model-item
  13. label="结账应收"
  14. :labelCol="labelCol"
  15. :wrapperCol="wrapperCol"
  16. prop="billAmount"
  17. >
  18. {{ model.billAmount.toFixed(2) }}元
  19. <a-switch v-model="model.coupon" />优惠
  20. </a-form-model-item>
  21. </a-col>
  22. <template v-if="model.coupon">
  23. <a-col :span="24">
  24. <a-form-model-item
  25. label="优惠方式"
  26. :labelCol="labelCol"
  27. :wrapperCol="wrapperCol"
  28. prop="refund"
  29. >
  30. <a-radio-group v-model="model.preferentialType">
  31. <a-radio :value="1"> 抹零 </a-radio>
  32. <a-radio :value="2"> 减现 </a-radio>
  33. <a-radio :value="3"> 打折 </a-radio>
  34. </a-radio-group>
  35. <template v-if="model.preferentialType === 3"
  36. >打<a-input-number
  37. style="width: 50px"
  38. v-model="model.discount"
  39. :min="1"
  40. :max="9"
  41. ></a-input-number
  42. >折
  43. </template>
  44. </a-form-model-item>
  45. </a-col>
  46. <a-col :span="24" v-if="model.preferentialType == 2">
  47. <a-form-model-item
  48. label="优惠金额"
  49. :labelCol="labelCol"
  50. :wrapperCol="wrapperCol"
  51. prop="couponFirstAmount"
  52. >
  53. <a-input-number
  54. style="width: 100px"
  55. :min="0"
  56. v-model="model.couponFirstAmount"
  57. placeholder="请输入优惠金额"
  58. ></a-input-number
  59. >元
  60. </a-form-model-item>
  61. </a-col>
  62. <a-col :span="24">
  63. <a-form-model-item
  64. label="惠后金额"
  65. :labelCol="labelCol"
  66. :wrapperCol="wrapperCol"
  67. >
  68. {{ couponAmount.toFixed(2) }}元
  69. </a-form-model-item>
  70. </a-col>
  71. <a-col :span="24">
  72. <a-form-model-item
  73. label="优惠券"
  74. :labelCol="labelCol"
  75. :wrapperCol="wrapperCol"
  76. prop="refund"
  77. >
  78. <a-select
  79. v-if="model.couponCard"
  80. v-model="model.couponId"
  81. style="width: 200px"
  82. placeholder="优惠券"
  83. :allowClear="true"
  84. >
  85. <a-select-option
  86. :value="couponItem.id"
  87. v-for="couponItem in memeberCouponList"
  88. :key="couponItem.id"
  89. >{{ couponItem.couponsName }}</a-select-option
  90. >
  91. </a-select>
  92. <a-switch v-model="model.couponCard" />使用优惠券
  93. </a-form-model-item>
  94. </a-col>
  95. </template>
  96. <a-col :span="24">
  97. <a-form-model-item
  98. label="实收金额"
  99. :labelCol="labelCol"
  100. :wrapperCol="wrapperCol"
  101. >
  102. {{ realityAmount.toFixed(2) }}元
  103. </a-form-model-item>
  104. </a-col>
  105. <a-col :span="24">
  106. <a-form-model-item
  107. label="收款金额"
  108. :labelCol="labelCol"
  109. :wrapperCol="wrapperCol"
  110. >
  111. <div v-for="(item, index) in payList" :key="index">
  112. <a-row type="flex" :key="index">
  113. <a-col :span="6">
  114. <a-input-number
  115. style="width: 100px"
  116. v-model="item.money"
  117. :min="0"
  118. ></a-input-number>
  119. </a-col>
  120. <a-col :span="6">
  121. <a-select
  122. v-model="item.payType"
  123. placeholder="收款方式"
  124. @change="(event) => onChange(event, item)"
  125. >
  126. <a-select-option
  127. :value="item2.id"
  128. v-for="item2 in payTypeList"
  129. :key="item2.id"
  130. >
  131. {{ item2.name }}
  132. </a-select-option>
  133. </a-select></a-col
  134. >
  135. <a-col :span="6">
  136. <a-icon
  137. v-if="index == payList.length - 1"
  138. type="plus-circle"
  139. class="dynamic-delete-button"
  140. @click="puls()" />
  141. <a-icon
  142. v-if="payList.length > 1"
  143. type="minus-circle"
  144. style="color: #f56c6c"
  145. class="dynamic-delete-button"
  146. @click="() => remove(index)"
  147. /></a-col>
  148. </a-row>
  149. <a-row type="flex" v-if="item.isVipMemmber">
  150. <a-col :span="12"> 姓名:{{ memberCard.name }} </a-col>
  151. <a-col :span="12"> 卡号:{{ memberCard.cardNo }} </a-col>
  152. <a-col :span="12">
  153. 会员级别: {{ memberCard.gradeName }}</a-col
  154. >
  155. <a-col :span="12"> 余额:{{ memberCard.balance }} </a-col>
  156. <a-col :span="12"> 积分:{{ memberCard.integral }} </a-col>
  157. <!-- <a-col :span="12"> 本次扣后剩余: </a-col>
  158. <a-col :span="12"> 本次新增积分: </a-col> -->
  159. </a-row>
  160. </div>
  161. </a-form-model-item>
  162. </a-col>
  163. <a-col :span="24">
  164. <a-form-model-item
  165. label="实收合计"
  166. :labelCol="labelCol"
  167. :wrapperCol="wrapperCol"
  168. >
  169. {{ sumAmount.toFixed(2) }}元
  170. </a-form-model-item>
  171. </a-col>
  172. </a-row>
  173. </a-form-model>
  174. </j-form-container>
  175. </a-spin>
  176. </template>
  177. <script>
  178. import { httpAction, getAction } from "@/api/manage";
  179. import { validateDuplicateValue } from "@/utils/util";
  180. export default {
  181. name: "Payment",
  182. components: {},
  183. props: {
  184. //表单禁用
  185. disabled: {
  186. type: Boolean,
  187. default: false,
  188. required: false,
  189. },
  190. },
  191. data() {
  192. return {
  193. model: {
  194. coupon: false,
  195. discount: 1,
  196. couponCard: false,
  197. couponType: 1,
  198. couponFirstAmount: 0,
  199. billAmount: 0,
  200. selectedFeeIds: [],
  201. },
  202. labelCol: {
  203. xs: { span: 24 },
  204. sm: { span: 5 },
  205. },
  206. wrapperCol: {
  207. xs: { span: 24 },
  208. sm: { span: 16 },
  209. },
  210. confirmLoading: false,
  211. validatorRules: {
  212. mobile: [
  213. {
  214. required: true,
  215. pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
  216. message: "请输入手机号!",
  217. },
  218. ],
  219. cardNo: [{ required: true, message: "请输入会员卡号!" }],
  220. gradeId: [{ required: true, message: "请输入等级类型!" }],
  221. payType: [{ required: true, message: "请输入付款类型!" }],
  222. paymentMethod: [{ required: true, message: "请输入付款方式!" }],
  223. customerName: [{ required: true, message: "请输入会员姓名!" }],
  224. sex: [{ required: true, message: "请输入性别!" }],
  225. certificateType: [{ required: true, message: "请输入证件类型!" }],
  226. validity: [{ required: true, message: "请输入有效期!" }],
  227. },
  228. url: {
  229. add: "/business/busRoomBookingOrders/booking-to-live",
  230. edit: "/business/busMemberCard/edit",
  231. queryById: "/business/busMemberCard/queryById",
  232. },
  233. gradeList: [],
  234. paymentMethodList: [],
  235. staffList: [],
  236. customerList: [],
  237. oldcustomerList: [],
  238. payTypeList: [],
  239. memberCard: {},
  240. isVipMemmber: false,
  241. payList: [],
  242. memeberCouponList: [],
  243. };
  244. },
  245. computed: {
  246. formDisabled() {
  247. return this.disabled;
  248. },
  249. sumAmount() {
  250. var sum = this.payList.reduce(function (total, item) {
  251. return total + item.money;
  252. }, 0);
  253. return sum;
  254. },
  255. couponAmount() {
  256. var sum = 0;
  257. if (this.model.coupon) {
  258. if (this.model.preferentialType == 1) {
  259. sum = Math.floor(this.model.billAmount);
  260. } else if (this.model.preferentialType == 2) {
  261. sum = this.model.billAmount - (this.model.couponFirstAmount || 0);
  262. } else if (this.model.preferentialType == 3) {
  263. sum = parseFloat(
  264. ((this.model.billAmount * this.model.discount) / 10).toFixed(2)
  265. );
  266. }
  267. } else {
  268. sum = this.model.billAmount;
  269. }
  270. return sum;
  271. },
  272. realityAmount() {
  273. if (this.model.couponCard) {
  274. var find = this.memeberCouponList.find(
  275. (t) => t.id == this.model.couponId
  276. );
  277. if (find) {
  278. return this.couponAmount - find.cost;
  279. }
  280. }
  281. return this.couponAmount;
  282. },
  283. },
  284. created() {
  285. var _info = JSON.parse(localStorage.getItem("storeInfo"));
  286. if (_info) {
  287. this.model.hotelId = _info.id;
  288. }
  289. //备份model原始值
  290. this.modelDefault = JSON.parse(JSON.stringify(this.model));
  291. getAction("/business/busRoomPayType/list", {
  292. pageSize: 99999,
  293. pageNo: 1,
  294. }).then((res) => {
  295. if (res.success) {
  296. this.payTypeList = res.result.records;
  297. }
  298. });
  299. getAction("/business/busMemberCard/list", {
  300. id: "11111111",
  301. }).then((res) => {
  302. if (res.success) {
  303. if (res.result.records && res.result.records.length > 0) {
  304. this.memberCard = res.result.records[0];
  305. }
  306. }
  307. });
  308. },
  309. methods: {
  310. getbusRoomPayType() {
  311. getAction("/business/busRoomPayType/list", {
  312. pageSize: 99999,
  313. pageNo: 1,
  314. }).then((res) => {
  315. if (res.success) {
  316. this.payTypeList = res.result.records;
  317. if (this.payTypeList && this.payTypeList.length > 0) {
  318. this.$set(this.model, "payType", this.payTypeList[0].id);
  319. this.payList = [
  320. {
  321. money: this.realityAmount,
  322. payType: this.payTypeList[0].id,
  323. isVipMemmber: false,
  324. },
  325. ];
  326. }
  327. }
  328. });
  329. },
  330. puls() {
  331. this.payList.push({
  332. money: 0,
  333. payType: this.payTypeList[0].id,
  334. isVipMemmber: false,
  335. });
  336. },
  337. remove(index) {
  338. this.payList.splice(index, 1);
  339. },
  340. onChange(e, value) {
  341. console.log("value", value);
  342. console.log("e", e);
  343. var find = this.payTypeList.find((t) => t.id == value.payType);
  344. value.isVipMemmber = find && find.name == "会员卡";
  345. },
  346. handleSearch(value) {
  347. let result;
  348. if (!value) {
  349. result = this.oldcustomerList;
  350. } else {
  351. result = this.oldcustomerList.filter((t) => t.name.includes(value));
  352. }
  353. this.customerList = result;
  354. },
  355. handleSelectMember(e) {
  356. var find = this.customerList.find((t) => t.id === e);
  357. this.model.phone = find.phone;
  358. this.model.customerName = find.name;
  359. this.model.customerId = find.id;
  360. },
  361. getMemeberCouponList() {
  362. getAction("/business/busMarketCouponsCashUsed/memeberCouponList", {
  363. pageNo: 1,
  364. pageSize: 99,
  365. conditions: 900,
  366. mobile: this.model.vipCustomerId,
  367. }).then((res) => {
  368. if (res.success) {
  369. this.memeberCouponList = res.result.records;
  370. }
  371. });
  372. },
  373. add(livingOrderId, roomId) {
  374. this.modelDefault.livingOrderId = livingOrderId;
  375. this.modelDefault.roomId = roomId;
  376. this.edit(this.modelDefault);
  377. },
  378. edit(record) {
  379. this.model = Object.assign({}, record);
  380. this.getbusRoomPayType();
  381. if (this.model.vipCustomerId) {
  382. this.getMemeberCouponList();
  383. }
  384. this.visible = true;
  385. },
  386. submitForm() {
  387. const that = this;
  388. // 触发表单验证
  389. this.$refs.form.validate((valid) => {
  390. if (valid) {
  391. console.log("this.realityAmount ", this.realityAmount);
  392. console.log("this.sumAmount ", this.sumAmount);
  393. if (this.realityAmount != this.sumAmount) {
  394. that.$message.warning("实收金额和实收合计必须相等");
  395. return;
  396. }
  397. var obj = {};
  398. var fees = [];
  399. if (this.model.coupon) {
  400. fees.push({
  401. feeType: this.model.feeType,
  402. preferentialType: this.model.preferentialType,
  403. money: this.couponAmount.toFixed(2),
  404. custorerOrderRemark: "优惠金额",
  405. isPreferential: true,
  406. });
  407. }
  408. if (this.model.couponCard && this.model.couponId) {
  409. var find = this.memeberCouponList.find(
  410. (t) => t.id == this.model.couponId
  411. );
  412. if (find) {
  413. fees.push({
  414. feeType: this.model.feeType,
  415. money: find.cost.toFixed(2),
  416. custorerOrderRemark: "优惠券",
  417. isPreferential: true,
  418. });
  419. }
  420. }
  421. this.payList.forEach((item) => {
  422. fees.push({
  423. feeType: this.model.feeType,
  424. money: item.money.toFixed(2),
  425. payType: item.payType,
  426. custorerOrderRemark: "结账退房",
  427. isPreferential: false,
  428. });
  429. });
  430. that.confirmLoading = true;
  431. var url =
  432. "/business/busRoomBookingOrders/settle-checkout?bookingOrderId=" +
  433. this.model.bookingOrderId;
  434. if (this.model.livingOrderId) {
  435. url =
  436. "/business/busRoomBookingOrders/living-settle-checkout?livingOrderId=" +
  437. this.model.livingOrderId;
  438. }
  439. if (
  440. this.model.selectedFeeIds &&
  441. this.model.selectedFeeIds.length > 0
  442. ) {
  443. url = "/business/busRoomBookingOrders/partial-settle";
  444. obj = {
  445. fees: fees,
  446. livingOrderId: this.model.livingOrderId,
  447. selectedFeeIds: this.model.selectedFeeIds,
  448. };
  449. }
  450. httpAction(
  451. url,
  452. this.model.selectedFeeIds && this.model.selectedFeeIds.length > 0
  453. ? obj
  454. : fees,
  455. "post"
  456. )
  457. .then((res) => {
  458. if (res.success) {
  459. that.$message.success("结账成功");
  460. that.$emit("ok");
  461. } else {
  462. that.$message.warning(res.message);
  463. }
  464. })
  465. .finally(() => {
  466. that.confirmLoading = false;
  467. });
  468. }
  469. });
  470. },
  471. },
  472. };
  473. </script>
  474. <style scoped>
  475. .dynamic-delete-button {
  476. cursor: pointer;
  477. position: relative;
  478. /* top: 4px; */
  479. margin-left: 5px;
  480. font-size: 18px;
  481. color: #1890ff;
  482. transition: all 0.3s;
  483. }
  484. .dynamic-delete-button:hover {
  485. color: #777;
  486. }
  487. .dynamic-delete-button[disabled] {
  488. cursor: not-allowed;
  489. opacity: 0.5;
  490. }
  491. </style>