index.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621
  1. <template>
  2. <div class="app-container">
  3. <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
  4. <el-form-item label="订单号">
  5. <el-input
  6. v-model="queryParams.id"
  7. placeholder="请输入订单号"
  8. clearable
  9. style="width: 240px;"
  10. @keyup.enter.native="handleQuery"
  11. />
  12. </el-form-item>
  13. <el-form-item label="团队名称" label-width="100px">
  14. <el-input
  15. v-model="queryParams.teamName"
  16. placeholder="请输入团队名称"
  17. clearable
  18. style="width: 240px;"
  19. @keyup.enter.native="handleQuery"
  20. />
  21. </el-form-item>
  22. <el-form-item label="团队类型">
  23. <el-select
  24. v-model="queryParams.teamTypeId"
  25. placeholder="团队类型"
  26. clearable
  27. style="width: 240px"
  28. >
  29. <el-option
  30. v-for="dict in dict.type.team_type"
  31. :key="dict.value"
  32. :label="dict.label"
  33. :value="dict.value"
  34. />
  35. </el-select>
  36. </el-form-item>
  37. <el-form-item label="订单状态">
  38. <el-select
  39. v-model="queryParams.status"
  40. placeholder="订单状态"
  41. clearable
  42. style="width: 100%"
  43. >
  44. <el-option
  45. v-for="dict in statusMapList"
  46. :key="dict.value"
  47. :label="dict.name"
  48. :value="dict.value"
  49. />
  50. </el-select>
  51. </el-form-item>
  52. <el-form-item label="支付时间">
  53. <el-date-picker
  54. v-model="queryParams.time"
  55. type="daterange"
  56. value-format="yyyy-MM-dd"
  57. range-separator="至"
  58. start-placeholder="开始日期"
  59. end-placeholder="结束日期">
  60. </el-date-picker>
  61. </el-form-item>
  62. <el-form-item>
  63. <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
  64. <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
  65. </el-form-item>
  66. </el-form>
  67. <el-row :gutter="10" class="mb8">
  68. <el-button
  69. type="primary"
  70. size="mini"
  71. icon="el-icon-download"
  72. v-hasPermi="['order:orderMr:downloadExcel']"
  73. @click="handleExport"
  74. v-loading.fullscreen.lock="handleExportLoading"
  75. element-loading-text="正在拼命生成数据中..."
  76. element-loading-spinner="el-icon-loading"
  77. element-loading-background="rgba(0, 0, 0, 0.5)"
  78. >导出excel</el-button>
  79. <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
  80. </el-row>
  81. <el-table ref="tables" v-loading="loading" :data="dataList" border>
  82. <el-table-column label="序号" align="center" type="index" width="60"></el-table-column>
  83. <el-table-column label="订单号" align="center" prop="id" />
  84. <el-table-column label="团队名称" align="center" prop="teamName" />
  85. <el-table-column label="团队类型" align="center" prop="type">
  86. <template slot-scope="scope">
  87. <dict-tag :options="dict.type.team_type" :value="scope.row.teamType"/>
  88. </template>
  89. </el-table-column>
  90. <el-table-column label="联系电话" align="center" prop="teamMobile" />
  91. <el-table-column label="负责人" align="center" prop="teamContact" />
  92. <el-table-column label="剧目名称" align="center" prop="performName" />
  93. <el-table-column label="票务名称" align="center" prop="goodsName" />
  94. <el-table-column label="座位类型" align="center" prop="seatTypeName" />
  95. <el-table-column label="团购数量" align="center" prop="quantity" />
  96. <el-table-column label="支付总额" align="center" prop="orderPrice">
  97. <template slot-scope="scope">
  98. <span>¥{{ scope.row.orderPrice }}</span>
  99. </template>
  100. </el-table-column>
  101. <el-table-column label="支付方式" align="center" prop="type">
  102. <template slot-scope="scope">
  103. <!-- <el-tooltip placement="top">
  104. <div slot="content">
  105. <span>{{ payWayList[scope.row.payWay] }}</span>
  106. </div>
  107. <span>{{ payWayList[scope.row.payWay] }}</span>
  108. </el-tooltip> -->
  109. <span>{{ payWayList[scope.row.payWay] }}</span>
  110. </template>
  111. </el-table-column>
  112. <el-table-column label="支付时间" align="center" prop="payTime" width="160" >
  113. <template slot-scope="scope">
  114. <span>{{ parseTime(scope.row.payTime) }}</span>
  115. </template>
  116. </el-table-column>
  117. <el-table-column label="订单状态" align="center" prop="type">
  118. <template slot-scope="scope">
  119. <span>{{statusList[scope.row.status]}}</span>
  120. </template>
  121. </el-table-column>
  122. <el-table-column label="操作" align="center" width="100" class-name="small-padding fixed-width">
  123. <template slot-scope="scope">
  124. <el-button
  125. size="mini"
  126. type="text"
  127. @click="openDetails(scope.row)"
  128. v-hasPermi="['groupBuyingMr:groupBuyingMr:details']"
  129. >详情</el-button>
  130. <el-button
  131. v-if="scope.row.status===0"
  132. size="mini"
  133. type="text"
  134. @click="handleCorporatePay(scope.row)"
  135. v-hasPermi="['groupBuyingMr:groupBuyingMr:details']"
  136. >对公转账</el-button>
  137. <el-button
  138. v-if="scope.row.status == 3 || scope.row.status == 7"
  139. size="mini"
  140. type="text"
  141. @click="handleOpen([scope.row])"
  142. v-hasPermi="['groupBuyingMr:groupBuyingMr:print']"
  143. >打印小票</el-button>
  144. </template>
  145. </el-table-column>
  146. </el-table>
  147. <pagination
  148. v-show="total>0"
  149. :total="total"
  150. :page.sync="queryParams.pageNum"
  151. :limit.sync="queryParams.pageSize"
  152. @pagination="getList"
  153. />
  154. <!-- 详情 -->
  155. <details-dia ref="detailsDia" :dict="dict" @getList="getList"></details-dia>
  156. <el-dialog
  157. title="选择小票机"
  158. :visible.sync="dialogVisible"
  159. width="30%"
  160. :before-close="handleClose">
  161. <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
  162. <el-form-item label="小票机" prop="region">
  163. <el-select v-model="ruleForm.region" placeholder="选择小票机">
  164. <el-option :label="item.deviceName" :key="item.id" :value="item.id" v-for="(item,index) in printList"></el-option>
  165. </el-select>
  166. </el-form-item>
  167. </el-form>
  168. <span slot="footer" class="dialog-footer">
  169. <el-button @click="dialogVisible = false">取 消</el-button>
  170. <el-button type="primary" :loading="dialogVisibleLoading" @click="print(viewerList)">{{ dialogVisibleLoading?'打印中...':'打印' }}</el-button>
  171. </span>
  172. </el-dialog>
  173. <el-dialog
  174. title="对公信息凭证"
  175. :visible.sync="showCorporatePay"
  176. width="50%"
  177. @close="handleCorporatePayClose"
  178. :before-close="handleCorporatePayClose">
  179. <el-form :model="ruleForm" :rules="corporatePayRules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
  180. <el-form-item label="凭证上传" prop="photoList" required>
  181. <el-upload
  182. ref="upload"
  183. :action="uploadObj.url"
  184. :headers="uploadObj.headers"
  185. accept=".jpg,.png"
  186. :on-success="handlePhotoListSuccess"
  187. :before-upload="beforeAvatarUpload"
  188. list-type="picture-card"
  189. :file-list="form.photoList"
  190. :on-remove="handleRemove"
  191. :limit="2"
  192. >
  193. <i class="el-icon-plus"></i>
  194. </el-upload>
  195. </el-form-item>
  196. <el-form-item label="备注">
  197. <el-input placeholder="请备注" type="textarea" maxlength="300" show-word-limit v-model="form.corporate.remark"></el-input>
  198. </el-form-item>
  199. </el-form>
  200. <span slot="footer" class="dialog-footer">
  201. <el-button @click="showCorporatePay = false">取 消</el-button>
  202. <el-button type="primary" :loading="corporatePayLoading" @click="corporatePay">{{ dialogVisibleLoading?'操作中...':'确定' }}</el-button>
  203. </span>
  204. </el-dialog>
  205. </div>
  206. </template>
  207. <script>
  208. import { getToken } from "@/utils/auth";
  209. import { pageList,gotoCorporatePay, downOrderListXls } from '@/api/order/groupBuyingMr'
  210. import detailsDia from "./dialog/details.vue";
  211. import { printApi } from '@/api/order/orderMr'
  212. import { pageList as getPrintListApi } from "@/api/device/pda";
  213. import { exportExcel } from '@/utils/exportexcel'
  214. const https = require('https');
  215. const axios = require('axios');
  216. export default {
  217. name: "agreement",
  218. dicts: ['agreement_type', 'team_type'],
  219. components: { detailsDia },
  220. data() {
  221. return {
  222. // 遮罩层
  223. loading: true,
  224. // 选中数组
  225. ids: [],
  226. // 非单个禁用
  227. single: true,
  228. // 非多个禁用
  229. multiple: true,
  230. // 显示搜索条件
  231. showSearch: true,
  232. // 总条数
  233. total: 0,
  234. // 用户表格数据
  235. dataList: null,
  236. // 弹出层标题
  237. title: "",
  238. // 是否显示弹出层
  239. open: false,
  240. // 日期范围
  241. dateRange: [],
  242. // 查询参数
  243. queryParams: {
  244. pageNum: 1,
  245. pageSize: 10,
  246. },
  247. statusList: {
  248. 0: '待支付',
  249. 2: '超时取消',
  250. 3: '待使用',
  251. 4: '退款中',
  252. 5: '己退款',
  253. 6: '退款失败',
  254. 7: '己使用',
  255. 8: '己超期',
  256. 9: '关闭',
  257. },
  258. statusMapList: [
  259. {id: 1, name: '待支付', value: 0},
  260. {id: 2, name: '超时取消', value: 2},
  261. {id: 3, name: '待使用', value: 3},
  262. {id: 4, name: '退款中', value: 4},
  263. {id: 5, name: '己退款', value: 5},
  264. {id: 6, name: '退款失败', value: 6},
  265. {id: 7, name: '己使用', value: 7},
  266. {id: 8, name: '己超期', value: 8},
  267. {id: 9, name: '关闭', value: 9},
  268. ],
  269. payList: {
  270. 0: '未支付',
  271. 1: '已支付',
  272. 2: '支付中',
  273. 3: '支付失败',
  274. 4: '支付退款',
  275. },
  276. payWayList: {
  277. 'cahsh': '现金',
  278. 'wecaht.applet': '微信小程序支付',
  279. 'alipay': '支付宝OTA',
  280. 'wecaht.h5': '微信公众号支付',
  281. 'meituan': '美团支付',
  282. 'corporate': '对公支付',
  283. },
  284. sourceList: {
  285. 1: '小程序',
  286. 2: '公众号',
  287. 3: '美团',
  288. 4: '携程',
  289. 5: '团购',
  290. },
  291. sourceMapList: [
  292. {id: 1, name: '小程序', value: 1},
  293. {id: 2, name: '公众号', value: 2},
  294. {id: 3, name: '美团', value: 3},
  295. {id: 4, name: '携程', value: 4},
  296. {id: 5, name: '团购', value: 5},
  297. ],
  298. visibleStatus: false,
  299. newObj: {},
  300. visibleType: '',
  301. viewerList: [],
  302. printList: [],
  303. dialogVisible: false,
  304. ruleForm: {},
  305. rules: {
  306. region: [
  307. { required: true, message: '请选择打印机', trigger: ['change','blur' ]}
  308. ],
  309. },
  310. dialogVisibleLoading: false,
  311. showCorporatePay:false,
  312. form:{
  313. orderId:'',
  314. photoList:[],
  315. corporate:{
  316. voucherUrl:'',
  317. remark:'',
  318. }
  319. },
  320. corporatePayRules: {
  321. photoList: [{ required: true, message: "请上传凭证", trigger: ["change","blur"] }],
  322. },
  323. uploadObj: {
  324. url: process.env.VUE_APP_UPLOAD_FILE_API + "/upload/single/minio",
  325. Headers: { Authorization: "Bearer " + getToken() },
  326. },
  327. corporatePayLoading:false,
  328. handleExportLoading: false,
  329. };
  330. },
  331. created() {
  332. this.getList();
  333. },
  334. methods: {
  335. /** 查询列表 */
  336. getList() {
  337. this.loading = true;
  338. pageList(this.queryParams)
  339. .then(response => {
  340. this.dataList = response.data.rows;
  341. this.total = response.data.total;
  342. this.loading = false;
  343. });
  344. },
  345. // 取消按钮
  346. cancel() {
  347. this.open = false;
  348. },
  349. /** 搜索按钮操作 */
  350. handleQuery() {
  351. this.queryParams.pageNum = 1;
  352. if(this.queryParams.time){
  353. this.queryParams.beginTime = this.queryParams.time[0];
  354. this.queryParams.endTime = this.queryParams.time[1];
  355. }else{
  356. this.queryParams.beginTime = null
  357. this.queryParams.endTime = null
  358. }
  359. this.getList();
  360. },
  361. /** 重置按钮操作 */
  362. resetQuery() {
  363. this.dateRange = [];
  364. this.$set(this.queryParams, 'id', '');
  365. this.$set(this.queryParams, 'status', '');
  366. this.$set(this.queryParams, 'teamTypeId', '');
  367. this.$set(this.queryParams, 'teamName', '');
  368. this.$set(this.queryParams, 'performName', '');
  369. this.$set(this.queryParams, 'beginTime', '');
  370. this.$set(this.queryParams, 'endTime', '');
  371. this.$set(this.queryParams, 'time', '');
  372. this.queryParams.pageNum = 1;
  373. this.handleQuery();
  374. },
  375. /** 详情按钮操作 */
  376. openDetails(row, type) {
  377. this.$refs["detailsDia"].openDialog("详情", row, type);
  378. },
  379. handleOpen(list=[]){
  380. if(!list||list.length==0) return
  381. let idList = []
  382. list.forEach((item,index)=>{
  383. idList.push(item.id)
  384. })
  385. this.viewerList = idList
  386. this.getPrintListApi()
  387. this.$set(this.ruleForm, 'region', '');
  388. this.$nextTick(()=>{
  389. this.$refs.ruleForm.clearValidate('region')
  390. })
  391. this.dialogVisible = true
  392. },
  393. handleClose(){
  394. this.dialogVisible = false
  395. },
  396. /** 查询打印机列表 */
  397. getPrintListApi() {
  398. getPrintListApi({deviceType:5,pageNum: 1,
  399. pageSize: 999,})
  400. .then(response => {
  401. this.printList = response.data.rows;
  402. }
  403. );
  404. },
  405. /** 选择打印机 */
  406. selectPrint(){
  407. },
  408. // 打印
  409. async print(list = []){
  410. this.$refs.ruleForm.validate(async (valid) => {
  411. if (valid) {
  412. this.dialogVisibleLoading = true
  413. try {
  414. let res = await printApi({
  415. //viewerList:list,
  416. orderId: list[0],
  417. source: 2,
  418. deviceId: this.ruleForm.region
  419. })
  420. if(res.code == 200) {
  421. let url = res.data.linkIp
  422. let printInfo = res.data.printInfo
  423. this.connectPrint(url,printInfo)
  424. }else {
  425. throw new Error(res)
  426. }
  427. } catch (error) {
  428. this.dialogVisible = false
  429. this.dialogVisibleLoading = false
  430. console.error("error=====",error)
  431. }
  432. } else {
  433. console.log('error submit!!');
  434. return false;
  435. }
  436. });
  437. },
  438. /** 连接打印机 */
  439. connectPrint(url,data){
  440. // let xhr = new XMLHttpRequest();
  441. // xhr.onreadystatechange = ()=>{
  442. // if(xhr.readyState == 4){ // 监听请求完成
  443. // if((xhr.status >=200 && xhr.status <300) || xhr.status == 304){
  444. // console.log(xhr.responseText)
  445. // this.dialogVisible = false
  446. // this.dialogVisibleLoading = false
  447. // }else{
  448. // console.log('请求失败')
  449. // this.dialogVisible = false
  450. // this.dialogVisibleLoading = false
  451. // }
  452. // }
  453. // }
  454. // xhr.open("post", url, true); // 异步请求
  455. // xhr.send(JSON.stringify(data));
  456. const ignoreSSL = axios.create({
  457. httpsAgent: new https.Agent({
  458. rejectUnauthorized: false
  459. }),
  460. withCredentials: true, // 跨域请求时发送Cookie
  461. timeout: 60000, // 请求超时
  462. headers: {
  463. "Content-Type": "application/json; charset=UTF-8;"
  464. }
  465. });
  466. ignoreSSL.post(url,
  467. { ...data }
  468. ).then(()=>{
  469. this.dialogVisible = false
  470. this.dialogVisibleLoading = false
  471. }).catch(()=>{
  472. this.dialogVisible = false
  473. this.dialogVisibleLoading = false
  474. })
  475. },
  476. handleCorporatePay(row){
  477. console.log('corporatePay',row);
  478. this.form.orderId = row.id;
  479. this.showCorporatePay = true;
  480. },
  481. handleCorporatePayClose(){
  482. console.log('1111');
  483. this.corporatePayLoading = false;
  484. this.showCorporatePay = false;
  485. },
  486. corporatePay(){
  487. console.log('form',this.form);
  488. if(this.form.photoList.length<1){
  489. this.$message.error('请上传凭证');
  490. return
  491. }
  492. this.corporatePayLoading = true;
  493. const voucherUrl = this.form.photoList.map(item => item.url).join(",");
  494. this.form.corporate.voucherUrl = voucherUrl;
  495. gotoCorporatePay(this.form).then((res)=>{
  496. this.$message.success(res.msg);
  497. this.corporatePayLoading = false;
  498. this.handleCorporatePayClose();
  499. }).catch((err)=>{
  500. this.corporatePayLoading = false;
  501. this.$message.error(err.msg);
  502. console.log('corporatePay err',err);
  503. })
  504. },
  505. /**
  506. * 剧目海报上传成功
  507. * @date 2023-11-22
  508. * @param {any} res
  509. * @returns {any}
  510. */
  511. handlePhotoListSuccess(res) {
  512. if (res.code === 200) {
  513. let photo = {
  514. imageUrl: res?.data?.url,
  515. url: res?.data?.url,
  516. photoType: '2'
  517. }
  518. if(!this.form.photoList){
  519. this.form.photoList = []
  520. }
  521. // this.form.photoList.push(photo);
  522. this.$set(this.form.photoList, this.form.photoList.length, photo);
  523. }
  524. },
  525. handleRemove(file, fileList) {
  526. this.form.photoList.forEach((item, index) => {
  527. if(item.uid == file.uid){
  528. this.form.photoList.splice(index, 1)
  529. }
  530. })
  531. },
  532. /**
  533. * 上传文件之前之前
  534. * @date 2023-11-22
  535. * @param {any} file
  536. * @returns {any}
  537. */
  538. beforeAvatarUpload(file) {
  539. const isJPG = file.type === "image/jpeg" || "image/png";
  540. if (!isJPG) {
  541. this.$message.error("上传头像图片只能是jpg或png格式!");
  542. }
  543. return isJPG;
  544. },
  545. /**
  546. * 导出报表
  547. * @date 2022-10-24
  548. * @returns {any}
  549. */
  550. handleExport() {
  551. this.$confirm('您确定要导出当前查询的数据吗?', '提示', {
  552. confirmButtonText: '确定 ',
  553. cancelButtonText: '取消 ',
  554. type: 'warning'
  555. })
  556. .then(() => {
  557. this.handleExportLoading = true;
  558. // const { pageNum, pageSize} = this.params;
  559. let postMap = {}
  560. for (let key in this.queryParams) {
  561. if(key != 'pageNum' && key != 'pageSize'){
  562. postMap[key] = this.queryParams[key]
  563. }
  564. }
  565. downOrderListXls(postMap)
  566. .then((res) => {
  567. exportExcel(res, '团购订单', '.xlsx');
  568. this.handleExportLoading = false;
  569. })
  570. .catch((error) => {
  571. console.log("error===",error)
  572. this.handleExportLoading = false;
  573. });
  574. })
  575. .catch(() => {
  576. this.$message.info('您已取消导出!');
  577. });
  578. },
  579. }
  580. };
  581. </script>
  582. <style lang="scss">
  583. .upload-btn {
  584. width: 100px;
  585. height: 100px;
  586. background-color: #fbfdff;
  587. border: dashed 1px #c0ccda;
  588. border-radius: 5px;
  589. i {
  590. font-size: 30px;
  591. margin-top: 20px;
  592. }
  593. &-text {
  594. margin-top: -10px;
  595. }
  596. }
  597. .avatar {
  598. cursor: pointer;
  599. }
  600. </style>