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

856 lines
27 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
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
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
6 days ago
  1. <script setup>
  2. import { ref, onMounted, reactive, computed } 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 request from '@/util/http'
  8. import moment from 'moment'
  9. import API from '../../api/index.js'
  10. // 变量
  11. // 这是动态表头,
  12. const columnOptions = ref([
  13. { prop: 'username', label: '姓名', width: 125 },
  14. { prop: 'jwcode', label: '精网号', width: 125 },
  15. { prop: 'area', label: '所属地区', width: 125 },
  16. { prop: 'activityName', label: '活动名称', width: 150 },
  17. { prop: 'rechargeGold', label: '充值金额', width: 125, sortable: true },
  18. { prop: 'rechargeWay', label: '充值方式', width: 125 },
  19. { prop: 'paidGold', label: '永久金币', width: 125, sortable: true },
  20. { prop: 'freeGold', label: '免费金币', width: 125, sortable: true },
  21. { prop: 'remark', label: '备注', width: 200, showOverflowTooltip: true },
  22. { prop: 'payWay', label: '支付方式', width: 125 },
  23. { prop: 'rechargeVoucher', label: '支付凭证', width: 125 },
  24. { prop: 'name', label: '提交人', width: 125 },
  25. { prop: 'status', label: '审核状态', width: 125 },
  26. { prop: 'reson', label: '驳回理由', width: 200 },
  27. { prop: 'rechargeTime', label: '交款时间', width: 200, sortable: true },
  28. { prop: 'createTime', label: '提交时间', width: 200, sortable: true },
  29. { prop: 'auditTime', label:'审核时间', width:200, sortable:true}
  30. ])
  31. // 默认显示
  32. const defaultColumns = ['username', 'jwcode', 'area', 'activityName', 'rechargeGold', 'rechargeWay', 'paidGold', 'freeGold',
  33. 'remark', 'payWay', 'rechargeVoucher', 'name', 'status', 'reson', 'rechargeTime', 'createTime', 'auditTime']
  34. const selectedColumns = ref([...defaultColumns])
  35. //这是获取用户信息的接口
  36. const adminData = ref({})
  37. const getAdminData = async function () {
  38. try {
  39. const result = await request({
  40. url: '/admin/userinfo',
  41. data: {}
  42. })
  43. adminData.value = result
  44. console.log('请求成功', result)
  45. console.log('用户信息', adminData.value)
  46. } catch (error) {
  47. console.log('请求失败', error)
  48. }
  49. }
  50. // 充值明细表格
  51. const tableData = ref([])
  52. // 搜索======================================
  53. // 搜索rechargeVo
  54. const rechargeVo = ref({
  55. rechargeWay: '客服充值'
  56. })
  57. // 搜索对象
  58. const getObj = ref({
  59. pageNum: 1,
  60. pageSize: 50
  61. })
  62. //分页总条目
  63. const total = ref(100)
  64. // 搜索对象时间
  65. const getTime = ref([])
  66. // 搜索活动列表
  67. const activity = ref([])
  68. // 所有信息
  69. const allData = ref([])
  70. // 搜索地区列表
  71. const area = ref([])
  72. // 编辑======================================
  73. // 驳回弹出框
  74. const rejectVisible = ref(false)
  75. // 驳回对象
  76. const rejectObj = ref({})
  77. // 通过对象
  78. const passObj = ref({})
  79. //标签页默认高亮选项
  80. const activeName = ref('all')
  81. // 支付方式选项
  82. const payWay = [
  83. {
  84. value: '微信',
  85. label: '微信'
  86. },
  87. {
  88. value: '支付宝',
  89. label: '支付宝'
  90. },
  91. {
  92. value: '银联',
  93. label: '银联'
  94. },
  95. {
  96. value: '信用卡',
  97. label: '信用卡'
  98. },
  99. {
  100. value: '借记卡',
  101. label: '借记卡'
  102. }
  103. ]
  104. // //表格高度
  105. // const tableHeight = computed(function () {
  106. // return (getObj.value.pageSize + 2) * 60 + "px";
  107. // });
  108. // 表单验证ref
  109. const Ref = ref(null)
  110. // 方法
  111. // 合计数存储
  112. // 统计合计数
  113. const trueGold = ref(0)
  114. const trueCount = ref(0)
  115. const trueRGold = ref(0)
  116. const trueFGold = ref(0)
  117. // 转化一下,保留两位小数,展示时填充转化后的变量名
  118. const formattedTrueGold = computed(() => trueGold.value.toFixed(2))
  119. const formattedTrueRGold = computed(() => trueRGold.value.toFixed(2))
  120. const formattedTrueFGold = computed(() => trueFGold.value.toFixed(2))
  121. // 待审核条数
  122. const pendingCount = ref(0)
  123. // 待审核金币数
  124. const pendingGold = ref(0)
  125. const pendingRGold = ref(0)
  126. const pendingFGold = ref(0)
  127. // 已通过条数
  128. const approvedCount = ref(0)
  129. // 已通过金币数
  130. const approvedGold = ref(0)
  131. const approvedRGold = ref(0)
  132. const approvedFGold = ref(0)
  133. // 已驳回条数
  134. const rejectedCount = ref(0)
  135. // 已驳回金币数
  136. const rejectedGold = ref(0)
  137. const rejectedRGold = ref(0)
  138. const rejectedFGold = ref(0)
  139. // 搜索==============================================================
  140. // 搜索方法
  141. const get = async function (val) {
  142. try {
  143. // 地区赋值
  144. if (adminData.value.area === '泰国') {
  145. rechargeVo.value.areas = ['泰国', '越南']
  146. } else if (adminData.value.area !== '总部') {
  147. rechargeVo.value.area = adminData.value.area
  148. }
  149. // 搜索参数页码赋值
  150. if (typeof val === 'number') {
  151. getObj.value.pageNum = val
  152. }
  153. // 搜索参数时间赋值
  154. if (getTime.value != null) {
  155. if (getTime.value.startDate != '' && getTime.value.endDate != '') {
  156. rechargeVo.value.startDate = getTime.value[0]
  157. rechargeVo.value.endDate = getTime.value[1]
  158. }
  159. } else {
  160. rechargeVo.value.startDate = ''
  161. rechargeVo.value.endDate = ''
  162. }
  163. rechargeVo.value.sortField = sortField.value
  164. rechargeVo.value.sortOrder = sortOrder.value
  165. console.log('搜索参数', getObj.value)
  166. // 发送POST请求
  167. const result = await request({
  168. url: '/recharge/recharge',
  169. data: {
  170. pageNum: getObj.value.pageNum,
  171. pageSize: getObj.value.pageSize,
  172. rechargeVo: { ...rechargeVo.value }
  173. }
  174. })
  175. // 合计数的接口
  176. // 复制一份 rechargeVo.value 并移除排序字段和排序方式
  177. const detailWithoutSort = { ...rechargeVo.value }
  178. delete detailWithoutSort.sortField
  179. delete detailWithoutSort.sortOrder
  180. delete detailWithoutSort.status
  181. const result2 = await request({
  182. url: '/recharge/recharge/RechargeA',
  183. data: detailWithoutSort
  184. })
  185. // 做一个判断,如果result2.data[i].flag="待审核",那么 totalData.value = result2.data[i],否则就赋值为0
  186. // 统计合计数
  187. if (result2.data) {
  188. result2.data.forEach((item) => {
  189. switch (item.auditStatus) {
  190. case '待审核':
  191. // 若 item.raudit 为空则赋值为 0
  192. pendingCount.value = item.raudit || 0
  193. // 若 item.sumRaudit 为空则赋值为 0
  194. pendingGold.value = item.sumRaudit || 0
  195. pendingRGold.value = item.sumRaudit1 || 0
  196. pendingFGold.value = item.sumRaudit2 || 0
  197. break
  198. case '已通过':
  199. approvedCount.value = item.raudit || 0
  200. approvedGold.value = item.sumRaudit || 0
  201. approvedRGold.value = item.sumRaudit1 || 0
  202. approvedFGold.value = item.sumRaudit2 || 0
  203. break
  204. case '已驳回':
  205. rejectedCount.value = item.raudit || 0
  206. rejectedGold.value = item.sumRaudit || 0
  207. rejectedRGold.value = item.sumRaudit1 || 0
  208. rejectedFGold.value = item.sumRaudit2 || 0
  209. break
  210. }
  211. })
  212. }
  213. trueGold.value = pendingGold.value + approvedGold.value + rejectedGold.value
  214. trueCount.value =
  215. pendingCount.value + approvedCount.value + rejectedCount.value
  216. trueRGold.value =
  217. pendingRGold.value + approvedRGold.value + rejectedRGold.value
  218. trueFGold.value =
  219. pendingFGold.value + approvedFGold.value + rejectedFGold.value
  220. // 将响应结果存储到响应式数据中
  221. console.log('请求成功', result)
  222. console.log('这是分页', getObj.value)
  223. // 存储表格数据
  224. tableData.value = result.data.list
  225. console.log('tableData', tableData.value)
  226. // 存储分页总数
  227. total.value = result.data.total
  228. console.log('total', total.value)
  229. } catch (error) {
  230. console.log('请求失败', error)
  231. // 在这里可以处理错误逻辑,比如显示错误提示等
  232. }
  233. }
  234. // 搜索
  235. const search = function () {
  236. trimJwCode();
  237. getObj.value.pageNum = 1
  238. get()
  239. }
  240. // 重置
  241. const reset = function () {
  242. delete rechargeVo.value.activityId
  243. delete rechargeVo.value.jwcode
  244. delete rechargeVo.value.payWay
  245. delete rechargeVo.value.area
  246. delete rechargeVo.value.startDate
  247. delete rechargeVo.value.endDate
  248. getTime.value = {}
  249. }
  250. // 今天
  251. const getToday = function () {
  252. const today = new Date()
  253. const startDate = new Date(
  254. today.getFullYear(),
  255. today.getMonth(),
  256. today.getDate()
  257. )
  258. const endDate = new Date(
  259. today.getFullYear(),
  260. today.getMonth(),
  261. today.getDate() + 1
  262. )
  263. getTime.value = [startDate, endDate]
  264. console.log('getTime', getTime.value)
  265. get()
  266. }
  267. // 昨天
  268. const getYesterday = function () {
  269. const yesterday = new Date()
  270. yesterday.setDate(yesterday.getDate() - 1)
  271. const startDate = new Date(
  272. yesterday.getFullYear(),
  273. yesterday.getMonth(),
  274. yesterday.getDate()
  275. )
  276. const endDate = new Date(
  277. yesterday.getFullYear(),
  278. yesterday.getMonth(),
  279. yesterday.getDate() + 1
  280. )
  281. getTime.value = [startDate, endDate]
  282. console.log('getTime', getTime.value)
  283. get()
  284. }
  285. // 近7天
  286. const get7Days = function () {
  287. const today = new Date()
  288. const startDate = new Date(
  289. today.getFullYear(),
  290. today.getMonth(),
  291. today.getDate() - 6
  292. )
  293. const endDate = new Date(
  294. today.getFullYear(),
  295. today.getMonth(),
  296. today.getDate() + 1
  297. )
  298. getTime.value = [startDate, endDate]
  299. console.log('getTime', getTime.value)
  300. get()
  301. }
  302. //全部充值明细
  303. const adminAll = function () {
  304. console.log('adminAll')
  305. rechargeVo.value.status = ''
  306. getObj.value.pageNum = 1
  307. get()
  308. }
  309. //待审核充值明细
  310. const adminWait = async function () {
  311. rechargeVo.value.status = 0
  312. getObj.value.pageNum = 1
  313. await get()
  314. console.log('adminWait')
  315. trueCount.value = pendingCount.value
  316. trueGold.value = pendingGold.value
  317. trueRGold.value = pendingRGold.value
  318. trueFGold.value = pendingFGold.value
  319. }
  320. //已通过充值明细
  321. const adminPass = async function () {
  322. rechargeVo.value.status = 1
  323. getObj.value.pageNum = 1
  324. await get()
  325. console.log('adminPass')
  326. trueCount.value = approvedCount.value
  327. trueGold.value = approvedGold.value
  328. trueRGold.value = approvedRGold.value
  329. trueFGold.value = approvedFGold.value
  330. }
  331. //已驳回充值明细
  332. const adminReject = async function () {
  333. rechargeVo.value.status = 2
  334. getObj.value.pageNum = 1
  335. await get()
  336. console.log('adminReject')
  337. trueCount.value = rejectedCount.value
  338. trueGold.value = rejectedGold.value
  339. trueRGold.value = rejectedRGold.value
  340. trueFGold.value = rejectedFGold.value
  341. }
  342. //点击标签页
  343. const handleClick = function (tab, event) {
  344. if (tab.props.name === 'all') {
  345. adminAll()
  346. } else if (tab.props.name === 'wait') {
  347. adminWait()
  348. } else if (tab.props.name === 'pass') {
  349. adminPass()
  350. } else if (tab.props.name === 'reject') {
  351. adminReject()
  352. }
  353. }
  354. // 获取活动名称
  355. const getActivity = async function () {
  356. try {
  357. // 发送POST请求
  358. const result = await request({
  359. url: '/recharge/activity/select',
  360. data: {}
  361. })
  362. // 将响应结果存储到响应式数据中
  363. console.log('请求成功', result)
  364. // 存储表格数据
  365. activity.value = result.data
  366. console.log('activity', activity.value)
  367. } catch (error) {
  368. console.log('请求失败', error)
  369. // 在这里可以处理错误逻辑,比如显示错误提示等
  370. }
  371. }
  372. // 获取地区
  373. const getArea = async function () {
  374. try {
  375. // 发送POST请求
  376. const result = await request({
  377. url: '/recharge/user/search',
  378. data: {}
  379. })
  380. // 将响应结果存储到响应式数据中
  381. console.log('请求成功', result)
  382. // 存储地区信息
  383. area.value = result.data
  384. console.log('地区', area.value)
  385. } catch (error) {
  386. console.log('请求失败', error)
  387. // 在这里可以处理错误逻辑,比如显示错误提示等
  388. }
  389. }
  390. // 验证跳转输入框的数字是否合法
  391. const checkNumber = function () {
  392. if (typeof parseInt(getObj.value.pageNum) === 'number') {
  393. console.log('总共有多少页' + Math.ceil(total.value / getObj.value.pageSize))
  394. if (
  395. getObj.value.pageNum > 0 &&
  396. getObj.value.pageNum <= Math.ceil(total.value / getObj.value.pageSize)
  397. ) {
  398. console.log('输入的数字合法')
  399. getObj.value.pageNum = parseInt(getObj.value.pageNum)
  400. get()
  401. } else {
  402. //提示
  403. ElMessage({
  404. type: 'error',
  405. message: '请检查输入内容'
  406. })
  407. }
  408. } else {
  409. //提示
  410. ElMessage({
  411. type: 'error',
  412. message: '请检查输入内容'
  413. })
  414. }
  415. }
  416. const handlePageSizeChange = function (val) {
  417. getObj.value.pageSize = val
  418. get()
  419. }
  420. const handleCurrentChange = function (val) {
  421. getObj.value.pageNum = val
  422. get()
  423. }
  424. // 编辑====================================
  425. // 通过按钮
  426. const pass = function (row) {
  427. // 通过初始化
  428. passObj.value = row
  429. passObj.value.adminId = adminData.value.adminId
  430. passObj.value.auditId = row.auditId
  431. // passObj.value.status = 1
  432. passObj.value.rechargeId = row.rechargeId
  433. passObj.value.detailId = row.detailId
  434. passObj.value.jwcode = row.jwcode
  435. passObj.value.paidGold = row.paidGold
  436. passObj.value.freeGold = row.freeGold
  437. passObj.value.adminName = adminData.value.adminName
  438. console.log('通过对象', passObj.value)
  439. }
  440. // 通过确认
  441. const passConfirm = async function () {
  442. try {
  443. // 也许大概应该在点击确认时改变状态
  444. passObj.value.status = 1
  445. console.log('通过对象', passObj.value)
  446. // 发送POST请求
  447. // passObj.value.flag = 0;
  448. const result = await request({
  449. url: '/audit/audit/goldedit',
  450. data: passObj.value
  451. })
  452. // 将响应结果存储到响应式数据中
  453. console.log('请求成功', result)
  454. // 刷新表格数据
  455. get()
  456. //提示
  457. ElMessage({
  458. type: 'success',
  459. message: '通过成功!'
  460. })
  461. } catch (error) {
  462. console.error('请求失败', error);
  463. // 提示网络请求错误
  464. ElMessage({
  465. type: 'error',
  466. message: '网络请求出错,请检查网络连接!'
  467. });
  468. }
  469. }
  470. // 打开驳回弹出框
  471. const openRejectVisible = function () {
  472. rejectVisible.value = true
  473. }
  474. // 关闭驳回弹出框
  475. const closeRejectVisible = function () {
  476. rejectVisible.value = false
  477. }
  478. // 驳回按钮
  479. const reject = function (row) {
  480. // 驳回初始化
  481. rejectObj.value.adminId = adminData.value.adminId
  482. rejectObj.value.auditId = row.auditId
  483. rejectObj.value.status = 2
  484. rejectObj.value.reson = ''
  485. rejectObj.value.rechargeId = row.rechargeId
  486. rejectObj.value.detailId = row.detailId
  487. console.log('驳回对象', rejectObj.value)
  488. openRejectVisible()
  489. }
  490. // 驳回确认
  491. const rejectConfirm = async function () {
  492. Ref.value.validate(async (valid) => {
  493. if (valid) {
  494. try {
  495. console.log('驳回对象', rejectObj.value)
  496. // 发送POST请求
  497. const result = await request({
  498. url: '/audit/audit/goldedit',
  499. data: rejectObj.value
  500. })
  501. // 将响应结果存储到响应式数据中
  502. console.log('请求成功', result)
  503. // 刷新表格数据
  504. get()
  505. // 关闭弹出框
  506. closeRejectVisible()
  507. //提示
  508. ElMessage({
  509. type: 'success',
  510. message: '驳回成功!'
  511. })
  512. } catch (error) {
  513. console.log('请求失败', error)
  514. // 在这里可以处理错误逻辑,比如显示错误提示等
  515. }
  516. } else {
  517. //提示
  518. ElMessage({
  519. type: 'error',
  520. message: '请检查输入内容'
  521. })
  522. }
  523. })
  524. }
  525. // 表单验证
  526. const rules = reactive({
  527. reson: [{ required: true, message: '请输入驳回理由', trigger: 'blur' }]
  528. })
  529. // 挂载
  530. onMounted(async function () {
  531. await getAdminData()
  532. await getActivity()
  533. await get()
  534. await getArea()
  535. })
  536. // 新增排序字段和排序方式
  537. const sortField = ref('')
  538. const sortOrder = ref('')
  539. // 处理排序事件
  540. const handleSortChange = (column) => {
  541. console.log('排序字段:', column.prop)
  542. console.log('排序方式:', column.order)
  543. if (column.prop === 'rechargeGold') {
  544. sortField.value = 'recharge_gold'
  545. } else if (column.prop === 'freeGold') {
  546. sortField.value = 'free_gold'
  547. } else if (column.prop === 'rechargeTime') {
  548. sortField.value = 'recharge_time'
  549. } else if (column.prop === 'createTime') {
  550. sortField.value = 'create_time'
  551. } else if (column.prop === 'paidGold') {
  552. sortField.value = 'paid_gold'
  553. }else if (column.prop === 'auditTime') {
  554. sortField.value = 'audit_time'
  555. }
  556. sortOrder.value = column.order === 'ascending' ? 'ASC' : 'DESC'
  557. get()
  558. }
  559. // 精网号去空格
  560. const trimJwCode = () => {
  561. if (rechargeVo.value.jwcode) {
  562. rechargeVo.value.jwcode = rechargeVo.value.jwcode.replace(/\s/g, '');
  563. }
  564. }
  565. </script>
  566. <template>
  567. <el-row>
  568. <el-col>
  569. <el-card style="margin-bottom: 20px">
  570. <el-row style="margin-bottom: 10px">
  571. <el-col :span="6">
  572. <div class="head-card-element">
  573. <el-text class="mx-1" size="large">精网号</el-text>
  574. <el-input v-model="rechargeVo.jwcode" placeholder="请输入精网号" style="width: 240px" clearable />
  575. </div>
  576. </el-col>
  577. <el-col :span="6">
  578. <div class="head-card-element">
  579. <el-text class="mx-1" size="large">活动名称</el-text>
  580. <el-select v-model="rechargeVo.activityId" placeholder="请选择活动名称" style="width: 240px"
  581. clearable>
  582. <el-option v-for="item in activity" :key="item.activityId" :label="item.activityName"
  583. :value="item.activityId" />
  584. </el-select>
  585. </div>
  586. </el-col>
  587. <el-col :span="6">
  588. <div class="head-card-element">
  589. <el-text class="mx-1" size="large">支付方式</el-text>
  590. <el-select v-model="rechargeVo.payWay" placeholder="请选择支付方式" style="width: 240px" clearable>
  591. <el-option v-for="item in payWay" :key="item.value" :label="item.label" :value="item.value" />
  592. </el-select>
  593. </div>
  594. </el-col>
  595. <el-col :span="6">
  596. <div class="head-card-element" v-if="adminData.area == '总部'">
  597. <el-text class="mx-1" size="large">所属地区</el-text>
  598. <el-select v-model="rechargeVo.area" placeholder="请选择所属地区" style="width: 240px" clearable>
  599. <el-option v-for="item in area" :key="item" :label="item" :value="item" />
  600. </el-select>
  601. </div>
  602. </el-col>
  603. </el-row>
  604. <el-row>
  605. <el-col :span="16">
  606. <div class="time-controls">
  607. <div class="time-group">
  608. <el-text class="mx-1" size="large">充值时间</el-text>
  609. <el-date-picker
  610. v-model="getTime"
  611. type="datetimerange"
  612. range-separator="至"
  613. start-placeholder="起始时间"
  614. end-placeholder="结束时间"
  615. style="width: 400px"
  616. />
  617. <el-button @click="getToday()" style="margin-left: 10px"> </el-button>
  618. <el-button @click="getYesterday()" style="margin-left: 10px"> </el-button>
  619. <el-button @click="get7Days()" style="margin-left: 10px"> 近7天 </el-button>
  620. </div>
  621. </div>
  622. </el-col>
  623. <el-col :span="8">
  624. <el-button @click="reset()" type="success" style="margin-right: 10px">重置</el-button>
  625. <el-button type="primary" @click="search()">查询</el-button>
  626. </el-col>
  627. </el-row>
  628. <el-row>
  629. <el-col :span="21">
  630. <div style="margin-top: 10px">
  631. <el-text class="mx-1" size="large">请选择您想看到的数据</el-text>
  632. <el-select v-model="selectedColumns" multiple placeholder="请选择您想看到的数据" size="large" style="width: 800px">
  633. <el-option v-for="item in columnOptions" :key="item.prop" :label="item.label" :value="item.prop" />
  634. </el-select>
  635. </div>
  636. </el-col>
  637. </el-row>
  638. </el-card>
  639. </el-col>
  640. </el-row>
  641. <el-row>
  642. <el-col>
  643. <el-card>
  644. <el-tabs v-model="activeName" type="card" class="demo-tabs" @tab-click="handleClick">
  645. <el-tab-pane label="全部" name="all"></el-tab-pane>
  646. <el-tab-pane label="待审核" name="wait"></el-tab-pane>
  647. <el-tab-pane label="已通过" name="pass"></el-tab-pane>
  648. <el-tab-pane label="已驳回" name="reject"></el-tab-pane>
  649. <div>
  650. 总条数{{ trueCount }}总金币数{{
  651. formattedTrueGold
  652. }}金币永久金币{{ formattedTrueRGold }}金币免费金币{{ formattedTrueFGold }}金币
  653. </div>
  654. </el-tabs>
  655. <div style="height: 540px; overflow-y: auto">
  656. <el-table :data="tableData" style="width: 100%" height="540px" @sort-change="handleSortChange" :row-style="{ height: '50px' }">
  657. <el-table-column type="index" label="序号" width="100px" fixed="left">
  658. <template #default="scope">
  659. <span>{{
  660. scope.$index + 1 + (getObj.pageNum - 1) * getObj.pageSize
  661. }}</span>
  662. </template>
  663. </el-table-column>
  664. <!-- 动态列 -->
  665. <template v-for="col in columnOptions" :key="col.prop">
  666. <el-table-column v-if="selectedColumns.includes(col.prop)" :prop="col.prop" :label="col.label"
  667. :width="col.width" :sortable="col.sortable ? 'custom' : false"
  668. :show-overflow-tooltip="true" >
  669. <template #default="scope">
  670. <!-- 特殊列模板 -->
  671. <template v-if="col.prop === 'rechargeTime'">
  672. {{ moment(scope.row.rechargeTime).format('YYYY-MM-DD HH:mm:ss') }}
  673. </template>
  674. <template v-else-if="col.prop === 'createTime'">
  675. {{ moment(scope.row.createTime).format('YYYY-MM-DD HH:mm:ss') }}
  676. </template>
  677. <template v-else-if="col.prop === 'auditTime'">
  678. {{ scope.row.auditTime ? moment(scope.row.auditTime).format('YYYY-MM-DD HH:mm:ss') : '----' }}
  679. </template>
  680. <template v-else-if="col.prop === 'remark'">
  681. <span>{{ scope.row[col.prop] }}</span>
  682. </template>
  683. <template v-else-if="col.prop === 'rechargeVoucher'">
  684. <el-image :src="scope.row.rechargeVoucher" style="width: 50px; height: 50px" />
  685. </template>
  686. <template v-else-if="col.prop === 'status'">
  687. <div class="status">
  688. <span :class="{
  689. 'green-dot': scope.row.status === 1,
  690. 'grey-dot': scope.row.status === 0,
  691. 'red-dot': scope.row.status === 2
  692. }"></span>
  693. <span>{{
  694. scope.row.status === 1 ? '已通过' :
  695. scope.row.status === 0 ? '待审核' : '已驳回'
  696. }}</span>
  697. </div>
  698. </template>
  699. <template v-else-if="['paidGold', 'freeGold'].includes(col.prop)">
  700. {{ scope.row[col.prop] / 100 }}
  701. </template>
  702. <span v-else>
  703. {{ scope.row[col.prop] }}
  704. </span>
  705. </template>
  706. </el-table-column>
  707. </template>
  708. <el-table-column fixed="right" prop="operation" label="操作" width="150px">
  709. <template #default="scope">
  710. <div class="operation">
  711. <el-popconfirm title="确定要通过此条记录吗?" @confirm="passConfirm">
  712. <template #reference>
  713. <el-button :disabled="scope.row.status === 1 || scope.row.status === 2
  714. ? true
  715. : false
  716. " type="primary" text @click="pass(scope.row)">
  717. 通过
  718. </el-button>
  719. </template>
  720. <template #actions="{ confirm, cancel }">
  721. <el-button size="small" @click="cancel">取消</el-button>
  722. <el-button type="primary" size="small" @click="confirm">
  723. 确定
  724. </el-button>
  725. </template>
  726. </el-popconfirm>
  727. <el-button :disabled="scope.row.status === 1 || scope.row.status === 2
  728. ? true
  729. : false
  730. " type="primary" text @click="reject(scope.row)">
  731. 驳回
  732. </el-button>
  733. </div>
  734. </template>
  735. </el-table-column>
  736. </el-table>
  737. </div>
  738. <!-- 分页 -->
  739. <div class="pagination">
  740. <el-pagination background :page-size="getObj.pageSize" :page-sizes="[5, 10, 20, 50, 100]"
  741. layout="total, sizes, prev, pager, next, jumper" :total="total" @size-change="handlePageSizeChange"
  742. @current-change="handleCurrentChange"></el-pagination>
  743. </div>
  744. </el-card>
  745. </el-col>
  746. </el-row>
  747. <!-- 驳回弹出框 -->
  748. <el-dialog v-model="rejectVisible" title="驳回理由" width="500" :before-close="closeRejectVisible">
  749. <template #footer>
  750. <el-form :model="rejectObj" ref="Ref" :rules="rules" label-width="auto" style="max-width: 600px">
  751. <el-form-item prop="reson" label="驳回理由:">
  752. <el-input v-model="rejectObj.reson" maxlength="150" show-word-limit style="width: 350px" type="textarea"
  753. placeholder="请输入内容" />
  754. </el-form-item>
  755. </el-form>
  756. <div class="dialog-footer">
  757. <el-button @click="closeRejectVisible()">取消</el-button>
  758. <el-button type="primary" @click="rejectConfirm()"> 确定 </el-button>
  759. </div>
  760. </template>
  761. </el-dialog>
  762. </template>
  763. <style scoped>
  764. .pagination {
  765. display: flex;
  766. }
  767. .operation {
  768. display: flex;
  769. }
  770. .green-dot {
  771. background-color: #67C23A;
  772. }
  773. .grey-dot {
  774. background-color: #909399;
  775. }
  776. .red-dot {
  777. background-color: #F56C6C;
  778. }
  779. .time-controls {
  780. display: flex;
  781. align-items: center;
  782. }
  783. .time-group {
  784. display: flex;
  785. align-items: center;
  786. gap: 10px;
  787. }
  788. .quick-buttons {
  789. display: flex;
  790. align-items: center;
  791. }
  792. .status {
  793. display: flex;
  794. align-items: center; /* 确保子元素垂直居中对齐 */
  795. gap: 6px; /* 设置圆点和文字之间的间距 */
  796. }
  797. .green-dot, .grey-dot, .red-dot {
  798. display: inline-block;
  799. width: 8px;
  800. height: 8px;
  801. border-radius: 50%;
  802. flex-shrink: 0; /* 防止圆点在空间不足时缩小 */
  803. margin: 0; /* 移除原有的 margin-right */
  804. }
  805. /* 备注列样式 */
  806. .remark-cell {
  807. display: block;
  808. width: 100%;
  809. overflow: hidden;
  810. text-overflow: ellipsis;
  811. white-space: nowrap;
  812. }
  813. /* 设置单元格内容溢出隐藏 */
  814. .el-table .el-table__cell {
  815. overflow: hidden;
  816. text-overflow: ellipsis;
  817. white-space: nowrap;
  818. }
  819. </style>