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.

505 lines
14 KiB

  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 moment from 'moment'
  8. import API from '@/util/http.js'
  9. const defaultTime = [
  10. new Date(2000, 1, 1, 0, 0, 0),
  11. new Date(2000, 2, 1, 23, 59, 59),
  12. ]
  13. const selectData = ref({
  14. jwcode: '',
  15. market: '',
  16. startTime: '',
  17. endTime: '',
  18. })
  19. const permanentBeans = ref(0)
  20. const num = ref(0)
  21. const money = ref(0)
  22. //获取当齐全条件的金豆总数
  23. const getTotalBeans = async () => {
  24. try {
  25. const result = await API({
  26. url: '/beanRecharge/statsOnlineBean',
  27. data: {
  28. ...selectData.value,
  29. }
  30. })
  31. if (result.code == 200) {
  32. if(result.data){
  33. permanentBeans.value = result.data.permanentBean
  34. num.value = result.data.num
  35. money.value = result.data.money
  36. }else{
  37. permanentBeans.value = 0
  38. num.value = 0
  39. money.value = 0
  40. }
  41. console.log('金豆总数获取成功');
  42. }
  43. console.log('获取金豆总数失败:', result.msg);
  44. } catch (error) {
  45. console.log('获取金豆总数出错');
  46. }
  47. }
  48. //时间格式化
  49. const formatTime = (val) => val ? moment(val).format('YYYY-MM-DD HH:mm:ss') : ''
  50. const tableData = ref([])
  51. //存储所有的地区数据
  52. const market = ref()
  53. const getTime = ref([])
  54. //记录当前选中时间按钮状态
  55. const activeTimeRange = ref('')
  56. const handleDatePickerChange = () => {
  57. activeTimeRange.value = ''
  58. console.log('当前选中时间范围', getTime.value);
  59. }
  60. //获取所有地区
  61. const getArea = async () => {
  62. const result = await API({
  63. url: '/beanRecharge/onlineMarket',
  64. data: {}
  65. })
  66. if (result.code == 200) {
  67. market.value = result.data
  68. console.log('线上充值地区获取成功', market.value)
  69. } else {
  70. ElMessage.error('线上充值地区获取失败')
  71. }
  72. }
  73. //获取今天日期
  74. const getToday = () => {
  75. const today = new Date()
  76. const startTime = new Date(
  77. today.getFullYear(),
  78. today.getMonth(),
  79. today.getDate(),
  80. )
  81. const endTime = new Date(
  82. today.getFullYear(),
  83. today.getMonth(),
  84. today.getDate(),
  85. 23, 59, 59
  86. )
  87. getTime.value = [startTime, endTime]
  88. activeTimeRange.value = 'today'
  89. search();
  90. }
  91. const getYesterday = () => {
  92. const yesterday = new Date()
  93. yesterday.setDate(yesterday.getDate() - 1)
  94. const startTime = new Date(
  95. yesterday.getFullYear(),
  96. yesterday.getMonth(),
  97. yesterday.getDate()
  98. )
  99. const endTime = new Date(
  100. yesterday.getFullYear(),
  101. yesterday.getMonth(),
  102. yesterday.getDate(),
  103. 23, 59, 59
  104. )
  105. getTime.value = [startTime, endTime]
  106. activeTimeRange.value = 'yesterday'
  107. search();
  108. }
  109. const get7Days = function () {
  110. const today = new Date()
  111. const startTime = new Date(
  112. today.getFullYear(),
  113. today.getMonth(),
  114. today.getDate() - 6
  115. )
  116. const endTime = new Date(
  117. today.getFullYear(),
  118. today.getMonth(),
  119. today.getDate(),
  120. 23, 59, 59
  121. )
  122. getTime.value = [startTime, endTime]
  123. activeTimeRange.value = '7days'
  124. search();
  125. }
  126. const reset = () => {
  127. selectData.value = {
  128. jwcode: '',
  129. market: '',
  130. startTime: '',
  131. endTime: '',
  132. }
  133. getTime.value = []
  134. activeTimeRange.value = ''
  135. search()
  136. }
  137. //查询
  138. const search = () => {
  139. getObj.value.pageNum = 1
  140. //判断精网号查询是否为数字
  141. getObj.value.pageNum = 1
  142. if (selectData.value.jwcode) {
  143. const numRef = /^\d{1,9}$/;
  144. if (!numRef.test(selectData.value.jwcode)) {
  145. ElMessage.error('请检查精网号格式')
  146. return
  147. }
  148. }
  149. get()
  150. getTotalBeans()
  151. }
  152. //获取表格数据
  153. const get = async () => {
  154. try {
  155. if (getTime.value != null) {
  156. selectData.value.startTime = formatTime(getTime.value[0])
  157. selectData.value.endTime = formatTime(getTime.value[1])
  158. } else {
  159. selectData.value.startTime = ''
  160. selectData.value.endTime = ''
  161. }
  162. const data = {
  163. ...getObj.value,
  164. beanOnlineRechargeInfo: {
  165. ...selectData.value,
  166. sortField: sortField.value,
  167. sortOrder: sortOrder.value,
  168. },
  169. }
  170. console.log('请求参数:', data);
  171. const result = await API({
  172. url: '/beanRecharge/selectByOnline',
  173. data: data
  174. })
  175. if (result.code == 200) {
  176. tableData.value = result.data.list
  177. total.value = result.data.total
  178. } else {
  179. ElMessage.error(result.message)
  180. }
  181. } catch (error) {
  182. console.log('搜索失败', error);
  183. }
  184. }
  185. //充值平台
  186. const platform = [
  187. {
  188. value: 1,
  189. label: 'PC'
  190. },
  191. {
  192. value: 2,
  193. label: '手机'
  194. }
  195. ]
  196. //排序字段
  197. //处理表格排序事件
  198. const sortField = ref('')
  199. const sortOrder = ref('')
  200. const handleSortChange = (column) => {
  201. console.log('排序字段:', column.prop)
  202. console.log('排序方式:', column.order)
  203. // 直接使用允许的排序字段列表进行过滤
  204. const allowedFields = ['money', 'num'];
  205. if (allowedFields.includes(column.prop)) {
  206. sortField.value = column.prop;
  207. }
  208. sortOrder.value = column.order === 'ascending' ? 'ASC' : 'DESC';
  209. console.log('传递给后端的排序字段:', sortField.value)
  210. console.log('传递给后端的排序方式:', sortOrder.value)
  211. get();
  212. }
  213. //========================分页===========================
  214. // 搜索对象
  215. const total = ref(0)
  216. const getObj = ref({
  217. pageNum: 1,
  218. pageSize: 50
  219. })
  220. const handlePageSizeChange = (value) => {
  221. getObj.value.pageSize = value
  222. get()
  223. }
  224. const handleCurrentChange = (value) => {
  225. getObj.value.pageNum = value
  226. get()
  227. }
  228. //======================导出=======================
  229. const exportExcel = async () => {
  230. const params = {
  231. ...getObj.value,
  232. beanOnlineRechargeInfo: {
  233. ...selectData.value,
  234. sortField: sortField.value,
  235. sortOrder: sortOrder.value,
  236. },
  237. }
  238. try {
  239. const res = await API({ url: '/export/exportol', data: params })
  240. if (res.code === 200) {
  241. ElMessage.success('导出成功')
  242. } else {
  243. ElMessage.error(res.message || '导出失败,请稍后重试')
  244. }
  245. } catch (error) {
  246. console.log('请求失败', error)
  247. ElMessage.error('导出失败,请稍后重试')
  248. }
  249. }
  250. const exportListVisible = ref(false)
  251. // 打开导出列表弹窗
  252. const openExportList = () => {
  253. getExportList()
  254. exportListVisible.value = true
  255. }
  256. // 导出列表数据
  257. const exportList = ref([])
  258. // 导出列表加载状态
  259. const exportListLoading = ref(false)
  260. // 获取导出列表
  261. const getExportList = async () => {
  262. exportListLoading.value = true
  263. try {
  264. const result = await API({ url: '/export/export' })
  265. if (result.code === 200) {
  266. const filteredData = result.data.filter(item => {
  267. return item.type === 10;
  268. });
  269. exportList.value = filteredData
  270. } else {
  271. ElMessage.error(result.msg || '获取导出列表失败')
  272. }
  273. } catch (error) {
  274. console.error('获取导出列表出错:', error)
  275. ElMessage.error('获取导出列表失败,请稍后重试')
  276. } finally {
  277. exportListLoading.value = false
  278. }
  279. }
  280. // 下载导出文件
  281. const downloadExportFile = (item) => {
  282. if (item.state === 2) {
  283. const link = document.createElement('a')
  284. link.href = item.url
  285. link.download = item.fileName
  286. link.click()
  287. } else {
  288. ElMessage.warning('文件还在导出中,请稍后再试')
  289. }
  290. }
  291. //根据状态返回对应的标签类型
  292. const getTagType = (state) => {
  293. switch (state) {
  294. case 0:
  295. return 'info';
  296. case 1:
  297. return 'primary';
  298. case 2:
  299. return 'success';
  300. case 3:
  301. return 'danger';
  302. default:
  303. return 'info';
  304. }
  305. }
  306. //根据状态返回对应的标签文案
  307. const getTagText = (state) => {
  308. switch (state) {
  309. case 0:
  310. return '待执行';
  311. case 1:
  312. return '执行中';
  313. case 2:
  314. return '执行完成';
  315. case 3:
  316. return '执行出错';
  317. default:
  318. return '未知状态';
  319. }
  320. }
  321. const format3 = (num) => {
  322. // 每三位添加逗号
  323. return num.toLocaleString('en-US')
  324. }
  325. onMounted(async function () {
  326. await get()
  327. await getArea()
  328. await getTotalBeans()
  329. })
  330. </script>
  331. <template>
  332. <el-card class="card1" style="margin-bottom: 0.5vh;">
  333. <div>
  334. <el-text size="large">精网号</el-text>
  335. <el-input v-model="selectData.jwcode" placeholder="请输入精网号" style="width: 10vw;margin-right: 1vw;" clearable />
  336. <el-text size="large">所属地区</el-text>
  337. <el-select v-model="selectData.market" placeholder="请选择所属地区" clearable style="width: 10vw;margin-right: 1vw;">
  338. <el-option v-for="item in market" :key="item" :label="item" :value="item" />
  339. </el-select>
  340. <el-text size="large">订单号</el-text>
  341. <el-input v-model="selectData.orderNo" placeholder="请输入订单号" style="width: 10vw;margin-right: 1vw;" clearable />
  342. <el-text size="large">充值平台</el-text>
  343. <el-select v-model="selectData.platform" placeholder="请选择充值平台" clearable style="width: 10vw;margin-right: 1vw;">
  344. <el-option v-for="item in platform" :key="item.value" :label="item.label" :value="item.value" />
  345. </el-select>
  346. </div>
  347. <div style="margin-top: 0.5vh;">
  348. <el-text size="large">充值时间</el-text>
  349. <el-date-picker v-model="getTime" type="datetimerange" range-separator="" start-placeholder="起始时间"
  350. end-placeholder="结束时间" style="width: 20vw" @change="handleDatePickerChange" :default-time="defaultTime" />
  351. <el-button @click="getToday()" style="margin-left: 10px" :type="activeTimeRange === 'today' ? 'primary' : ''">
  352. </el-button>
  353. <el-button @click="getYesterday()" style="margin-left: 10px"
  354. :type="activeTimeRange === 'yesterday' ? 'primary' : ''">
  355. </el-button>
  356. <el-button @click="get7Days()" style="margin-left: 10px" :type="activeTimeRange === '7days' ? 'primary' : ''"> 近7天
  357. </el-button>
  358. <el-button type="success" @click="reset()">重置</el-button>
  359. <el-button type="primary" @click="search()">查询</el-button>
  360. <el-button type="primary" @click="exportExcel()">导出Excel</el-button>
  361. <el-button type="primary" @click="openExportList">查看导出列表</el-button>
  362. </div>
  363. </el-card>
  364. <el-card class="card2">
  365. <div class="goldStatistics">
  366. 充值金豆数{{ format3(num) }}&nbsp;&nbsp;&nbsp;&nbsp;合计新币数{{ format3(money) }}
  367. </div>
  368. <!-- 设置表格容器的高度和滚动样式 -->
  369. <div>
  370. <el-table :data="tableData" style="width:80vw;" height="60vh" @sort-change="handleSortChange">
  371. <el-table-column type="index" label="序号" width="80px" fixed="left">
  372. <template #default="scope">
  373. <span>{{
  374. scope.$index + 1 + (getObj.pageNum - 1) * getObj.pageSize
  375. }}</span>
  376. </template>
  377. </el-table-column>
  378. <el-table-column fixed="left" prop="name" label="姓名" min-width="120" show-overflow-tooltip />
  379. <el-table-column fixed="left" prop="jwcode" label="精网号" min-width="110px" />
  380. <el-table-column prop="market" label="所属地区" min-width="100px" />
  381. <el-table-column prop="orderNo" header-align="center" align="center" label="订单号" min-width="210px" />
  382. <el-table-column prop="num" label="数量" sortable="custom" min-width="110px" />
  383. <el-table-column prop="money" label="金额" sortable="custom" min-width="150px" />
  384. <el-table-column prop="platform" label="充值平台" min-width="150px" show-overflow-tooltip>
  385. <template #default=scope>
  386. <span v-if="scope.row.platform == 1">PC</span>
  387. <span v-else-if="scope.row.platform == 2">手机</span>
  388. <span v-else>其他</span>
  389. </template>
  390. </el-table-column>
  391. <el-table-column prop="rechargeTime" label="充值时间" min-width="200px">
  392. <template #default="scope">
  393. {{ moment(scope.row.rechargeTime).format('YYYY-MM-DD HH:mm:ss') }}
  394. </template>
  395. </el-table-column>
  396. </el-table>
  397. </div>
  398. <!-- 分页 -->
  399. <div class="pagination" style="margin-top: 20px">
  400. <el-pagination background :page-size="getObj.pageSize" :page-sizes="[5, 10, 20, 50, 100]"
  401. layout="total, sizes, prev, pager, next, jumper" :total="total" @size-change="handlePageSizeChange"
  402. @current-change="handleCurrentChange"></el-pagination>
  403. </div>
  404. </el-card>
  405. <!-- 导出弹窗 -->
  406. <el-dialog v-model="exportListVisible" title="导出列表" width="80vw" class="custom-height-dialog">
  407. <el-table :data="exportList" style="width:80vw;height: 60vh;" :loading="exportListLoading">
  408. <el-table-column prop="fileName" label="文件名" />
  409. <el-table-column prop="state" label="状态">
  410. <template #default="scope">
  411. <el-tag :type="getTagType(scope.row.state)" :effect="scope.row.state === 3 ? 'light' : 'plain'">
  412. {{ getTagText(scope.row.state) }}
  413. </el-tag>
  414. </template>
  415. </el-table-column>
  416. <el-table-column prop="createTime" label="创建时间">
  417. <template #default="scope">
  418. {{ moment(scope.row.createTime).format('YYYY-MM-DD HH:mm:ss') }}
  419. </template>
  420. </el-table-column>
  421. <el-table-column label="操作">
  422. <template #default="scope">
  423. <el-button type="primary" size="small" @click="downloadExportFile(scope.row)"
  424. :disabled="scope.row.state !== 2">
  425. 下载
  426. </el-button>
  427. </template>
  428. </el-table-column>
  429. </el-table>
  430. <template #footer>
  431. <div class="dialog-footer">
  432. <el-button text @click="exportListVisible = false">关闭</el-button>
  433. </div>
  434. </template>
  435. </el-dialog>
  436. </template>
  437. <style scoped lang="scss">
  438. // 搜索的卡片样式
  439. .card1 {
  440. background: #F3FAFE;
  441. }
  442. // 表单的卡片样式
  443. .card2 {
  444. background: #E7F4FD;
  445. }
  446. // 新币总数等等
  447. .goldStatistics {
  448. margin-left: 1vw;
  449. margin-bottom: 1vh;
  450. color: #000000;
  451. font-family: "PingFang SC";
  452. font-size: 16px;
  453. font-style: normal;
  454. font-weight: 700;
  455. line-height: 20px;
  456. }
  457. // 表头背景等
  458. :deep(.el-table__header-wrapper),
  459. :deep(.el-table__body-wrapper),
  460. :deep(.el-table__cell),
  461. /* 表格 */
  462. :deep(.el-table__body td) {
  463. background-color: #F3FAFE !important;
  464. }
  465. /* 表头 */
  466. :deep(.el-table__header th) {
  467. background-color: #F3FAFE !important;
  468. }
  469. /* 鼠标悬停 */
  470. :deep(.el-table__row:hover > .el-table__cell) {
  471. background-color: #E5EBFE !important;
  472. }
  473. </style>