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.

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