increaseViewers.vue 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082
  1. <template>
  2. <el-dialog
  3. title="添加观影人"
  4. :visible.sync="dialogVisible"
  5. width="90%"
  6. :before-close="handleClose">
  7. <div
  8. v-loading="loading"
  9. :element-loading-text="loadingText"
  10. element-loading-spinner="el-icon-loading"
  11. element-loading-background="rgba(0, 0, 0, 0.8)"
  12. class="increase-viewers-box">
  13. <div class="increase-viewers-info">
  14. <el-table
  15. :data="viewerList"
  16. border
  17. style="width: 100%">
  18. <el-table-column
  19. label="序号"
  20. type="index"
  21. width="50">
  22. </el-table-column>
  23. <el-table-column
  24. label="姓名"
  25. width="180">
  26. <template slot-scope="scope">
  27. <div>
  28. <span v-if="actionIndex != scope.row.id">{{ scope.row.name }}</span>
  29. <el-input size="mini" v-else v-model="tableForm.name" placeholder="请输入姓名"></el-input>
  30. </div>
  31. </template>
  32. </el-table-column>
  33. <el-table-column
  34. label="身份证号"
  35. width="250">
  36. <template slot-scope="scope">
  37. <div>
  38. <span v-if="actionIndex != scope.row.id">{{ scope.row.idcard }}</span>
  39. <el-input
  40. size="mini"
  41. v-else
  42. v-model="tableForm.idcard"
  43. placeholder="请输入身份证号"
  44. clearable
  45. style="width: 230px;"
  46. @keyup.enter.native="handleQuery"
  47. >
  48. <el-button slot="append" :loading="idcardLoading" size="mini" type="primary" @click="readCert">{{ idcardLoading ? '识别中':'识别' }}</el-button>
  49. </el-input>
  50. </div>
  51. </template>
  52. </el-table-column>
  53. <el-table-column
  54. label="座位类型">
  55. <template slot-scope="scope">
  56. <span>{{ scope.row.seatTypeName }}</span>
  57. </template>
  58. </el-table-column>
  59. <el-table-column
  60. prop="date"
  61. label="座位号">
  62. <template slot-scope="scope">
  63. <span>{{ scope.row.seatName }}</span>
  64. </template>
  65. </el-table-column>
  66. <el-table-column
  67. prop="date"
  68. label="价格(元)">
  69. <template slot-scope="scope">
  70. <span>{{ scope.row.salePrice }}</span>
  71. </template>
  72. </el-table-column>
  73. <el-table-column
  74. label="人员类别"
  75. width="140">
  76. <template slot-scope="scope">
  77. <div>
  78. <dict-tag v-if="actionIndex != scope.row.id" :options="dict.type.personnel_type" :value="scope.row.identity"/>
  79. <el-select
  80. size="mini"
  81. v-else
  82. v-model="tableForm.identity"
  83. placeholder="请选择人员类别"
  84. clearable
  85. style="width: 100%"
  86. >
  87. <el-option
  88. v-for="dict in dict.type.personnel_type"
  89. :key="dict.value"
  90. :label="dict.label"
  91. :value="dict.value"
  92. />
  93. </el-select>
  94. </div>
  95. </template>
  96. </el-table-column>
  97. <el-table-column
  98. label="应付金额(元)">
  99. <template slot-scope="scope">
  100. <span v-if="(scope.$index!=0 && oneMany ==1 && personnelNum != 0)">{{ scope.row.realPrice }}</span>
  101. <div v-else>
  102. <span v-if="actionIndex != scope.row.id">{{ scope.row.realPrice }}</span>
  103. <el-input-number size="mini" style="width: 120px;" v-else v-model="tableForm.realPrice" controls-position="right" label="请输入应付金额(元)"></el-input-number>
  104. </div>
  105. </template>
  106. </el-table-column>
  107. <el-table-column
  108. label="备注"
  109. width="180">
  110. <template slot-scope="scope">
  111. <div>
  112. <span v-if="actionIndex != scope.row.id">{{ scope.row.remark }}</span>
  113. <el-input size="mini" v-else v-model="tableForm.remark" placeholder="请输入备注"></el-input>
  114. </div>
  115. </template>
  116. </el-table-column>
  117. <el-table-column
  118. label="操作"
  119. width="80"
  120. >
  121. <template slot-scope="scope" v-if="(scope.$index != 0 && oneMany!=2) || scope.$index == 0">
  122. <el-button
  123. size="mini"
  124. type="success"
  125. :loading="factorAuthLoading"
  126. v-if="actionIndex == scope.row.id"
  127. @click="handleSeva(scope.$index, scope.row)">{{ factorAuthLoading ? '保存中....' : '保存' }}</el-button>
  128. <el-button
  129. :disabled="!!actionIndex"
  130. size="mini"
  131. type="primary"
  132. v-if="actionIndex != scope.row.id"
  133. @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
  134. <!-- <el-button
  135. size="mini"
  136. type="danger"
  137. @click="handleDelete(scope.$index, scope.row)">删除</el-button> -->
  138. </template>
  139. </el-table-column>
  140. </el-table>
  141. </div>
  142. <div style="padding: 10px 0 20px;">合计:累计观影人员{{ viewerList.length }}人,应付总额¥{{ moneyAll }}(元)</div>
  143. <div>
  144. <el-form
  145. :model="ruleForm"
  146. :rules="rules"
  147. ref="ruleForm11"
  148. label-width="120px"
  149. class="demo-ruleForm"
  150. size="mini"
  151. >
  152. <div style="display: flex;">
  153. <el-form-item label="用户来源 :" prop="source">
  154. <el-radio-group v-model="ruleForm.source">
  155. <el-radio label="7">窗口</el-radio>
  156. <el-radio label="10">美团</el-radio>
  157. <el-radio label="11">携程</el-radio>
  158. <el-radio label="13">抖音</el-radio>
  159. <el-radio label="14">猫眼</el-radio>
  160. <!-- <el-radio label="15">去哪儿</el-radio> -->
  161. <el-radio label="16">其他</el-radio>
  162. </el-radio-group>
  163. </el-form-item>
  164. <el-form-item label-width="60px" v-if="ruleForm.source && ruleForm.source == 16" label="备注 :" prop="sourceRemark">
  165. <el-input style="width: 200px;" v-model="ruleForm.sourceRemark"></el-input>
  166. </el-form-item>
  167. </div>
  168. <el-form-item v-if="ruleForm.source && ruleForm.source != 7" label="核销码/订单码" prop="orderIdOrQrCode">
  169. <el-input style="width: 400px;" type="textarea" :rows="2" v-model="ruleForm.orderIdOrQrCode"></el-input>
  170. </el-form-item>
  171. <el-form-item label="支付方式 :" prop="paymentType">
  172. <el-radio-group v-model="ruleForm.paymentType">
  173. <el-radio label="1">扫码</el-radio>
  174. <el-radio label="2">现金</el-radio>
  175. <el-radio v-if="['10','11','13','14'].includes(ruleForm.source)" label="3">对公支付</el-radio>
  176. </el-radio-group>
  177. </el-form-item>
  178. <el-form-item label="应付金额 :">
  179. ¥{{ moneyAll }}元
  180. </el-form-item>
  181. <el-form-item v-if="ruleForm.paymentType == 2 || ruleForm.paymentType == 3" label="实付金额 :" prop="realPrice">
  182. <el-input @input="setRealPrice" style="width: 200px;" v-model="ruleForm.realPrice"></el-input>
  183. </el-form-item>
  184. <el-form-item label="找零金额 :" v-if="ruleForm.paymentType == 2">
  185. ¥{{ ruleForm.small }}元
  186. </el-form-item>
  187. <el-form-item label="订单备注 :" prop="remark">
  188. <el-input style="width: 400px;" type="textarea" :rows="2" maxlength="200" v-model="ruleForm.remark" show-word-limit></el-input>
  189. </el-form-item>
  190. </el-form>
  191. </div>
  192. <!-- 支付过程 控制 -->
  193. <div v-if="payStatus" class="increase-viewers-pay-status">
  194. <div class="increase-viewers-pay-status-info" v-if="!loading">
  195. <span style="font-weight: 600;font-size: 20px;">提示</span>
  196. <span style="padding: 10px 0;">
  197. {{ payStatus==1 ? '生成订单失败!!!' :
  198. payStatus==2 ? '生成订单生成成功,请点击调取扫码盒子' :
  199. payStatus==4 ? '扫码支付失败!!!' :
  200. payStatus==5 ? '请出示付款码!!!' :
  201. payStatus==6 ? '连接扫码器失败!!!' :
  202. payStatus==7 ? '用户支付失败或未支付,请重新连接支付!!!' :
  203. payStatus==8 ? '用户支付成功,请点击打印票!!!' :
  204. payStatus==9 ? '支付超时!!!' :
  205. payStatus==3 ? '现金支付记录入库失败,请重新提交' : '未知状态' }}
  206. </span>
  207. <!-- 重新生成订单 1 -->
  208. <div v-if="payStatus==1" style="display: flex;">
  209. <el-button @click="payStatus = null" type="success">修改信息</el-button>
  210. <el-button @click="orderInfoSubmitFun()" style="margin-left: 20px;" type="primary">重新生成订单</el-button>
  211. </div>
  212. <!-- 扫码支付 2 -->
  213. <el-button v-if="payStatus==2" @click="vbar_open(orderId)" type="success">扫码支付</el-button>
  214. <!-- 扫码支付 4 -->
  215. <el-button v-if="payStatus==4" @click="vbar_open(orderId)" type="success">重新扫码支付</el-button>
  216. <!-- 重新支付 3 -->
  217. <el-button v-if="payStatus==3" @click="gotoCashPayFun(orderId)" type="success">重新提交入库</el-button>
  218. <!-- 重新支付 6 7 -->
  219. <el-button v-if="payStatus==6 || payStatus==7" @click="vbar_open(orderId)" type="success">重新连接扫码支付</el-button>
  220. <!-- 打印 8 -->
  221. <div v-if="payStatus==8">
  222. <el-select v-model="printListId" placeholder="选择打印机">
  223. <el-option :label="item.deviceName" :key="item.id" :value="item.id" v-for="(item,index) in printList"></el-option>
  224. </el-select>
  225. <el-button style="margin-left: 15px" @click="print" type="success">打印门票</el-button>
  226. <el-button style="margin-left: 15px" @click="goTicketingCollections" type="success">跳转取票界面</el-button>
  227. </div>
  228. <!-- 支付超时 9 -->
  229. <div v-if="payStatus==9">
  230. <!-- <el-button @click="print" type="danger">取消支付</el-button> -->
  231. <el-button @click="orderInfoSubmitFun()" type="primary">重新扫码</el-button>
  232. </div>
  233. </div>
  234. </div>
  235. </div>
  236. <span slot="footer" class="dialog-footer">
  237. <el-button @click="handleClose()">取 消</el-button>
  238. <el-button v-if="!orderId&&!payStatus" :loading="loading" type="primary" @click="submitForm('ruleForm11')">确定支付</el-button>
  239. </span>
  240. </el-dialog>
  241. </template>
  242. <script>
  243. import {
  244. orderInfoSubmit,
  245. gotoMicroPay,
  246. gotoCashPay,
  247. gotoCorporatePay,
  248. payQuery,
  249. selectRegion,
  250. orderInfoCancel,
  251. factorAuth
  252. } from '@/api/windowTicketSales/ticketingSales'
  253. import { pageList as getPrintListApi } from "@/api/device/pda";
  254. import { printApi } from '@/api/windowTicketSales/ticketingCollection'
  255. const mathM = require('mathjs')
  256. const https = require('https');
  257. const axios = require('axios');
  258. export default {
  259. dicts: ['personnel_type'],
  260. data() {
  261. return {
  262. loading: false,
  263. loadingText: '',
  264. dialogVisible: false,
  265. actionIndex: false,
  266. tableForm: {
  267. name: '', // 姓名
  268. mobile: '', // 电话
  269. idcard: '', // 身份证
  270. identity: '', // 观影人身份
  271. remark: '', // 备注信息
  272. salePrice: '', // 原价
  273. realPrice: '', // 实付金额
  274. seatId: '', // 座位ID
  275. seatName: '', // 座位名称
  276. seatType: '', // 座位类型
  277. },
  278. ruleForm: {
  279. performId: "", // 剧目ID
  280. retailId: "", // 分销ID
  281. goodsList: [], // 商品列表
  282. auditoriumId: "", // 演出厅ID
  283. performTimeId: "1", // 场次时段ID
  284. seatTypeId: "", // 座位类型ID
  285. source: '', // 订单来源
  286. purchaser: {},// 购票人信息
  287. viewerList: [], // 观影人列表
  288. orderIdOrQrCode: '',
  289. paymentType: '', // 支付方式
  290. small: '',// 找零
  291. realPrice: '', // 实付金额
  292. },
  293. viewerList: [], // 观影人列表
  294. rules: {
  295. source: [
  296. { required: true, message: '请选择用户来源', trigger: ['blur','change']},
  297. ],
  298. orderIdOrQrCode: [
  299. { required: true, message: '请输入核销码/订单码', trigger: ['blur','change']},
  300. ],
  301. paymentType: [
  302. { required: true, message: '请选择支付方式', trigger: ['blur','change']},
  303. ],
  304. realPrice: [
  305. { required: true, message: '请输入实付金额', trigger: ['blur','change']},
  306. ],
  307. sourceRemark: [
  308. { required: true, message: '请输入备注', trigger: ['blur','change']},
  309. ],
  310. },
  311. moneyAll: '',
  312. payment: '',
  313. payStatus: null, // 支付状态
  314. orderId: null,
  315. websocket_connected: false, // 是否已连接
  316. websocketCtrl: null,
  317. websocketData: null,
  318. idcardLoading: false,
  319. payTime: null, // 支付等待时间
  320. payTimeNum: 0,
  321. printListId: null,
  322. printList: [],
  323. // 身份证校验 loading
  324. factorAuthLoading: false,
  325. ifRealUser: 0, // 散客是否实名:0-否 1-是
  326. ifRealTeam: 0, // 团购是否实名:0否 1-是
  327. oneMany: 1, // 证件要求: 1一证一票,2一证多票
  328. personnelNum: 0, // 人员要求:0-表示不限制 其他数字表示限制人数
  329. };
  330. },
  331. methods: {
  332. async initData(list,params){
  333. try {
  334. this.ifRealUser = params.ifRealUser // 散客是否实名:0-否 1-是
  335. this.ifRealTeam = params.ifRealTeam // 团购是否实名:0否 1-是
  336. this.oneMany = params.oneMany // 证件要求: 1一证一票,2一证多票
  337. this.personnelNum = params.personnelNum // 人员要求:0-表示不限制 其他数字表示限制人数
  338. this.websocketClear()
  339. this.idcardLoading = false
  340. this.ruleForm = {
  341. performId: "", // 剧目ID
  342. retailId: "", // 分销ID
  343. goodsList: [], // 商品列表
  344. auditoriumId: "", // 演出厅ID
  345. performTimeId: "", // 场次时段ID
  346. seatTypeId: "", // 座位类型ID
  347. source: '', // 订单来源
  348. purchaser: {},// 购票人信息
  349. viewerList: [], // 观影人列表
  350. orderIdOrQrCode: '',
  351. paymentType: '', // 支付方式
  352. small: '',// 实付金额
  353. realPrice: '', // 实付金额
  354. remark: '', // 订单备注
  355. sourceRemark: '', // 来源备注
  356. }
  357. this.payStatus = null
  358. this.orderId = null
  359. this.websocket_connected = false
  360. this.dialogVisible = true
  361. this.loading = true
  362. this.actionIndex = null
  363. this.viewerList = []
  364. let perform = await this.selectRegionFun(params,list[0].seatTypeId)
  365. console.log("perform===",perform)
  366. // let perform = {
  367. // money: 1,
  368. // name: '普通票'
  369. // }
  370. let listCopy = []
  371. let listCopy1 = []
  372. list.forEach((item,index)=>{
  373. listCopy.push({
  374. id: index+1,
  375. name: '', // 姓名
  376. mobile: '', // 电话
  377. idcard: '', // 身份证
  378. identity: '', // 观影人身份
  379. remark: '', // 备注信息
  380. salePrice: this.oneMany == 2 || (this.oneMany == 1 && this.personnelNum != 0) ? index == 0 ? perform.money : 0 : perform.money, // 原价
  381. realPrice: this.oneMany == 2 || (this.oneMany == 1 && this.personnelNum != 0) ? index == 0 ? perform.money : 0 : perform.money, // 实付金额
  382. seatId: item.id, // 座位ID
  383. seatName: item.name?item.name:'暂无命名', // 座位名称
  384. seatType: perform.seatTypeId, // 座位类型
  385. seatTypeId: perform.seatTypeId,
  386. seatTypeName: perform.seatTypeName,
  387. })
  388. })
  389. //this.goodsList =
  390. this.viewerList = JSON.parse(JSON.stringify(listCopy))
  391. this.setMoneyAll()
  392. console.log(this.viewerList)
  393. this.loading = false
  394. this.$nextTick(()=>{
  395. this.$refs.ruleForm11.clearValidate()
  396. })
  397. } catch (error) {
  398. console.error("error====",error)
  399. }
  400. },
  401. /** 获取票务信息 */
  402. async selectRegionFun(params,seatTypeId){
  403. try {
  404. this.loadingText = "获取票务信息中..."
  405. let res = await selectRegion({
  406. "auditoriumId": params.auditoriumId, // 演艺厅ID
  407. "goodsId": params.goodsId, // 商品ID
  408. "performId": params.performId, // 上一界面节目ID
  409. "performTimeId": params.timeId, // 时段ID
  410. "retailId": "" // 分销ID
  411. })
  412. if(res.code == 200) {
  413. if(res.data.regionPriceList &&res.data.regionPriceList.length>0){
  414. //let obj = res.data.regionPriceList[0]
  415. let obj = {}
  416. res.data.regionPriceList.forEach((item,index)=>{
  417. if(seatTypeId == item.seatTypeId) {
  418. obj = item
  419. }
  420. })
  421. if(JSON.stringify(obj) != '{}'){
  422. this.ruleForm.performId = obj.performId
  423. this.ruleForm.goodsList = [
  424. {
  425. goodsId: obj.goodsId,
  426. salePeice: obj.salePrice,
  427. saleNum: 1,
  428. }
  429. ]
  430. this.ruleForm.auditoriumId = obj.auditoriumId
  431. this.ruleForm.performId = obj.performId
  432. this.ruleForm.performTimeId = res.data.performTimeId
  433. this.ruleForm.seatTypeId = obj.seatTypeId
  434. return {
  435. money: obj.salePrice,
  436. //name: obj.goodsName,
  437. seatTypeId: obj.seatTypeId,
  438. seatTypeName: obj.seatTypeName,
  439. }
  440. }else {
  441. this.$message.error('存在座位未设置价格,请选择其他票!!!');
  442. this.loading = false
  443. this.dialogVisible = false
  444. }
  445. }else {
  446. this.$message.error('存在座位未设置价格,请选择其他票!!!');
  447. this.loading = false
  448. this.dialogVisible = false
  449. }
  450. console.log("res====",res)
  451. }else {
  452. this.$message.error(res.msg);
  453. this.loading = false
  454. this.dialogVisible = false
  455. }
  456. } catch (error) {
  457. console.error("error=====",error)
  458. this.$message.error('价格查询出错');
  459. this.loading = false
  460. this.dialogVisible = false
  461. }
  462. },
  463. /** 取消订单 */
  464. async orderInfoCancelFun(type){
  465. try {
  466. this.loading = true
  467. this.loadingText = "取消订单中..."
  468. orderInfoCancel({
  469. orderId: this.orderId
  470. }).then((res)=>{
  471. if(res.code==200) {
  472. if(type){ // 关闭弹窗
  473. this.$emit('clearDialogVisible')
  474. this.dialogVisible = false
  475. }else {
  476. this.payStatus = 9
  477. this.loading = false
  478. }
  479. }
  480. }).catch(()=>{
  481. this.$message.error('订单关闭失败!!!');
  482. })
  483. } catch (error) {
  484. }
  485. },
  486. /** 退出窗口 */
  487. handleClose(done) {
  488. // if(this.payStatus==8) {
  489. // this.$message.error('请daying');
  490. // return
  491. // }
  492. this.$confirm('确认关闭?')
  493. .then(_ => {
  494. if(this.orderId){
  495. this.orderInfoCancelFun(true)
  496. }else {
  497. this.dialogVisible = false
  498. }
  499. })
  500. .catch(_ => {});
  501. },
  502. /** 保存个人信息 */
  503. handleSeva(index, row) {
  504. if(!this.tableForm.name){
  505. this.$message.error('请输入姓名!!!');
  506. return
  507. }
  508. if(!this.tableForm.idcard){
  509. this.$message.error('请输入身份证号!!!');
  510. return
  511. }
  512. if(this.tableForm.identity && this.tableForm.identity != 0){
  513. if(!this.tableForm.remark){
  514. this.$message.error('请输入备注!!!');
  515. return
  516. }
  517. }
  518. //this.factorAuthFun(index,this.tableForm)
  519. if(this.oneMany == 2 && index==0) {
  520. this.$set(this.viewerList,index,JSON.parse(JSON.stringify(this.tableForm)))
  521. let list = JSON.parse(JSON.stringify(this.viewerList))
  522. list.forEach((item,index)=>{
  523. item.name = this.tableForm.name
  524. item.idcard = this.tableForm.idcard
  525. })
  526. this.viewerList = list
  527. }else {
  528. this.$set(this.viewerList,index,JSON.parse(JSON.stringify(this.tableForm)))
  529. }
  530. this.actionIndex = null
  531. this.setMoneyAll()
  532. },
  533. /** 校验 身份证 */
  534. async factorAuthFun(index, obj){
  535. try {
  536. this.factorAuthLoading = true
  537. let res = await factorAuth({
  538. "name": obj.name,
  539. "idcard": obj.idcard
  540. })
  541. if(res.code == 200){
  542. this.factorAuthLoading = false
  543. if(res.data.status != 1) {
  544. this.$message.error(res.data.errReason);
  545. }else {
  546. this.$set(this.viewerList,index,JSON.parse(JSON.stringify(this.tableForm)))
  547. this.actionIndex = null
  548. this.setMoneyAll()
  549. }
  550. }else {
  551. this.$message.error(res.msg);
  552. this.factorAuthLoading = false
  553. }
  554. } catch (error) {
  555. this.$message.error(error);
  556. this.factorAuthLoading = false
  557. }
  558. },
  559. handleEdit(index, row) {
  560. this.actionIndex = row.id
  561. this.tableForm = JSON.parse(JSON.stringify(row))
  562. console.log(index, row);
  563. },
  564. handleDelete(index, row) {
  565. console.log(index, row);
  566. },
  567. setMoneyAll(){
  568. let moneyAll = 0
  569. this.viewerList.forEach((item,index) => {
  570. console.log("item.realPrice====",item.realPrice)
  571. if(item.realPrice && !isNaN(Number(item.realPrice))) {
  572. moneyAll = mathM.format(Number(moneyAll) + Number(item.realPrice),10)
  573. }
  574. })
  575. console.log("dsfsfdsf",moneyAll)
  576. this.moneyAll = moneyAll? moneyAll: ''
  577. },
  578. setRealPrice(value) {
  579. if(value && !isNaN(value)) {
  580. this.$set(this.ruleForm,'small',mathM.format(Number(value) - Number(this.moneyAll),10) )
  581. }
  582. },
  583. /** 检查是否存在空值 */
  584. checkViewerList() {
  585. let flog = false
  586. for(let i = 0; i < this.viewerList.length; i++){
  587. let obj = this.viewerList[i]
  588. if(!obj.name){
  589. this.$message.error('请填写观影人姓名!!!');
  590. flog = true
  591. break;
  592. }
  593. if(!obj.idcard){
  594. this.$message.error('请填写观影人身份证号!!!');
  595. flog = true
  596. break;
  597. }
  598. if(obj.identity && obj.identity != 0){
  599. if(!obj.remark){
  600. this.$message.error('请填写观影人备注!!!');
  601. flog = true
  602. break;
  603. }
  604. }
  605. }
  606. if(this.actionIndex){
  607. this.$message.error('请先保存观影影人信息!!!');
  608. flog = true
  609. }
  610. return flog
  611. },
  612. submitForm(formName) {
  613. this.$refs[formName].validate((valid) => {
  614. if (valid) {
  615. if(!this.checkViewerList()){
  616. this.orderInfoSubmitFun()
  617. }
  618. } else {
  619. console.log('error submit!!');
  620. return false;
  621. }
  622. });
  623. },
  624. resetForm(formName) {
  625. this.$refs[formName].resetFields();
  626. },
  627. /** 生成订单 */
  628. async orderInfoSubmitFun(){
  629. this.loading = true
  630. try {
  631. this.orderId = null
  632. this.loadingText = "生成订单中..."
  633. let res = await orderInfoSubmit({
  634. ...this.ruleForm,
  635. viewerList: this.viewerList
  636. })
  637. if(res.code == 200){
  638. this.orderId = res.data.orderId
  639. if(this.ruleForm.paymentType == 2) {
  640. this.gotoCashPayFun(this.orderId)
  641. }else if(this.ruleForm.paymentType == 3) { // 对公支付
  642. this.gotoCorporatePayFun(this.orderId)
  643. }else {
  644. // 扫码支付
  645. this.loading = false
  646. this.payStatus = 2
  647. }
  648. }else{
  649. this.$message.error('生成订单失败!!!');
  650. this.loading = false
  651. this.payStatus = 1
  652. }
  653. } catch (error) {
  654. this.$message.error('生成订单失败!!!');
  655. this.loading = false
  656. this.payStatus = 1
  657. }
  658. },
  659. /** 调取 订单支付码支付 */
  660. async gotoMicroPayFun(orderId,code){
  661. this.loading = true
  662. try {
  663. this.loadingText = "订单支付中..."
  664. this.payStatus = ''
  665. let res = await gotoMicroPay({
  666. "orderId": orderId, // 订单编号-提交订单返回
  667. "authCode": code // 微信扫码支付-支付码
  668. })
  669. if(res.code == 200){
  670. this.payTimeNum = 0
  671. this.websocketClear()
  672. if(this.payTime){
  673. clearInterval(this.payTime)
  674. }
  675. this.payTime = setInterval(()=>{
  676. this.payQueryFun(this.orderId)
  677. },1500)
  678. }else{
  679. this.$message.error('支付失败!!!');
  680. this.payStatus = ''
  681. this.loading = false
  682. this.payStatus = 6
  683. }
  684. } catch (error) {
  685. this.$message.error('支付失败!!!');
  686. this.loading = false
  687. this.payStatus = 6
  688. }
  689. },
  690. /** 对公支付 */
  691. async gotoCorporatePayFun(orderId) {
  692. this.loading = true
  693. try {
  694. this.loadingText = "订单入库中..."
  695. let res = await gotoCorporatePay({
  696. "orderId": orderId, // 订单编号-提交订单返回
  697. "payAmount": this.ruleForm.realPrice
  698. })
  699. if(res.code == 200){
  700. if(this.payTime){
  701. clearInterval(this.payTime)
  702. }
  703. this.payTimeNum = 0
  704. this.payTime = setInterval(()=>{
  705. this.payQueryFun(this.orderId)
  706. },1000)
  707. }else{
  708. this.$message.error('订单入库中失败!!!');
  709. this.loading = false
  710. this.payStatus = 3
  711. }
  712. } catch (error) {
  713. this.$message.error('订单入库中失败!!!');
  714. this.loading = false
  715. this.payStatus = 3
  716. }
  717. },
  718. /** 订单现金支付 */
  719. async gotoCashPayFun(orderId){
  720. this.loading = true
  721. try {
  722. this.loadingText = "订单入库中..."
  723. let res = await gotoCashPay({
  724. "orderId": orderId, // 订单编号-提交订单返回
  725. "payAmount": this.ruleForm.realPrice
  726. })
  727. if(res.code == 200){
  728. if(this.payTime){
  729. clearInterval(this.payTime)
  730. }
  731. this.payTimeNum = 0
  732. this.payTime = setInterval(()=>{
  733. this.payQueryFun(this.orderId)
  734. },1000)
  735. }else{
  736. this.$message.error('订单入库中失败!!!');
  737. this.loading = false
  738. this.payStatus = 3
  739. }
  740. } catch (error) {
  741. this.$message.error('订单入库中失败!!!');
  742. this.loading = false
  743. this.payStatus = 3
  744. }
  745. },
  746. // 跳转取票界面
  747. goTicketingCollections(){
  748. this.$router.push({
  749. path:"/windowTicketSales/ticketingCollections",
  750. query:{
  751. orderId: this.orderId
  752. }
  753. })
  754. },
  755. /** 查看支付 状态 */
  756. async payQueryFun(orderId){
  757. this.loading = true
  758. try {
  759. this.payTimeNum = this.payTimeNum + 1
  760. if(this.payTimeNum==15){
  761. if(this.payTime){
  762. clearInterval(this.payTime)
  763. }
  764. this.orderInfoCancelFun()
  765. return
  766. }
  767. if(this.ruleForm.paymentType == 2){
  768. this.loadingText = "订单入库中..."
  769. }else {
  770. this.loadingText = "订单支付中..."
  771. }
  772. this.payStatus = ''
  773. let res = await payQuery({
  774. orderId: orderId
  775. })
  776. if(res.code == 200){
  777. if(res.data) {
  778. if(res.data.payStatus == 0) {
  779. if(this.payTime){
  780. clearInterval(this.payTime)
  781. }
  782. if(this.ruleForm.paymentType == 2){
  783. this.$message.error('"订单入库中失败"');
  784. this.loading = false
  785. this.payStatus = 3
  786. }else {
  787. this.$message.error('用户未支付!!!');
  788. this.loading = false
  789. this.payStatus = 7
  790. }
  791. }else if(res.data.payStatus == 1) {
  792. if(this.payTime){
  793. clearInterval(this.payTime)
  794. }
  795. if(this.ruleForm.paymentType == 2){
  796. this.$message({
  797. message: '订单入库成功',
  798. type: 'success'
  799. });
  800. this.loading = false
  801. // this.payStatus = 8
  802. // this.getPrintListApi()
  803. this.goTicketingCollections()
  804. }else {
  805. this.$message({
  806. message: '用户已支付成功,请打印门票',
  807. type: 'success'
  808. });
  809. // 开始 打印
  810. this.loading = false
  811. // this.payStatus = 8
  812. // this.getPrintListApi()
  813. this.goTicketingCollections()
  814. }
  815. }else if(res.data.payStatus == 2) {
  816. }else if(res.data.payStatus == 3) {
  817. if(this.payTime){
  818. clearInterval(this.payTime)
  819. }
  820. if(this.ruleForm.paymentType == 2){
  821. this.$message.error('"订单入库中失败"');
  822. this.loading = false
  823. this.payStatus = 3
  824. }else {
  825. this.$message.error('用户支付失败!!!');
  826. this.loading = false
  827. this.payStatus = 7
  828. }
  829. }else if(res.data.payStatus == 4) {
  830. if(this.payTime){
  831. clearInterval(this.payTime)
  832. }
  833. if(this.ruleForm.paymentType == 2){
  834. this.$message.error('"订单入库中失败"');
  835. this.loading = false
  836. this.payStatus = 3
  837. }else {
  838. this.$message.error('支付退款!!!');
  839. this.loading = false
  840. this.payStatus = 7
  841. }
  842. }
  843. }
  844. }else{
  845. this.$message.error('支付失败!!!');
  846. this.loading = false
  847. this.payStatus = 7
  848. }
  849. } catch (error) {
  850. this.$message.error('支付失败!!!');
  851. this.loading = false
  852. this.payStatus = 7
  853. }
  854. },
  855. /** 连接VBarServer */
  856. vbar_open() {
  857. this.loading = true
  858. this.loadingText = "连接扫码盒子中!!!"
  859. this.payStatus = null
  860. this.websocketClear()
  861. console.log('sdfdsfsd')
  862. if (!this.websocket_connected) {
  863. var host = "ws://localhost:2693";
  864. this.websocketCtrl = new WebSocket(host,'ctrl');
  865. this.websocketData = new WebSocket(host,'data');
  866. this.websocketData.onopen = (evt) => {
  867. console.log('sdasdasd====',evt)
  868. this.loading = false
  869. this.payStatus = 5
  870. this.websocket_connected = true;
  871. this.websocket_open_state(evt);
  872. }
  873. this.websocketData.onerror = (evt) => {
  874. console.log('sdasdasd11111====',evt)
  875. this.payStatus = 6
  876. //this.vbar_open()
  877. }
  878. this.websocketData.onmessage = (evt) => {
  879. console.log("接受消息====",evt)
  880. this.websocket_decode(evt.data);
  881. }
  882. }
  883. //setTimeout(this.vbar_open(), 3000);
  884. },
  885. /** 连接结果 */
  886. websocket_open_state(message){
  887. //document.getElementById('wsocket').value = "已连接";
  888. },
  889. //接收扫码结果处理
  890. websocket_decode(code){
  891. console.log()
  892. if(this.orderId && this.payStatus==5 &&code) {
  893. this.gotoMicroPayFun(this.orderId,code)
  894. }
  895. },
  896. /** 关闭通讯 */
  897. websocketClear(){
  898. if(this.websocketCtrl){
  899. this.websocketCtrl.close()
  900. }
  901. if(this.websocketData){
  902. this.websocketData.close()
  903. }
  904. this.websocket_connected = false
  905. },
  906. /** 读取身份证 */
  907. readCert(){
  908. this.idcardLoading = true
  909. var result = "";
  910. try {
  911. let xmlHttp = new XMLHttpRequest();
  912. let Protocol = window.location.protocol.split(':')[0];
  913. //获取当前协议,并且分割字符串,得到http或者https
  914. if (Protocol === 'https'){
  915. //创建请求 第一个参数是代表以post方式发送;第二个是请求端口和地址;第三个表示是否异步
  916. xmlHttp.open("POST", "http://127.0.0.1:18889/api/readCert?ReadSN=" + 0, false); //readCert读卡,生成正反面仿复印件
  917. }else {
  918. //创建请求 第一个参数是代表以post方式发送;第二个是请求端口和地址;第三个表示是否异步
  919. xmlHttp.open("POST", "http://127.0.0.1:18889/api/readCert?ReadSN=" + 0, false); //readCert读卡,生成正反面仿复印件
  920. }
  921. //发送请求
  922. xmlHttp.send();
  923. if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
  924. result = xmlHttp.responseText;
  925. xmlHttp.readyState = 1;
  926. }
  927. } catch (e) {
  928. console.error("e====",e)
  929. }
  930. let obj = JSON.parse(result)
  931. if(obj.resultContent && obj.resultContent.certNumber){
  932. this.$set(this.tableForm,"idcard",obj.resultContent.certNumber)
  933. this.$set(this.tableForm,"name",obj.resultContent.partyName)
  934. }else {
  935. this.$message.error('读取失败!!!');
  936. }
  937. this.idcardLoading = false
  938. //return result;
  939. console.log(result,obj)
  940. },
  941. /** 查询打印机列表 */
  942. getPrintListApi() {
  943. getPrintListApi({deviceType:5,pageNum: 1,
  944. pageSize: 999,})
  945. .then(response => {
  946. this.printList = response.data.rows;
  947. }).catch((error)=>{
  948. console.log("error===",error)
  949. }
  950. );
  951. },
  952. // 打印
  953. async print(list = []){
  954. if(!this.printListId) {
  955. this.$message.error('请选择打印机!!');
  956. return
  957. }
  958. this.loading = true
  959. this.loadingText = '打印中...'
  960. this.payStatus = ''
  961. try {
  962. let res = await printApi({
  963. orderId: this.orderId,
  964. source: 2,
  965. deviceId: this.printListId
  966. })
  967. if(res.code == 200) {
  968. let url = res.data.linkIp
  969. let printInfo = res.data.printInfo
  970. this.connectPrint(url,printInfo)
  971. }else {
  972. throw new Error(res)
  973. }
  974. } catch (error) {
  975. this.loading = false
  976. this.payStatus = 8
  977. console.error("error=====",error)
  978. }
  979. },
  980. /** 连接打印机 */
  981. connectPrint(url,data){
  982. // 创建忽略 SSL 的 axios 实例
  983. const ignoreSSL = axios.create({
  984. httpsAgent: new https.Agent({
  985. rejectUnauthorized: false
  986. }),
  987. withCredentials: true, // 跨域请求时发送Cookie
  988. timeout: 60000, // 请求超时
  989. headers: {
  990. "Content-Type": "application/json; charset=UTF-8;"
  991. }
  992. });
  993. ignoreSSL.post(url,
  994. { ...data }
  995. ).then(()=>{
  996. this.dialogVisible = false
  997. this.loading = false
  998. }).catch(()=>{
  999. this.loading = false
  1000. this.payStatus = 8
  1001. // this.dialogVisible = false
  1002. // this.loading = false
  1003. })
  1004. // 在 axios 请求时,选择性忽略 SSL
  1005. // const agent = new https.Agent({
  1006. // rejectUnauthorized: false
  1007. // });
  1008. // axios.post(
  1009. // url,
  1010. // { httpsAgent: agent,...data }
  1011. // ).then(()=>{
  1012. // this.dialogVisible = false
  1013. // this.loading = false
  1014. // })
  1015. // .catch(()=>{
  1016. // this.dialogVisible = false
  1017. // this.loading = false
  1018. // })
  1019. },
  1020. }
  1021. }
  1022. </script>
  1023. <style scoped lang="scss">
  1024. .increase-viewers-box {
  1025. width: 100%;
  1026. height: calc( 100vh - 250px );
  1027. box-sizing: border-box;
  1028. overflow: hidden;
  1029. overflow-y: auto;
  1030. position: relative;
  1031. }
  1032. .increase-viewers-pay-status {
  1033. width: 100%;
  1034. height: 100%;
  1035. position: absolute;
  1036. z-index: 999;
  1037. background-color: rgba(0,0,0,0.3);
  1038. top: 0;
  1039. left: 0;
  1040. .increase-viewers-pay-status-info {
  1041. width: 100%;
  1042. height: 100%;
  1043. display: flex;
  1044. flex-direction: column;
  1045. justify-content: center;
  1046. align-items: center;
  1047. color: #fff;
  1048. }
  1049. }
  1050. </style>