金币系统前端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

967 lines
28 KiB

12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
11 months ago
11 months ago
12 months ago
11 months ago
12 months ago
11 months ago
12 months ago
12 months ago
11 months ago
11 months ago
12 months ago
11 months ago
12 months ago
11 months ago
12 months ago
12 months ago
11 months ago
11 months ago
12 months ago
11 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
11 months ago
12 months ago
12 months ago
12 months ago
  1. <script setup>
  2. import { ref, onMounted, reactive, computed, nextTick } from 'vue'
  3. import ElementPlus from 'element-plus'
  4. import { ElMessage, ElMessageBox } from 'element-plus'
  5. import { AiFillRead } from 'vue-icons-plus/ai'
  6. import axios from 'axios'
  7. import moment from 'moment'
  8. import API from '@/util/http'
  9. import * as XLSX from 'xlsx' // 引入 xlsx 库
  10. // 提取 XLSX 工具函数
  11. const { utils, writeFile } = XLSX
  12. // 变量
  13. //这是获取用户信息的接口
  14. const adminData = ref({})
  15. const getAdminData = async function () {
  16. try {
  17. const result = await API({ url: '/admin/userinfo', data: {} })
  18. adminData.value = result
  19. console.log('请求成功', result)
  20. console.log('用户信息', adminData.value)
  21. } catch (error) {
  22. console.log('请求失败', error)
  23. }
  24. }
  25. // 充值明细表格
  26. const tableData = ref([])
  27. // 搜索======================================
  28. // 搜索rechargeVo
  29. const rechargeVo = ref({
  30. activityId: '',
  31. rechargeWay: '',
  32. area: '',
  33. startDate: '',
  34. endDate: '',
  35. status: ''
  36. })
  37. // 搜索对象
  38. const getObj = ref({
  39. pageNum: 1,
  40. pageSize: 50
  41. })
  42. //分页总条目
  43. const total = ref(100)
  44. // 搜索对象时间
  45. const getTime = ref([])
  46. // 搜索活动列表
  47. const activity = ref([])
  48. // 所有信息
  49. const allData = ref([])
  50. // 搜索地区列表
  51. const area = ref([])
  52. //标签页默认高亮选项
  53. const activeName = ref('all')
  54. // 充值方式选项
  55. const rechargeWay = ref([])
  56. // 获取充值方式的数据的接口
  57. const getPayWay = async function () {
  58. try {
  59. const result = await API({ url: '/recharge/recharge/getWay', data: {} })
  60. rechargeWay.value = result.data.filter((item) => item)
  61. console.log('请求成功', result)
  62. console.log('充值方式', rechargeWay.value)
  63. } catch (error) {
  64. console.log('请求失败', error)
  65. }
  66. }
  67. // 方法
  68. // 合计数存储
  69. const trueGold = ref(0)
  70. const trueRGold = ref(0)
  71. const trueFGold = ref(0)
  72. //全部
  73. const totalmoney = ref(0)
  74. const totalRcoin = ref(0)
  75. const totalFcoin = ref(0)
  76. //待审核
  77. const pendingGold = ref(0)
  78. const pendingRGold = ref(0)
  79. const pendingFGold = ref(0)
  80. // 已通过金币数
  81. const approvedGold = ref(0)
  82. const approvedRGold = ref(0)
  83. const approvedFGold = ref(0)
  84. // 已驳回金币数
  85. const rejectedGold = ref(0)
  86. const rejectedRGold = ref(0)
  87. const rejectedFGold = ref(0)
  88. // 搜索==============================================================
  89. // 搜索方法
  90. const get = async function (val) {
  91. try {
  92. // 地区赋值
  93. if (adminData.value.area === '泰国') {
  94. rechargeVo.value.areas = ['泰国', '越南']
  95. } else if (adminData.value.area !== '总部') {
  96. rechargeVo.value.area = adminData.value.area
  97. }
  98. // 搜索参数页码赋值
  99. if (typeof val === 'number') {
  100. getObj.value.pageNum = val
  101. }
  102. // 搜索参数时间赋值
  103. if (getTime.value != null) {
  104. if (getTime.value[0] && getTime.value[1]) {
  105. rechargeVo.value.startDate = getTime.value[0]
  106. rechargeVo.value.endDate = getTime.value[1]
  107. }
  108. } else {
  109. rechargeVo.value.startDate = ''
  110. rechargeVo.value.endDate = ''
  111. }
  112. // 搜索参数赋值
  113. rechargeVo.value.sortField = sortField.value
  114. rechargeVo.value.sortOrder = sortOrder.value
  115. console.log('搜索参数', getObj.value)
  116. // 发送POST请求
  117. const result = await API({
  118. url: '/recharge/recharge',
  119. data: { ...getObj.value, rechargeVo: { ...rechargeVo.value } }
  120. })
  121. // 复制一份 rechargeVo.value 并移除排序字段和排序方式
  122. const detailWithoutSort = ref({
  123. area: rechargeVo.value.area,
  124. adminId: rechargeVo.value.adminId,
  125. startDate: rechargeVo.value.startDate,
  126. endDate: rechargeVo.value.endDate
  127. })
  128. const result2 = await API({
  129. url: '/recharge/recharge/RechargeA',
  130. data: {
  131. ...detailWithoutSort.value
  132. }
  133. })
  134. // 检查 result2 是否为空
  135. if (!result2 || !result2.data || result2.data.length === 0) {
  136. totalmoney.value = 0
  137. totalRcoin.value = 0
  138. totalFcoin.value = 0
  139. }
  140. if (result2.data) {
  141. result2.data.forEach((item) => {
  142. switch (item.auditStatus) {
  143. case '待审核':
  144. // 若 item.raudit 为空则赋值为 0
  145. // 若 item.sumRaudit 为空则赋值为 0
  146. pendingGold.value = item.sumRaudit || 0
  147. pendingRGold.value = item.sumRaudit1 || 0
  148. pendingFGold.value = item.sumRaudit2 || 0
  149. break
  150. case '已通过':
  151. approvedGold.value = item.sumRaudit || 0
  152. approvedRGold.value = item.sumRaudit1 || 0
  153. approvedFGold.value = item.sumRaudit2 || 0
  154. break
  155. case '已驳回':
  156. rejectedGold.value = item.sumRaudit || 0
  157. rejectedRGold.value = item.sumRaudit1 || 0
  158. rejectedFGold.value = item.sumRaudit2 || 0
  159. break
  160. }
  161. })
  162. }
  163. trueGold.value = pendingGold.value + approvedGold.value + rejectedGold.value
  164. trueRGold.value =
  165. pendingRGold.value + approvedRGold.value + rejectedRGold.value
  166. trueFGold.value =
  167. pendingFGold.value + approvedFGold.value + rejectedFGold.value
  168. // 将响应结果存储到响应式数据中
  169. console.log('请求成功', result)
  170. // 存储表格数据
  171. tableData.value = result.data.list
  172. console.log('tableData', tableData.value)
  173. // 存储分页总数
  174. total.value = result.data.total
  175. console.log('total', total.value)
  176. } catch (error) {
  177. console.log('请求失败', error)
  178. // 在这里可以处理错误逻辑,比如显示错误提示等
  179. }
  180. }
  181. // 搜索
  182. const search = function () {
  183. getObj.value.pageNum = 1
  184. get()
  185. }
  186. // 重置
  187. const reset = function () {
  188. rechargeVo.value.activityId = ''
  189. rechargeVo.value.rechargeWay = ''
  190. rechargeVo.value.area = ''
  191. rechargeVo.value.startDate = ''
  192. rechargeVo.value.endDate = ''
  193. sortField.value = ''
  194. sortOrder.value = ''
  195. getTime.value = []
  196. }
  197. // 今天
  198. const getToday = function () {
  199. const today = new Date()
  200. const startDate = new Date(
  201. today.getFullYear(),
  202. today.getMonth(),
  203. today.getDate()
  204. )
  205. // 设置结束时间为当天的 23:59:59
  206. const endDate = new Date(
  207. today.getFullYear(),
  208. today.getMonth(),
  209. today.getDate(),
  210. 23, 59, 59
  211. )
  212. getTime.value = [startDate, endDate]
  213. // 格式化时间
  214. rechargeVo.value.startDate = moment(startDate).format('YYYY-MM-DD HH:mm:ss')
  215. rechargeVo.value.endDate = moment(endDate).format('YYYY-MM-DD HH:mm:ss')
  216. console.log('getTime', getTime.value)
  217. get()
  218. }
  219. // 昨天
  220. const getYesterday = function () {
  221. const yesterday = new Date()
  222. yesterday.setDate(yesterday.getDate() - 1)
  223. const startDate = new Date(
  224. yesterday.getFullYear(),
  225. yesterday.getMonth(),
  226. yesterday.getDate()
  227. )
  228. // 设置结束时间为昨天的 23:59:59
  229. const endDate = new Date(
  230. yesterday.getFullYear(),
  231. yesterday.getMonth(),
  232. yesterday.getDate(),
  233. 23, 59, 59
  234. )
  235. getTime.value = [startDate, endDate]
  236. // 格式化时间
  237. rechargeVo.value.startDate = moment(startDate).format('YYYY-MM-DD HH:mm:ss')
  238. rechargeVo.value.endDate = moment(endDate).format('YYYY-MM-DD HH:mm:ss')
  239. console.log('getTime', getTime.value)
  240. get()
  241. }
  242. // 近7天
  243. const get7Days = function () {
  244. const today = new Date()
  245. const startDate = new Date(
  246. today.getFullYear(),
  247. today.getMonth(),
  248. today.getDate() - 6
  249. )
  250. // 设置结束时间为当天的 23:59:59
  251. const endDate = new Date(
  252. today.getFullYear(),
  253. today.getMonth(),
  254. today.getDate(),
  255. 23, 59, 59
  256. )
  257. getTime.value = [startDate, endDate]
  258. // 格式化时间
  259. rechargeVo.value.startDate = moment(startDate).format('YYYY-MM-DD HH:mm:ss')
  260. rechargeVo.value.endDate = moment(endDate).format('YYYY-MM-DD HH:mm:ss')
  261. console.log('getTime', getTime.value)
  262. get()
  263. }
  264. //全部充值明细
  265. const adminAll = function () {
  266. console.log('adminAll')
  267. rechargeVo.value.status = ''
  268. getObj.value.pageNum = 1
  269. get()
  270. }
  271. //待审核充值明细
  272. const adminWait = async function () {
  273. rechargeVo.value.status = 0
  274. getObj.value.pageNum = 1
  275. await get()
  276. console.log('adminWait')
  277. trueGold.value = pendingGold.value
  278. trueRGold.value = pendingRGold.value
  279. trueFGold.value = pendingFGold.value
  280. }
  281. //已通过充值明细
  282. const adminPass = async function () {
  283. rechargeVo.value.status = 1
  284. getObj.value.pageNum = 1
  285. await get()
  286. console.log('adminPass')
  287. trueGold.value = approvedGold.value
  288. trueRGold.value = approvedRGold.value
  289. trueFGold.value = approvedFGold.value
  290. }
  291. //已驳回充值明细
  292. const adminReject = async function () {
  293. rechargeVo.value.status = 2
  294. getObj.value.pageNum = 1
  295. await get()
  296. trueGold.value = rejectedGold.value
  297. trueRGold.value = rejectedRGold.value
  298. trueFGold.value = rejectedFGold.value
  299. console.log('adminReject')
  300. }
  301. //点击标签页
  302. const handleClick = function (tab, event) {
  303. if (tab.props.name === 'all') {
  304. adminAll()
  305. } else if (tab.props.name === 'wait') {
  306. adminWait()
  307. } else if (tab.props.name === 'pass') {
  308. adminPass()
  309. } else if (tab.props.name === 'reject') {
  310. adminReject()
  311. }
  312. }
  313. // 获取活动名称
  314. const getActivity = async function () {
  315. try {
  316. // 发送POST请求
  317. const result = await API({ url: '/recharge/activity/select', data: {} })
  318. // 将响应结果存储到响应式数据中
  319. console.log('请求成功', result)
  320. // 存储表格数据
  321. activity.value = result.data
  322. console.log('activity', activity.value)
  323. } catch (error) {
  324. console.log('请求失败', error)
  325. // 在这里可以处理错误逻辑,比如显示错误提示等
  326. }
  327. }
  328. // 获取地区
  329. const getArea = async function () {
  330. console.log('888888888880000000')
  331. try {
  332. // 发送POST请求
  333. const result = await API({ url: '/recharge/user/search', data: {} })
  334. // 将响应结果存储到响应式数据中
  335. console.log('请求成功地区', result.data)
  336. // 存储地区信息
  337. area.value = result.data
  338. console.log('地区', area.value)
  339. } catch (error) {
  340. console.log('请求失败', error)
  341. // 在这里可以处理错误逻辑,比如显示错误提示等
  342. }
  343. }
  344. // 验证跳转输入框的数字是否合法
  345. const checkNumber = function () {
  346. if (typeof parseInt(getObj.value.pageNum) === 'number') {
  347. console.log('总共有多少页' + Math.ceil(total.value / getObj.value.pageSize))
  348. if (
  349. getObj.value.pageNum > 0 &&
  350. getObj.value.pageNum <= Math.ceil(total.value / getObj.value.pageSize)
  351. ) {
  352. getObj.value.pageNum = parseInt(getObj.value.pageNum)
  353. console.log('输入的数字合法')
  354. get()
  355. } else {
  356. //提示
  357. ElMessage({
  358. type: 'error',
  359. message: '请检查输入内容'
  360. })
  361. }
  362. } else {
  363. //提示
  364. ElMessage({
  365. type: 'error',
  366. message: '请检查输入内容'
  367. })
  368. }
  369. }
  370. // 挂载
  371. onMounted(async function () {
  372. getAdminData()
  373. get()
  374. getActivity()
  375. getPayWay()
  376. getArea()
  377. })
  378. const handlePageSizeChange = function (val) {
  379. getObj.value.pageSize = val
  380. get()
  381. }
  382. const handleCurrentChange = function (val) {
  383. getObj.value.pageNum = val
  384. get()
  385. }
  386. // 新增排序字段和排序方式
  387. const sortField = ref('')
  388. const sortOrder = ref('')
  389. // 处理排序事件
  390. const handleSortChange = (column) => {
  391. console.log('排序字段:', column.prop)
  392. console.log('排序方式:', column.order)
  393. if (column.prop === 'paidGold') {
  394. sortField.value = 'recharge_gold'
  395. } else if (column.prop === 'freeGold') {
  396. sortField.value = 'free_gold'
  397. } else if (column.prop === 'rechargeTime') {
  398. sortField.value = 'recharge_time'
  399. } else if (column.prop === 'createTime') {
  400. sortField.value = 'create_time'
  401. } else if (column.prop === 'paidMoney') {
  402. sortField.value = 'paid_gold'
  403. }
  404. sortOrder.value = column.order === 'ascending' ? 'ASC' : 'DESC'
  405. get()
  406. }
  407. // 导出Excel相关变量和方法
  408. const headers = [
  409. '序号',
  410. '姓名',
  411. '精网号',
  412. '所属地区',
  413. '活动名称',
  414. '货币名称',
  415. '充值金额',
  416. '充值方式',
  417. '永久金币',
  418. '免费金币',
  419. '备注',
  420. '支付方式',
  421. '提交人',
  422. '状态',
  423. '驳回理由',
  424. '交款时间'
  425. ]
  426. const showExportInfoPanel = ref(false)
  427. // 点击导出按钮直接显示信息面板
  428. const exportExcel = async () => {
  429. try {
  430. console.log('点击导出按钮,尝试显示信息面板');
  431. showExportInfoPanel.value = true;
  432. await nextTick(); // 组件更新显示信息面板
  433. } catch (error) {
  434. console.error('显示信息面板失败:', error);
  435. ElMessage.error('显示信息面板失败,请稍后重试');
  436. }
  437. };
  438. // 新增导出状态相关变量
  439. const exportProgress = ref(0)
  440. const isExporting = ref(false)
  441. const exportCancelToken = ref(null)
  442. // 移除未使用的映射
  443. // const platformMap = {
  444. // 0: '初始化金币',
  445. // 1: 'ERP系统',
  446. // 2: 'Homily Chart',
  447. // 3: 'Homily Link',
  448. // 4: '金币系统'
  449. // };
  450. // const updateTypeMap = {
  451. // 0: '充值',
  452. // 1: '消费',
  453. // 2: '退款',
  454. // 3: '其他'
  455. // };
  456. // 优化后的导出方法
  457. const doExportExcel = async () => {
  458. try {
  459. isExporting.value = true
  460. exportProgress.value = 0
  461. showExportInfoPanel.value = false
  462. // 初始化 Excel
  463. const wb = utils.book_new()
  464. const ws = utils.aoa_to_sheet([headers])
  465. utils.book_append_sheet(wb, ws, 'Sheet1')
  466. // 流式写入配置
  467. const writer = {
  468. write: (d, o) => {
  469. if (!d) return
  470. utils.sheet_add_aoa(ws, d, { origin: -1 })
  471. }
  472. }
  473. let page = 1
  474. let totalExported = 0
  475. const pageSize = 5000 // 每次请求 5000 条
  476. let totalRecords = 0
  477. // 首次请求获取总记录数
  478. const firstResult = await API({
  479. url: '/recharge/recharge',
  480. method: 'post',
  481. data: {
  482. pageNum: 1,
  483. pageSize,
  484. rechargeVo: { ...rechargeVo.value }
  485. }
  486. })
  487. totalRecords = firstResult.data.total
  488. // 创建取消令牌
  489. const CancelToken = axios.CancelToken
  490. exportCancelToken.value = CancelToken.source()
  491. // 处理首次请求的数据
  492. const firstData = firstResult.data.list
  493. if (firstData.length) {
  494. const rows = firstData.map((row, index) => [
  495. totalExported + index + 1,
  496. row.username || '',
  497. row.jwcode || '',
  498. row.area || '',
  499. row.activityName || '',
  500. // 假设货币名称字段在数据中为 currencyName,若不存在请替换为实际字段
  501. row.currencyName || '',
  502. (row.paidGold / 100).toFixed(2) || '0.00',
  503. row.rechargeWay || '',
  504. (row.paidGold / 100).toFixed(2) || '0.00',
  505. (row.freeGold / 100).toFixed(2) || '0.00',
  506. row.remark || '',
  507. row.payWay || '',
  508. row.name || '',
  509. // 根据状态值显示对应文本
  510. row.status === 1 ? '已通过' : row.status === 0 ? '待审核' : row.status === 2 ? '已驳回' : '',
  511. row.reson || '',
  512. moment(row.rechargeTime).format('YYYY-MM-DD HH:mm:ss') || ''
  513. ])
  514. writer.write(rows)
  515. totalExported += firstData.length
  516. exportProgress.value = Math.round((totalExported / totalRecords) * 100)
  517. page++
  518. }
  519. while (totalExported < totalRecords) {
  520. const result = await API({
  521. url: '/recharge/recharge',
  522. method: 'post',
  523. data: {
  524. pageNum: page,
  525. pageSize,
  526. rechargeVo: { ...rechargeVo.value }
  527. },
  528. cancelToken: exportCancelToken.value.token
  529. })
  530. const data = result.data.list
  531. if (!data.length) break
  532. // 转换数据
  533. const rows = data.map((row, index) => [
  534. totalExported + index + 1,
  535. row.username || '',
  536. row.jwcode || '',
  537. row.area || '',
  538. row.activityName || '',
  539. // 假设货币名称字段在数据中为 currencyName,若不存在请替换为实际字段
  540. row.currencyName || '',
  541. (row.paidGold / 100).toFixed(2) || '0.00',
  542. row.rechargeWay || '',
  543. (row.paidGold / 100).toFixed(2) || '0.00',
  544. (row.freeGold / 100).toFixed(2) || '0.00',
  545. row.remark || '',
  546. row.payWay || '',
  547. row.name || '',
  548. // 根据状态值显示对应文本
  549. row.status === 1 ? '已通过' : row.status === 0 ? '待审核' : row.status === 2 ? '已驳回' : '',
  550. row.reson || '',
  551. moment(row.rechargeTime).format('YYYY-MM-DD HH:mm:ss') || ''
  552. ])
  553. // 流式写入
  554. writer.write(rows)
  555. totalExported += data.length
  556. exportProgress.value = Math.round((totalExported / totalRecords) * 100)
  557. // 内存控制:每 500 页释放内存
  558. if (page % 500 === 0) {
  559. await new Promise(resolve => setTimeout(resolve, 0))
  560. }
  561. page++
  562. }
  563. // 生成最终文件
  564. writeFile(wb, '客户金币明细.xlsx')
  565. ElMessage.success(`导出成功,共${totalExported}条数据`)
  566. } catch (error) {
  567. if (!axios.isCancel(error)) {
  568. ElMessage.error(`导出失败: ${error.message}`)
  569. }
  570. } finally {
  571. isExporting.value = false
  572. exportCancelToken.value = null
  573. }
  574. }
  575. // 新增取消导出方法
  576. const cancelExport = () => {
  577. if (exportCancelToken.value) {
  578. exportCancelToken.value.cancel('用户取消导出')
  579. ElMessage.warning('导出已取消')
  580. isExporting.value = false
  581. }
  582. }
  583. const putExcel = ref({
  584. startDate: new Date(),
  585. endDate: new Date(new Date().setDate(new Date().getDate() + 1))
  586. })
  587. </script>
  588. <template>
  589. <el-row>
  590. <el-col>
  591. <el-card style="margin-bottom: 20px">
  592. <el-row style="margin-bottom: 10px">
  593. <el-col :span="6">
  594. <div class="head-card-element">
  595. <el-text class="mx-1" size="large">活动名称</el-text>
  596. <el-select
  597. v-model="rechargeVo.activityId"
  598. placeholder="请选择活动名称"
  599. size="large"
  600. style="width: 240px"
  601. clearable
  602. >
  603. <el-option
  604. v-for="item in activity"
  605. :key="item.activityId"
  606. :label="item.activityName"
  607. :value="item.activityId"
  608. />
  609. </el-select>
  610. </div>
  611. </el-col>
  612. <!-- <el-col :span="8">
  613. <div class="head-card-element">
  614. <el-text class="mx-1" size="large">充值方式</el-text>
  615. <el-select
  616. v-model="rechargeVo.rechargeWay"
  617. placeholder="请选择充值方式"
  618. size="large"
  619. style="width: 240px"
  620. clearable
  621. >
  622. <el-option
  623. v-for="item in rechargeWay"
  624. :key="item"
  625. :label="item"
  626. :value="item"
  627. />
  628. </el-select>
  629. </div>
  630. </el-col>-->
  631. <el-col :span="8">
  632. <div class="head-card-element" v-if="adminData.area == '总部'">
  633. <el-text class="mx-1" size="large">所属地区</el-text>
  634. <el-select
  635. v-model="rechargeVo.area"
  636. placeholder="请选择所属地区"
  637. size="large"
  638. style="width: 240px"
  639. clearable
  640. >
  641. <el-option
  642. v-for="item in area"
  643. :key="item"
  644. :label="item"
  645. :value="item"
  646. />
  647. </el-select>
  648. </div>
  649. </el-col>
  650. </el-row>
  651. <el-row>
  652. <el-col :span="16">
  653. <div class="head-card-element">
  654. <el-text class="mx-1" size="large">充值时间</el-text>
  655. <el-date-picker
  656. v-model="getTime"
  657. type="datetimerange"
  658. range-separator="至"
  659. start-placeholder="起始时间"
  660. end-placeholder="结束时间"
  661. />
  662. <el-button style="margin-left: 10px" @click="getToday()"
  663. ></el-button
  664. >
  665. <el-button @click="getYesterday()"></el-button>
  666. <el-button @click="get7Days()">近7天</el-button>
  667. </div>
  668. </el-col>
  669. <el-col :span="6">
  670. <div class="head-card-btn">
  671. <el-button type="success" @click="reset()">重置</el-button>
  672. <el-button type="primary" @click="search()">查询</el-button>
  673. <!-- 新增导出按钮 -->
  674. <el-button type="primary" @click="exportExcel">导出excel</el-button>
  675. </div>
  676. </el-col>
  677. </el-row>
  678. </el-card>
  679. </el-col>
  680. </el-row>
  681. <el-row>
  682. <el-col>
  683. <el-card>
  684. <el-tabs
  685. v-model="activeName"
  686. type="card"
  687. class="demo-tabs"
  688. @tab-click="handleClick"
  689. >
  690. <el-tab-pane label="全部" name="all"></el-tab-pane>
  691. <el-tab-pane label="待审核" name="wait"></el-tab-pane>
  692. <el-tab-pane label="已通过" name="pass"></el-tab-pane>
  693. <el-tab-pane label="已驳回" name="reject"></el-tab-pane>
  694. <div>
  695. 充值金额{{ (trueRGold / 100).toFixed(2) }}新币永久金币{{
  696. (trueRGold / 100).toFixed(2)
  697. }}金币免费金币{{ (totalFcoin / 100).toFixed(2) }}金币
  698. </div>
  699. </el-tabs>
  700. <!-- 设置表格容器的高度和滚动样式 -->
  701. <div style="height: 520px; overflow-y: auto">
  702. <el-table
  703. :data="tableData"
  704. style="width: 100%"
  705. height="520px"
  706. @sort-change="handleSortChange"
  707. >
  708. <el-table-column
  709. type="index"
  710. label="序号"
  711. width="70px"
  712. fixed="left"
  713. >
  714. <template #default="scope">
  715. <span>{{
  716. scope.$index + 1 + (getObj.pageNum - 1) * getObj.pageSize
  717. }}</span>
  718. </template>
  719. </el-table-column>
  720. <el-table-column
  721. fixed="left"
  722. prop="username"
  723. label="姓名"
  724. width="100px"
  725. />
  726. <el-table-column
  727. fixed="left"
  728. prop="jwcode"
  729. label="精网号"
  730. width="110px"
  731. />
  732. <el-table-column prop="area" label="所属地区" width="100px" />
  733. <el-table-column
  734. prop="activityName"
  735. label="活动名称"
  736. width="150px"
  737. />
  738. <el-table-column prop="" label="货币名称" width="120px" />
  739. <el-table-column
  740. prop="paidMoney"
  741. label="充值金额"
  742. width="120px"
  743. sortable=" custom"
  744. >
  745. <template #default="scope">
  746. <span>{{ scope.row.paidGold / 100 }}</span>
  747. </template>
  748. </el-table-column>
  749. <el-table-column
  750. prop="rechargeWay"
  751. label="充值方式"
  752. width="100px"
  753. />
  754. <el-table-column
  755. prop="paidGold"
  756. label="永久金币"
  757. sortable="“custom”"
  758. width="110px"
  759. >
  760. <template #default="scope">
  761. <span>{{ scope.row.paidGold / 100 }}</span>
  762. </template>
  763. </el-table-column>
  764. <el-table-column
  765. prop="freeGold"
  766. label="免费金币"
  767. sortable="“custom”"
  768. width="110px"
  769. >
  770. <template #default="scope">
  771. <span>{{ scope.row.freeGold / 100 }}</span>
  772. </template>
  773. </el-table-column>
  774. <el-table-column
  775. prop="remark"
  776. label="备注"
  777. width="200px"
  778. show-overflow-tooltip
  779. />
  780. <el-table-column prop="payWay" label="支付方式" width="100px" />
  781. <el-table-column
  782. prop="rechargeVoucher"
  783. label="支付凭证"
  784. width="150px"
  785. >
  786. <template #default="scope">
  787. <el-image
  788. :preview-src-list="[scope.row.rechargeVoucher]"
  789. :preview-teleported="true"
  790. :src="scope.row.rechargeVoucher"
  791. alt="凭证"
  792. style="width: 50px; height: 50px"
  793. />
  794. </template>
  795. </el-table-column>
  796. <el-table-column prop="name" label="提交人" width="100px" />
  797. <el-table-column prop="status" label="状态" width="100px">
  798. <template #default="scope">
  799. <span v-if="scope.row.status === 1">
  800. <div class="status">
  801. <span class="green-dot"></span>
  802. <span>已通过</span>
  803. </div>
  804. </span>
  805. <span v-if="scope.row.status === 0">
  806. <div class="status">
  807. <span class="grey-dot"></span>
  808. <span>待审核</span>
  809. </div>
  810. </span>
  811. <span v-if="scope.row.status === 2">
  812. <div class="status">
  813. <span class="red-dot"></span>
  814. <span>已驳回</span>
  815. </div>
  816. </span>
  817. </template>
  818. </el-table-column>
  819. <el-table-column
  820. prop="reson"
  821. label="驳回理由"
  822. width="200px"
  823. show-overflow-tooltip
  824. />
  825. <el-table-column
  826. prop="rechargeTime"
  827. sortable="“custom”"
  828. label="交款时间"
  829. width="200px"
  830. >
  831. <template #default="scope">
  832. {{
  833. moment(scope.row.rechargeTime).format('YYYY-MM-DD HH:mm:ss')
  834. }}
  835. </template>
  836. </el-table-column>
  837. <el-table-column
  838. prop="createTime"
  839. sortable="“custom”"
  840. label="提交时间"
  841. width="200px"
  842. />
  843. </el-table>
  844. </div>
  845. <!-- 分页 -->
  846. <div class="pagination" style="margin-top: 20px">
  847. <el-pagination
  848. background
  849. :page-size="getObj.pageSize"
  850. :page-sizes="[5, 10, 20, 50, 100]"
  851. layout="total, sizes, prev, pager, next, jumper"
  852. :total="total"
  853. @size-change="handlePageSizeChange"
  854. @current-change="handleCurrentChange"
  855. ></el-pagination>
  856. </div>
  857. </el-card>
  858. </el-col>
  859. </el-row>
  860. <!-- 导出excel提前展示的信息面板 -->
  861. <el-dialog
  862. v-model="showExportInfoPanel"
  863. title="导出信息确认"
  864. width="400px"
  865. :close-on-click-modal="false"
  866. >
  867. <div class="info-panel-header">导出信息</div>
  868. <div v-if="!rechargeVo.activityId && !rechargeVo.area && !rechargeVo.startDate && !rechargeVo.endDate">
  869. 你正在导出所有数据
  870. </div>
  871. <div v-else>
  872. 你正在导出以下数据
  873. </div>
  874. <div v-if="rechargeVo.activityId">活动名称{{ rechargeVo.activityId || '' }}</div>
  875. <div v-if="rechargeVo.area">所属地区{{ rechargeVo.area || '' }}</div>
  876. <div v-if="rechargeVo.startDate || rechargeVo.endDate">
  877. <span>充值时间</span>
  878. <span>{{ rechargeVo.startDate ? moment(rechargeVo.startDate).format('YYYY-MM-DD HH:mm:ss') : '无起始时间' }} {{ rechargeVo.endDate ? moment(rechargeVo.endDate).format('YYYY-MM-DD HH:mm:ss') : '无结束时间' }}</span>
  879. </div>
  880. <template #footer>
  881. <span class="dialog-footer">
  882. <el-button @click="showExportInfoPanel = false">取消</el-button>
  883. <el-button type="primary" @click="doExportExcel">导出</el-button>
  884. </span>
  885. </template>
  886. </el-dialog>
  887. <!-- 导出进度弹窗 -->
  888. <el-dialog
  889. v-model="isExporting"
  890. title="正在导出"
  891. width="400px"
  892. :close-on-click-modal="false"
  893. :show-close="false"
  894. >
  895. <el-progress
  896. :percentage="exportProgress"
  897. :format="(percentage) => `${percentage}%`"
  898. />
  899. <template #footer>
  900. <span class="dialog-footer">
  901. <el-button type="danger" @click="cancelExport">取消导出</el-button>
  902. </span>
  903. </template>
  904. </el-dialog>
  905. </template>
  906. <style scoped>
  907. .pagination {
  908. display: flex;
  909. }
  910. .status {
  911. display: flex;
  912. }
  913. .head-card {
  914. display: flex;
  915. }
  916. .head-card-element {
  917. margin-right: 20px;
  918. }
  919. .head-card-btn {
  920. margin-left: auto;
  921. }
  922. </style>