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.

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