increaseViewers.vue 51 KB

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