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
15 KiB

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