金币系统前端
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

1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
3 weeks ago
3 weeks ago
1 month ago
3 weeks ago
1 month ago
3 weeks ago
1 month ago
1 month ago
3 weeks ago
3 weeks ago
1 month ago
3 weeks ago
1 month ago
3 weeks ago
1 month ago
1 month ago
3 weeks ago
3 weeks ago
1 month ago
3 weeks ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
3 weeks ago
1 month ago
1 month ago
1 month 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>