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.

488 lines
17 KiB

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