index.vue 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106
  1. <template>
  2. <div class="app-container app-container-scheduling" :style="{'--q-height':qHeight}">
  3. <div class="app-container-query" ref="queryFormBox">
  4. <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
  5. <el-form-item v-if="queryShow.orderId" label="订单号">
  6. <el-input v-model="queryParams.orderId" placeholder="请输入订单号" clearable style="width: 240px;"
  7. @keyup.enter.native="handleQuery" />
  8. <span @click="clearQuery('orderId')" class="query_clear"><i class="el-icon-circle-close"></i></span>
  9. </el-form-item>
  10. <el-form-item v-if="queryShow.orderStatus" label="订单状态">
  11. <el-select v-model="queryParams.orderStatus" placeholder="订单状态" clearable style="width: 100%">
  12. <el-option v-for="dict in dict.type.order_status_type" :key="dict.value" :label="dict.label"
  13. :value="dict.value" />
  14. <span @click="clearQuery('orderStatus')" class="query_clear"><i class="el-icon-circle-close"></i></span>
  15. </el-select>
  16. </el-form-item>
  17. <el-form-item v-if="queryShow.seatTypeId" label="座位类型">
  18. <el-select v-model="queryParams.seatTypeId" placeholder="座位类型" clearable style="width: 100%">
  19. <el-option v-for="(item, index) in seatTypeList" :key="item.id" :label="item.name" :value="item.id"></el-option>
  20. </el-select>
  21. <span @click="clearQuery('seatTypeId')" class="query_clear"><i class="el-icon-circle-close"></i></span>
  22. </el-form-item>
  23. <el-form-item v-if="queryShow.source" label="购票渠道">
  24. <el-select v-model="queryParams.source" placeholder="购票渠道" clearable style="width: 100%">
  25. <el-option v-for="dict in dict.type.order_form_type" :key="dict.value" :label="dict.label"
  26. :value="dict.value" />
  27. </el-select>
  28. <span @click="clearQuery('source')" class="query_clear"><i class="el-icon-circle-close"></i></span>
  29. </el-form-item>
  30. <el-form-item v-if="queryShow.qrcodeNo" label="取票码">
  31. <el-input v-model="queryParams.qrcodeNo" placeholder="请输入取票码" clearable style="width: 240px;"
  32. @keyup.enter.native="handleQuery" />
  33. <span @click="clearQuery('qrcodeNo')" class="query_clear"><i class="el-icon-circle-close"></i></span>
  34. </el-form-item>
  35. <el-form-item v-if="queryShow.payTime" label="支付时间">
  36. <!-- <el-date-picker style="width: 230px;" v-model="queryParams.payTime" type="date" value-format="yyyy-MM-dd"
  37. placeholder="支付时间">
  38. </el-date-picker> -->
  39. <el-date-picker
  40. v-model="queryParams.payTime"
  41. type="daterange"
  42. value-format="yyyy-MM-dd"
  43. range-separator="至"
  44. start-placeholder="开始日期"
  45. end-placeholder="结束日期">
  46. </el-date-picker>
  47. <span @click="clearQuery('payTime')" class="query_clear"><i class="el-icon-circle-close"></i></span>
  48. </el-form-item>
  49. <el-form-item v-if="queryShow.performDate" label="场次时间" label-width="70px">
  50. <el-date-picker
  51. style="width: 250px;"
  52. v-model="queryParams.performDate"
  53. @change="pagePerformTimeListFun"
  54. type="daterange"
  55. value-format="yyyy-MM-dd"
  56. range-separator="至"
  57. start-placeholder="开始日期"
  58. end-placeholder="结束日期">
  59. </el-date-picker>
  60. <span @click="clearQuery('performDate')" class="query_clear"><i class="el-icon-circle-close"></i></span>
  61. </el-form-item>
  62. <!-- <el-form-item label="场次时间">
  63. <el-date-picker
  64. style="width: 230px;"
  65. v-model="queryParams.performDate"
  66. @change="pagePerformTimeListFun"
  67. type="date"
  68. value-format="yyyy-MM-dd"
  69. placeholder="选择日期">
  70. </el-date-picker>
  71. </el-form-item> -->
  72. <el-form-item label="场次" v-if="!multiPerformDate && queryShow.performDate">
  73. <el-select v-model="queryParams.performTimeId" placeholder="场次" clearable style="width: 100%">
  74. <el-option
  75. v-for="dict in pagePerformTimeList"
  76. :key="dict.id"
  77. :label="dict.timeSnapshot+'('+dict.performTimeStart+'-'+dict.performTimeEnd+')'"
  78. :value="dict.id" />
  79. </el-select>
  80. <span @click="clearQuery('performDate')" class="query_clear"><i class="el-icon-circle-close"></i></span>
  81. </el-form-item>
  82. <el-form-item>
  83. <el-dropdown @command="openQuery">
  84. <el-button size="mini" type="primary" icon="el-icon-plus"></el-button>
  85. <el-dropdown-menu slot="dropdown">
  86. <el-dropdown-item command="orderId">订单号</el-dropdown-item>
  87. <el-dropdown-item command="orderStatus">订单状态</el-dropdown-item>
  88. <el-dropdown-item command="seatTypeId">座位类型</el-dropdown-item>
  89. <el-dropdown-item command="source">购票渠道</el-dropdown-item>
  90. <el-dropdown-item command="qrcodeNo">取票码</el-dropdown-item>
  91. <el-dropdown-item command="payTime">支付时间</el-dropdown-item>
  92. <el-dropdown-item command="performDate">场次时间/场次</el-dropdown-item>
  93. </el-dropdown-menu>
  94. </el-dropdown>
  95. <el-button style="margin-left: 10px;" type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
  96. <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
  97. </el-form-item>
  98. </el-form>
  99. </div>
  100. <div class="app-container-table-box">
  101. <el-row :gutter="10" class="mb8">
  102. <el-button type="primary" size="mini" icon="el-icon-download" v-hasPermi="['order:viewers:excel']"
  103. @click="handleExport" v-loading.fullscreen.lock="handleExportLoading" element-loading-text="正在拼命生成数据中..."
  104. element-loading-spinner="el-icon-loading" element-loading-background="rgba(0, 0, 0, 0.5)">导出excel</el-button>
  105. <el-button
  106. type="primary"
  107. size="mini"
  108. v-hasPermi="['order:viewers:tuikuai']"
  109. :disabled="multipleSelection.length==0"
  110. @click="openRefundSubmitModel(multipleSelection)">批量退款</el-button>
  111. <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
  112. </el-row>
  113. <div class="app-container-table-info">
  114. <el-table ref="tables" height="100%" @selection-change="handleSelectionChange" v-loading="loading" :data="dataList" border>
  115. <el-table-column
  116. :selectable="isSelectableFun"
  117. type="selection"
  118. :fixed="fixed"
  119. width="55"></el-table-column>
  120. <el-table-column label="订单号" :fixed="fixed" align="center" prop="orderId" />
  121. <el-table-column label="观影人名称" :fixed="fixed" align="center" prop="name" />
  122. <el-table-column label="身份证号" :fixed="fixed" align="center" prop="idcard" />
  123. <el-table-column label="票务名称" :fixed="fixed" align="center" prop="goodsName" />
  124. <el-table-column label="座位类型" :fixed="fixed" align="center" prop="seatTypeName" />
  125. <el-table-column label="购买渠道" :fixed="fixed" align="center" prop="source">
  126. <template slot-scope="scope">
  127. <dict-tag :options="dict.type.order_form_type" :value="scope.row.source" />
  128. </template>
  129. </el-table-column>
  130. <el-table-column label="场次时间" align="center" prop="performDate" />
  131. <el-table-column label="场次" width="120" align="center">
  132. <template slot-scope="scope">
  133. <span>{{ scope.row.performTimeStart + '-' + scope.row.performTimeEnd }}</span>
  134. </template>
  135. </el-table-column>
  136. <el-table-column label="购票人" align="center" prop="memberName" />
  137. <el-table-column label="取票码" align="center" prop="qrcodeNo" width="100" />
  138. <el-table-column label="购票人手机号" align="center" prop="memberMobile" />
  139. <el-table-column label="订单应收总额" align="center">
  140. <template slot-scope="scope">
  141. <span>{{ scope.row.priceTotal || scope.row.priceTotal == 0 ? '¥' + scope.row.priceTotal : '-' }}</span>
  142. </template>
  143. </el-table-column>
  144. <el-table-column label="订单实收总额" align="center">
  145. <template slot-scope="scope">
  146. <span>{{ scope.row.realPriceTotal || scope.row.realPriceTotal == 0 ? '¥' + scope.row.realPriceTotal : '-' }}</span>
  147. </template>
  148. </el-table-column>
  149. <el-table-column label="观影人单价" align="center" prop="realPrice">
  150. <template slot-scope="scope">
  151. <span>{{ scope.row.realPrice || scope.row.realPrice == 0 ? '¥' + scope.row.realPrice : '-' }}</span>
  152. </template>
  153. </el-table-column>
  154. <el-table-column label="支付方式" align="center" prop="payWay">
  155. <template slot-scope="scope">
  156. <dict-tag :options="dict.type.pay_way_type" :value="scope.row.payWay" />
  157. </template>
  158. </el-table-column>
  159. <el-table-column label="支付时间" align="center" prop="payTime" width="160">
  160. <template slot-scope="scope">
  161. <span>{{ parseTime(scope.row.payTime) }}</span>
  162. </template>
  163. </el-table-column>
  164. <el-table-column label="订单状态" align="center">
  165. <template slot-scope="scope">
  166. <dict-tag :options="dict.type.order_status_type" :value="scope.row.status" />
  167. </template>
  168. </el-table-column>
  169. <el-table-column label="核销渠道" align="center" prop="deviceName" />
  170. <el-table-column label="人员类别" align="center">
  171. <template slot-scope="scope">
  172. <dict-tag :options="dict.type.personnel_type" :value="scope.row.identity" />
  173. </template>
  174. </el-table-column>
  175. <el-table-column label="打印次数/次" align="center" prop="ticketPrintTotal" />
  176. <el-table-column label="备注" align="center" prop="remark" />
  177. <el-table-column label="操作" align="center" width="100" class-name="small-padding fixed-width">
  178. <template slot-scope="scope">
  179. <el-button size="mini" type="text" @click="openDetails(scope.row)"
  180. v-hasPermi="['order:viewers:details']">详情</el-button>
  181. <span v-hasPermi="['order:viewers:print']" style="display: inline-block;">
  182. <el-button
  183. style="margin-left: 10px;"
  184. v-if="scope.row.status == 3 || scope.row.status == 7" size="mini" type="text"
  185. @click="handleOpen([scope.row])"
  186. >打印</el-button>
  187. </span>
  188. <span v-hasPermi="['order:viewers:tuikuai']" style="display: inline-block;">
  189. <el-button
  190. style="margin-left: 10px;"
  191. v-if="(scope.row.status == 3 || scope.row.status == 6 || scope.row.status == 7 || scope.row.status == 8) && scope.row.source != 1 && scope.row.source != 6" size="mini" type="text"
  192. @click="openRefundSubmitModel([scope.row])"
  193. >退款</el-button>
  194. </span>
  195. </template>
  196. </el-table-column>
  197. </el-table>
  198. <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
  199. @pagination="getList" />
  200. </div>
  201. </div>
  202. <!-- 详情 -->
  203. <details-dia ref="detailsDia" @getList="getList"></details-dia>
  204. <!-- 打印 -->
  205. <el-dialog title="选择小票机" :visible.sync="dialogVisible" width="30%" :before-close="handleClose">
  206. <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
  207. <el-form-item label="小票机" prop="region">
  208. <el-select v-model="ruleForm.region" placeholder="选择小票机">
  209. <el-option :label="item.deviceName" :key="item.id" :value="item.id"
  210. v-for="(item, index) in printList"></el-option>
  211. </el-select>
  212. </el-form-item>
  213. </el-form>
  214. <span slot="footer" class="dialog-footer">
  215. <el-button @click="dialogVisible = false">取 消</el-button>
  216. <el-button type="primary" :loading="dialogVisibleLoading" @click="print(viewerList)">{{
  217. dialogVisibleLoading ? '打印中...' : '打印' }}</el-button>
  218. </span>
  219. </el-dialog>
  220. <!-- 退款 -->
  221. <el-dialog
  222. title="退款提示"
  223. :visible.sync="tkDialogVisible"
  224. width="80%"
  225. :before-close="handleCloseTk"
  226. :modal-append-to-body="false"
  227. :show-close="!tkDialogVisibleLoading"
  228. >
  229. <div style="width: 100%;height: calc( 100vh - 30vh );overflow: hidden;overflow-y: auto;">
  230. <div style=" width: 100%;box-sizing: border-box;padding-left: 40px;">
  231. <el-table
  232. :data="tkSelectList"
  233. style="width: 100%">
  234. <el-table-column
  235. type="index"
  236. label="序号"
  237. >
  238. </el-table-column>
  239. <el-table-column
  240. prop="orderId"
  241. label="订单号"
  242. >
  243. </el-table-column>
  244. <el-table-column
  245. label="退款人数"
  246. >
  247. <template slot-scope="scope">
  248. <span>{{ scope.row.viewerList.length }}</span>
  249. </template>
  250. </el-table-column>
  251. <el-table-column
  252. prop="refundAmount"
  253. label="退款金额"
  254. >
  255. </el-table-column>
  256. <el-table-column
  257. label="原订单金额"
  258. >
  259. <template slot-scope="scope">
  260. <span>{{ scope.row.orgRealPrice }}</span>
  261. </template>
  262. </el-table-column>
  263. <el-table-column
  264. prop="address"
  265. label="状态">
  266. <template slot-scope="scope">
  267. <span
  268. :style="{
  269. color: refundSubmitAction == scope.row.orderId?'#409eff':
  270. refundSubmitSuccess.includes(scope.row.orderId)?'#67c23a':
  271. refundSubmitError.includes(scope.row.orderId)?'#f56c6c':
  272. '#000'
  273. }"
  274. >
  275. {{
  276. refundSubmitAction == scope.row.orderId?'退款提交中...':
  277. refundSubmitSuccess.includes(scope.row.orderId)?'退款提交成功':
  278. refundSubmitError.includes(scope.row.orderId)?'退款提交失败':
  279. '等待退款提交...' }}
  280. </span>
  281. </template>
  282. </el-table-column>
  283. <el-table-column
  284. prop="errorRemark"
  285. label="退款失败原因"
  286. >
  287. </el-table-column>
  288. <el-table-column label="操作">
  289. <template slot-scope="scope">
  290. <el-button
  291. v-if="!tkDialogVisibleLoading"
  292. type="danger"
  293. size="mini"
  294. @click="deleteSelect(scope.$index, scope.row)">移除</el-button>
  295. </template>
  296. </el-table-column>
  297. </el-table>
  298. </div>
  299. <div style="width: 100%;box-sizing: border-box;">
  300. <el-form :disabled="tkDialogVisibleLoading" :model="tkRuleForm" :rules="tkRules" ref="tkRuleForm" label-width="100px" class="demo-ruleForm">
  301. <el-form-item label="" label-width="0">
  302. <span style="font-weight: 600;margin-left: 40px;">订单合计{{ tkSelectList.length }}笔,</span>
  303. <span style="font-weight: 600;">退款人数合计{{ tkRuleForm.refundPeople }}人,</span>
  304. <span style="font-weight: 600;">退款金额合计¥{{ tkRuleForm.refundAmountAll }}</span>
  305. </el-form-item>
  306. <el-form-item label="退款原因" prop="refundReason">
  307. <el-input
  308. type="textarea"
  309. :rows="3"
  310. v-model="tkRuleForm.refundReason"></el-input>
  311. </el-form-item>
  312. <el-form-item label="备注" prop="remark">
  313. <el-input
  314. type="textarea"
  315. :rows="3"
  316. v-model="tkRuleForm.remark"></el-input>
  317. </el-form-item>
  318. </el-form>
  319. </div>
  320. </div>
  321. <span slot="footer" class="dialog-footer">
  322. <el-button :loading="tkDialogVisibleLoading" @click="handleCloseTk('tkRuleForm')">取 消</el-button>
  323. <el-button
  324. :loading="tkDialogVisibleLoading"
  325. type="primary"
  326. @click="tkSubmitForm('tkRuleForm')"
  327. v-if="refundSubmitSuccess.length != tkSelectList.length && tkSelectList.length>0"
  328. >{{
  329. tkDialogVisibleLoading ? '退款中...':
  330. refundSubmitError.length > 0? '继续提交失败订单':
  331. '确定退款'
  332. }}</el-button>
  333. </span>
  334. </el-dialog>
  335. </div>
  336. </template>
  337. <script>
  338. import { pageList, downOrderListXls, printApi, refundSubmitApi } from '@/api/order/viewers'
  339. import detailsDia from "./dialog/details";
  340. import { pagePerformTimeList } from "@/api/schedulingMr/schedulingMr"
  341. import { exportExcel } from '@/utils/exportexcel'
  342. import { pageList as getPrintListApi } from "@/api/device/pda";
  343. import { pageList as getSeatTypeList } from '@/api/seatTypeMr/seatTypeMr'
  344. const https = require('https');
  345. const axios = require('axios');
  346. const mathM = require('mathjs')
  347. import moment from "moment"
  348. export default {
  349. name: "Viewers",
  350. dicts: ['order_form_type', 'order_status_type', 'pay_way_type', 'personnel_type'],
  351. components: { detailsDia },
  352. data() {
  353. return {
  354. qHeight: '0px',
  355. resizeObserver: null,
  356. // 遮罩层
  357. loading: true,
  358. // 选中数组
  359. ids: [],
  360. // 非单个禁用
  361. single: true,
  362. // 非多个禁用
  363. multiple: true,
  364. // 显示搜索条件
  365. showSearch: true,
  366. // 总条数
  367. total: 0,
  368. // 用户表格数据
  369. dataList: [],
  370. // 弹出层标题
  371. title: "",
  372. // 是否显示弹出层
  373. open: false,
  374. // 查询参数
  375. queryParams: {
  376. pageNum: 1,
  377. pageSize: 10,
  378. },
  379. visibleStatus: false,
  380. newObj: {},
  381. visibleType: '',
  382. pagePerformTimeList: [], // 场次列表
  383. handleExportLoading: false,
  384. viewerList: [],
  385. printList: [],
  386. dialogVisible: false,
  387. ruleForm: {},
  388. rules: {
  389. region: [
  390. { required: true, message: '请选择备注', trigger: ['change', 'blur'] }
  391. ],
  392. },
  393. dialogVisibleLoading: false,
  394. seatTypeList: [],
  395. multipleSelection: [],
  396. tkDialogVisible: false,
  397. tkDialogVisibleLoading: false,
  398. tkSelectList: [],
  399. tkRuleForm: {
  400. "orderId": null,
  401. "refundReason": null,
  402. "remark": null,
  403. "refundAmount": 0,
  404. "ifDirectRefund": 1,
  405. "refundPeople": 0,
  406. "errorRemark": '',
  407. "viewerList": [
  408. {
  409. "viewerId": "1111",
  410. "salePrice": 0.01
  411. }
  412. ]
  413. },
  414. tkRules: {
  415. refundReason: [{ required: true, message: '请输入退款原因', trigger: ['blur', 'change'] }],
  416. remark: [{ required: false, message: '请输入备注', trigger: ['blur', 'change'] }],
  417. },
  418. refundSubmitAction: null,
  419. refundSubmitSuccess:[], // 成功条数
  420. refundSubmitError: [], // 失败条数
  421. refundSubmitErrorList: [], //
  422. multiPerformDate:false,
  423. fixed: 'left',
  424. queryShow: {
  425. orderId: true,
  426. orderStatus: true,
  427. seatTypeId: false,
  428. source: false,
  429. qrcodeNo: false,
  430. payTime: false,
  431. performDate: true
  432. },
  433. };
  434. },
  435. created() {
  436. //this.$set(this.queryParams,'performDate',[moment().format("yyyy-MM-DD"),moment().format("yyyy-MM-DD")])
  437. this.getSeatTypeListFun()
  438. //this.$set(this.queryParams,'performDate',moment().format("yyyy-MM-DD"))
  439. this.$set(this.queryParams,'performDate',[moment().format("yyyy-MM-DD"),moment().format("yyyy-MM-DD")])
  440. this.pagePerformTimeListFun(this.queryParams.performDate)
  441. this.getList();
  442. },
  443. activated(){
  444. this.getList();
  445. },
  446. mounted() {
  447. this.resizeObserver = new ResizeObserver(entries => {
  448. for (let entry of entries) {
  449. const { width, height } = entry.contentRect;
  450. this.qHeight = height + 'px'
  451. }
  452. if(document.body.clientWidth<765) {
  453. this.fixed = false
  454. }else {
  455. this.fixed = 'left'
  456. }
  457. });
  458. this.resizeObserver.observe(this.$refs.queryFormBox);
  459. },
  460. methods: {
  461. /** 查询列表 */
  462. getList() {
  463. this.loading = true;
  464. let params = {...this.addDateRange(this.queryParams, this.dateRange)};
  465. if(params.performDate&&params.performDate.length==2){
  466. params.performBeginDate = params.performDate[0];
  467. params.performEndDate = params.performDate[1];
  468. }
  469. delete params.performDate;
  470. pageList(this.addDateRange(params))
  471. .then(response => {
  472. this.dataList = response.data.rows;
  473. this.total = response.data.total;
  474. this.loading = false;
  475. }).catch(()=>{
  476. this.dataList = []
  477. this.total = 0
  478. this.loading = false;
  479. })
  480. },
  481. // 取消按钮
  482. cancel() {
  483. this.open = false;
  484. },
  485. /** 搜索按钮操作 */
  486. handleQuery() {
  487. this.queryParams.pageNum = 1;
  488. if (this.queryParams.time) {
  489. this.queryParams.beginTime = this.queryParams.time[0];
  490. this.queryParams.endTime = this.queryParams.time[1];
  491. }else {
  492. this.queryParams.beginTime = null
  493. this.queryParams.endTime = null
  494. }
  495. if (this.queryParams.createTime && this.queryParams.createTime.length > 0) {
  496. this.queryParams.createBeginTime = this.queryParams.createTime[0];
  497. this.queryParams.createEndTime = this.queryParams.createTime[1];
  498. }else {
  499. this.queryParams.createBeginTime = null
  500. this.queryParams.createEndTime = null
  501. }
  502. if (this.queryParams.payTime && this.queryParams.payTime.length > 0) {
  503. this.queryParams.payBeginTime = this.queryParams.payTime[0];
  504. this.queryParams.payEndTime = this.queryParams.payTime[1];
  505. }else {
  506. this.queryParams.payBeginTime = null
  507. this.queryParams.payEndTime = null
  508. }
  509. this.getList();
  510. },
  511. /** 重置按钮操作 */
  512. resetQuery() {
  513. this.queryParams = {
  514. pageNum: 1,
  515. pageSize: 10,
  516. }
  517. // this.$set(this.queryParams, 'orderId', '');
  518. // this.$set(this.queryParams, 'status', '');
  519. // this.$set(this.queryParams, 'memberMobile', '');
  520. // this.$set(this.queryParams, 'source', '');
  521. // this.$set(this.queryParams, 'performName', '');
  522. // this.$set(this.queryParams, 'payBeginTime', '');
  523. // this.$set(this.queryParams, 'payEndTime', '');
  524. // this.$set(this.queryParams, 'time', '');
  525. // this.$set(this.queryParams, 'createTime', '');
  526. // this.$set(this.queryParams, 'createBeginTime', '');
  527. // this.$set(this.queryParams, 'createEndTime', '');
  528. // this.$set(this.queryParams, 'goodsName', '');
  529. // this.$set(this.queryParams, 'performDate', '');
  530. // this.$set(this.queryParams, 'timeSnapshot', '');
  531. // this.$set(this.queryParams, 'performTimeId', '');
  532. // this.queryParams.pageNum = 1;
  533. this.handleQuery();
  534. },
  535. /** 详情按钮操作 */
  536. openDetails(row, type) {
  537. this.$refs["detailsDia"].openDialog("详情", row, type);
  538. },
  539. async pagePerformTimeListFun(value) {
  540. // console.log('value',value);
  541. try {
  542. this.pagePerformTimeList = []
  543. this.$set(this.queryParams,'performTimeId',null)
  544. if(!value){
  545. return
  546. }
  547. if(value.length==2&&value[0]==value[1]){
  548. this.multiPerformDate = false
  549. }else{
  550. this.multiPerformDate = true
  551. return
  552. }
  553. let { data,code } = await pagePerformTimeList({
  554. performDate: value[0],
  555. pageNum: 1,
  556. pageSize: 999
  557. })
  558. this.pagePerformTimeList = [].concat(data.rows)
  559. } catch (error) {
  560. }
  561. },
  562. /**
  563. * 导出报表
  564. * @date 2022-10-24
  565. * @returns {any}
  566. */
  567. handleExport() {
  568. this.$confirm('您确定要导出当前查询的数据吗?', '提示', {
  569. confirmButtonText: '确定 ',
  570. cancelButtonText: '取消 ',
  571. type: 'warning'
  572. })
  573. .then(() => {
  574. this.handleExportLoading = true;
  575. // const { pageNum, pageSize} = this.params;
  576. let postMap = {}
  577. if (this.queryParams.time) {
  578. this.queryParams.beginTime = this.queryParams.time[0];
  579. this.queryParams.endTime = this.queryParams.time[1];
  580. }else {
  581. this.queryParams.beginTime = null
  582. this.queryParams.endTime = null
  583. }
  584. if (this.queryParams.createTime && this.queryParams.createTime.length > 0) {
  585. this.queryParams.createBeginTime = this.queryParams.createTime[0];
  586. this.queryParams.createEndTime = this.queryParams.createTime[1];
  587. }else {
  588. this.queryParams.createBeginTime = null
  589. this.queryParams.createEndTime = null
  590. }
  591. if (this.queryParams.payTime && this.queryParams.payTime.length > 0) {
  592. this.queryParams.payBeginTime = this.queryParams.payTime[0];
  593. this.queryParams.payEndTime = this.queryParams.payTime[1];
  594. }else {
  595. this.queryParams.payBeginTime = null
  596. this.queryParams.payEndTime = null
  597. }
  598. if(this.queryParams.performDate){
  599. this.queryParams.performBeginDate = this.queryParams.performDate[0];
  600. this.queryParams.performEndDate = this.queryParams.performDate[1];
  601. }else {
  602. this.queryParams.performBeginDate = null
  603. this.queryParams.performEndDate = null
  604. }
  605. let params = JSON.parse(JSON.stringify(this.queryParams))
  606. for (let key in params) {
  607. if(key != 'pageNum' && key != 'pageSize' && key != 'time' && key != 'createTime' && key != 'payTime' && key != 'performDate'){
  608. postMap[key] = params[key]
  609. }
  610. }
  611. downOrderListXls(postMap)
  612. .then((res) => {
  613. exportExcel(res, '订单管理', '.xlsx');
  614. this.handleExportLoading = false;
  615. })
  616. .catch((error) => {
  617. console.log("error===", error)
  618. this.handleExportLoading = false;
  619. });
  620. })
  621. .catch(() => {
  622. this.$message.info('您已取消导出!');
  623. });
  624. },
  625. handleOpen(list = []) {
  626. if (!list || list.length == 0) return
  627. let idList = []
  628. list.forEach((item, index) => {
  629. idList.push(item.id)
  630. })
  631. this.viewerList = idList
  632. this.getPrintListApi()
  633. this.$set(this.ruleForm, 'region', '');
  634. this.$nextTick(() => {
  635. this.$refs.ruleForm.clearValidate('region')
  636. })
  637. this.dialogVisible = true
  638. },
  639. handleClose() {
  640. this.dialogVisible = false
  641. },
  642. /** 查询打印机列表 */
  643. getPrintListApi() {
  644. getPrintListApi({
  645. deviceType: 5, pageNum: 1,
  646. pageSize: 999,
  647. })
  648. .then(response => {
  649. this.printList = response.data.rows;
  650. }
  651. );
  652. },
  653. /** 选择打印机 */
  654. selectPrint() {
  655. },
  656. // 打印
  657. async print(list = []) {
  658. this.$refs.ruleForm.validate(async (valid) => {
  659. if (valid) {
  660. this.dialogVisibleLoading = true
  661. try {
  662. let res = await printApi({
  663. viewerList: list,
  664. source: 2,
  665. deviceId: this.ruleForm.region
  666. })
  667. if (res.code == 200) {
  668. let url = res.data.linkIp
  669. let printInfo = res.data.printInfo
  670. this.connectPrint(url, printInfo)
  671. } else {
  672. throw new Error(res)
  673. }
  674. } catch (error) {
  675. this.dialogVisible = false
  676. this.dialogVisibleLoading = false
  677. console.error("error=====", error)
  678. }
  679. } else {
  680. console.log('error submit!!');
  681. return false;
  682. }
  683. });
  684. },
  685. /** 连接打印机 */
  686. connectPrint(url, data) {
  687. // 创建忽略 SSL 的 axios 实例
  688. const ignoreSSL = axios.create({
  689. httpsAgent: new https.Agent({
  690. rejectUnauthorized: false
  691. }),
  692. withCredentials: true, // 跨域请求时发送Cookie
  693. timeout: 60000, // 请求超时
  694. headers: {
  695. "Content-Type": "application/json; charset=UTF-8;"
  696. }
  697. });
  698. ignoreSSL.post(url,
  699. { ...data }
  700. ).then(() => {
  701. this.dialogVisible = false
  702. this.dialogVisibleLoading = false
  703. }).catch(() => {
  704. this.dialogVisible = false
  705. this.dialogVisibleLoading = false
  706. })
  707. },
  708. /** 获取座位类型 */
  709. async getSeatTypeListFun() {
  710. try {
  711. let res = await getSeatTypeList({
  712. pageNum: 1, pageSize: 999
  713. })
  714. this.seatTypeList = res.data.rows
  715. } catch (error) {
  716. }
  717. },
  718. /** 打开弹窗 */
  719. openRefundSubmitModel(data, type) {
  720. // 判断是否需要弹出确认框
  721. let needsConfirmation = data.some(item => item.source === 20 || item.source === 3);
  722. // 弹出确认框的逻辑
  723. const showConfirmationDialog = () => {
  724. return this.$confirm(`请确认在OTA平台中已完成对应订单的退款操作流程,否则修改后无法恢复,请谨慎修改!`, '警告', {
  725. confirmButtonText: '确认退款',
  726. cancelButtonText: '取消',
  727. type: 'warning'
  728. });
  729. };
  730. // 构建订单列表的逻辑
  731. const buildOrderList = (data) => {
  732. let list = [];
  733. data.forEach(item => {
  734. let existingOrder = list.find(order => order.orderId === item.orderId);
  735. if (!existingOrder) {
  736. list.push({
  737. orderId: item.orderId,
  738. refundReason: null,
  739. remark: null,
  740. refundAmount: 0,
  741. refundPeople: 0,
  742. ifDirectRefund: 1,
  743. errorRemark: '',
  744. viewerList: [
  745. {
  746. viewerId: item.id,
  747. salePrice: item.realPrice ? item.realPrice : 0
  748. }
  749. ]
  750. });
  751. } else {
  752. existingOrder.viewerList.push({
  753. viewerId: item.id,
  754. salePrice: item.realPrice ? item.realPrice : 0
  755. });
  756. }
  757. });
  758. return list;
  759. };
  760. // 计算退款总额和人数的逻辑
  761. const calculateRefunds = (list) => {
  762. let refundAmountAll = 0;
  763. let refundPeople = 0;
  764. list.forEach(item => {
  765. let refundAmount = 0;
  766. item.viewerList.forEach(viewer => {
  767. refundAmount = mathM.format(Number(refundAmount) + Number(viewer.salePrice), 10);
  768. refundAmountAll = mathM.format(Number(refundAmountAll) + Number(viewer.salePrice), 10);
  769. if(viewer.orgRealPrice) {
  770. refundAmountAll = mathM.format(Number(refundAmountAll) + Number(viewer.orgRealPrice), 10);
  771. }
  772. });
  773. item.refundAmount = refundAmount;
  774. refundPeople += item.viewerList.length;
  775. });
  776. return { refundAmountAll, refundPeople };
  777. };
  778. // 更新表单数据和列表数据的逻辑
  779. const updateFormAndList = (refundAmountAll, refundPeople, list) => {
  780. this.tkRuleForm['refundAmountAll'] = refundAmountAll;
  781. this.tkRuleForm['refundPeople'] = refundPeople;
  782. this.tkSelectList = JSON.parse(JSON.stringify(list));
  783. console.log("Updated list:", this.tkSelectList);
  784. this.tkDialogVisible = true;
  785. };
  786. const executeRefundProcess = () => {
  787. this.refundSubmitSuccess = [];
  788. this.refundSubmitError = [];
  789. let orderList = buildOrderList(data);
  790. let { refundAmountAll, refundPeople } = calculateRefunds(orderList);
  791. updateFormAndList(refundAmountAll, refundPeople, orderList);
  792. };
  793. if (needsConfirmation) {
  794. showConfirmationDialog()
  795. .then(() => {
  796. // 用户点击了确认退款,执行以下逻辑
  797. executeRefundProcess();
  798. })
  799. .catch(() => {
  800. // 用户点击了取消,给出取消信息
  801. this.$message({
  802. type: 'info',
  803. message: '已取消'
  804. });
  805. });
  806. } else {
  807. // 不需要确认退款,直接执行退款流程
  808. executeRefundProcess();
  809. }
  810. },
  811. deleteSelect(index,row){
  812. let refundAmountAll = 0
  813. let refundPeople = 0
  814. let list = JSON.parse(JSON.stringify(this.tkSelectList))
  815. /** 清除成功 */
  816. let listCopy = JSON.parse(JSON.stringify(this.refundSubmitSuccess))
  817. this.refundSubmitSuccess.forEach((item,index1)=>{
  818. if(item == row.orderId) {
  819. listCopy.splice(index1,1)
  820. }
  821. })
  822. this.refundSubmitSuccess = listCopy
  823. /** 清除失败 */
  824. let listCopy1 = JSON.parse(JSON.stringify(this.refundSubmitError))
  825. this.refundSubmitError.forEach((item,index1)=>{
  826. if(item == row.orderId) {
  827. listCopy1.splice(index1,1)
  828. }
  829. })
  830. this.refundSubmitError = listCopy1
  831. list.splice(index,1)
  832. list.forEach((item,index)=>{
  833. if(item.viewerList && item.viewerList.length > 0){
  834. let refundAmount = 0
  835. refundPeople = refundPeople + item.viewerList.length
  836. item.viewerList.forEach((item1,index1)=>{
  837. refundAmount = mathM.format(Number(refundAmount) + Number(item1.salePrice),10)
  838. refundAmountAll = mathM.format(Number(refundAmountAll) + Number(item1.salePrice),10)
  839. })
  840. list[index].refundAmount = refundAmount
  841. }
  842. })
  843. this.tkRuleForm['refundAmountAll'] = refundAmountAll
  844. this.tkRuleForm['refundPeople'] = refundPeople
  845. this.tkSelectList = JSON.parse(JSON.stringify(list))
  846. },
  847. /** 提交退款 */
  848. tkSubmitForm(formName) {
  849. this.$refs[formName].validate((valid) => {
  850. if (valid) {
  851. let listCopy = JSON.parse(JSON.stringify(this.tkSelectList))
  852. this.tkSelectList.forEach((item,index)=>{
  853. listCopy[index] = {
  854. ...item,
  855. refundReason: this.tkRuleForm.refundReason?this.tkRuleForm.refundReason:'',
  856. remark: this.tkRuleForm.remark?this.tkRuleForm.remark:''
  857. }
  858. })
  859. this.tkSelectList = listCopy
  860. //this.refundSubmitFun(0)
  861. if(this.refundSubmitError && this.refundSubmitError.length>0) {
  862. let list = []
  863. this.refundSubmitError.forEach((item,index)=>{
  864. this.tkSelectList.forEach((item1,index1)=>{
  865. if(item == item1.orderId){
  866. list.push(item1)
  867. }
  868. })
  869. })
  870. this.refundSubmitError = []
  871. this.refundSubmitErrorList = list
  872. console.log("this.refundSubmitErrorList===",list)
  873. this.moreRefundSubmitFun(0)
  874. }else {
  875. this.refundSubmitFun(0)
  876. }
  877. } else {
  878. console.log('error submit!!');
  879. return false;
  880. }
  881. });
  882. },
  883. /** 批量退票 */
  884. async refundSubmitFun(index) {
  885. try {
  886. this.tkDialogVisibleLoading = true
  887. this.refundSubmitAction = this.tkSelectList[index].orderId
  888. let res = await refundSubmitApi({
  889. ...this.tkSelectList[index]
  890. })
  891. this.refundSubmitAction = null
  892. if(res.code == 200) {
  893. this.$set(this.tkSelectList[index],'errorRemark','')
  894. this.refundSubmitSuccess.push(this.tkSelectList[index].orderId)
  895. }else {
  896. this.refundSubmitError.push(this.tkSelectList[index].orderId)
  897. this.$message.error(`订单号:${this.tkSelectList[index].orderId},退款提交失败`);
  898. this.$set(this.tkSelectList[index],'errorRemark',res.msg)
  899. }
  900. if((index+1) < this.tkSelectList.length) {
  901. this.refundSubmitAction = this.tkSelectList[index+1].orderId
  902. setTimeout(() => {
  903. this.refundSubmitFun(index+1)
  904. }, 3000);
  905. }else {
  906. this.tkDialogVisibleLoading = false
  907. if(this.refundSubmitError.length == 0) {
  908. this.$message({
  909. message: '全部退款提交成功!!!',
  910. type: 'success'
  911. });
  912. // this.handleCloseTk()
  913. }
  914. }
  915. } catch (error) {
  916. console.error(index+"===error====",error)
  917. this.refundSubmitAction = null
  918. this.refundSubmitError.push(this.tkSelectList[index].orderId)
  919. this.$message.error(`订单号:${this.tkSelectList[index].orderId},退款提交失败`);
  920. this.$set(this.tkSelectList[index],'errorRemark',error?error.message||error.title||error.msg||error:'系统问题')
  921. if((index+1) < this.tkSelectList.length) {
  922. this.refundSubmitAction = this.tkSelectList[index+1].orderId
  923. setTimeout(() => {
  924. this.refundSubmitFun(index+1)
  925. }, 3000);
  926. }else {
  927. this.tkDialogVisibleLoading = false
  928. }
  929. }
  930. },
  931. /** 再次 批量退票 */
  932. async moreRefundSubmitFun(index) {
  933. try {
  934. this.tkDialogVisibleLoading = true
  935. this.refundSubmitAction = this.refundSubmitErrorList[index].orderId
  936. let res = await refundSubmitApi({
  937. ...this.refundSubmitErrorList[index]
  938. })
  939. this.refundSubmitAction = null
  940. if(res.code == 200) {
  941. this.tkSelectList.forEach((item1,index1)=>{
  942. if(this.refundSubmitErrorList[index].orderId == item1.orderId){
  943. this.$set(this.tkSelectList[index1],'errorRemark','')
  944. }
  945. })
  946. this.refundSubmitSuccess.push(this.refundSubmitErrorList[index].orderId)
  947. }else {
  948. this.refundSubmitError.push(this.refundSubmitErrorList[index].orderId)
  949. this.$message.error(`订单号:${this.refundSubmitErrorList[index].orderId},退款提交失败`);
  950. this.tkSelectList.forEach((item1,index1)=>{
  951. if(this.refundSubmitErrorList[index].orderId == item1.orderId){
  952. this.$set(this.tkSelectList[index1],'errorRemark',res.msg)
  953. }
  954. })
  955. }
  956. if((index+1) < this.refundSubmitErrorList.length) {
  957. this.refundSubmitAction = this.refundSubmitErrorList[index+1].orderId
  958. setTimeout(() => {
  959. this.moreRefundSubmitFun(index+1)
  960. }, 3000);
  961. }else {
  962. this.tkDialogVisibleLoading = false
  963. if(this.refundSubmitErrorList.length == 0) {
  964. this.$message({
  965. message: '全部退款成功!!!',
  966. type: 'success'
  967. });
  968. // this.handleCloseTk()
  969. }
  970. }
  971. } catch (error) {
  972. console.error(index+"===error====",error)
  973. console.error("dsfsdfds===",(index+1) < this.refundSubmitErrorList.length
  974. )
  975. this.refundSubmitAction = null
  976. this.refundSubmitError.push(this.refundSubmitErrorList[index].orderId)
  977. this.$message.error(`订单号:${this.refundSubmitErrorList[index].orderId},退款提交失败`);
  978. this.tkSelectList.forEach((item1,index1)=>{
  979. if(this.refundSubmitErrorList[index].orderId == item1.orderId){
  980. this.$set(this.tkSelectList[index1],'errorRemark', error?error.message||error.title||error.msg||error:'系统问题')
  981. }
  982. })
  983. if((index+1) < this.refundSubmitErrorList.length) {
  984. this.refundSubmitAction = this.refundSubmitErrorList[index+1].orderId
  985. setTimeout(() => {
  986. this.moreRefundSubmitFun(index+1)
  987. }, 3000);
  988. }else {
  989. this.tkDialogVisibleLoading = false
  990. }
  991. }
  992. },
  993. /** 退款状态 */
  994. refundSubmitStatus(row){
  995. },
  996. /** 选择 */
  997. handleSelectionChange(val) {
  998. this.multipleSelection = val;
  999. },
  1000. /** 是否可用 */
  1001. isSelectableFun(row, index){
  1002. return row.status == 3 || row.status == 6 || row.status == 7 || row.status == 8
  1003. },
  1004. handleCloseTk(formName){
  1005. console.log('dsfsdfsdf')
  1006. this.tkDialogVisible = false
  1007. if(this.$refs.tkRuleForm) {
  1008. this.$refs.tkRuleForm.resetFields()
  1009. }
  1010. this.getList();
  1011. },
  1012. clearQuery(key) {
  1013. this.$set(this.queryShow,key,false)
  1014. this.$set(this.queryParams,key,'')
  1015. if(key == 'performDate') {
  1016. this.$set(this.queryParams,'performTimeId','')
  1017. }
  1018. },
  1019. openQuery(key) {
  1020. this.$set(this.queryShow,key,true)
  1021. }
  1022. },
  1023. beforeDestroy() {
  1024. this.resizeObserver.unobserve(this.$refs.queryFormBox);
  1025. this.resizeObserver.disconnect();
  1026. },
  1027. };
  1028. </script>
  1029. <style scoped lang="scss">
  1030. .app-container {
  1031. height: calc( 100vh - 110px );
  1032. box-sizing: border-box;
  1033. }
  1034. .app-container-query {
  1035. }
  1036. .app-container-table-box {
  1037. height: calc( 100% - var(--q-height) );
  1038. .app-container-table-info {
  1039. height: calc( 100% - 100px );
  1040. }
  1041. }
  1042. .app-container-scheduling ::v-deep .el-select__tags {
  1043. flex-wrap: inherit !important;
  1044. overflow-x: auto !important;
  1045. }
  1046. .app-container-scheduling ::v-deep .el-form-item__content {
  1047. position: relative;
  1048. }
  1049. .app-container-scheduling ::v-deep .el-form-item__content .query_clear{
  1050. position: absolute;
  1051. top: -15px;
  1052. right: -10px;
  1053. display: none;
  1054. cursor: pointer;
  1055. z-index: 99;
  1056. }
  1057. .app-container-scheduling ::v-deep .el-form-item__content:hover .query_clear {
  1058. display: block;
  1059. }
  1060. </style>