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.

433 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. getObj.value.pageNum = 1
  135. get()
  136. getTotalBeans()
  137. }
  138. //获取表格数据
  139. const get = async () => {
  140. try {
  141. if (getTime.value != null) {
  142. selectData.value.startTime = formatTime(getTime.value[0])
  143. selectData.value.endTime = formatTime(getTime.value[1])
  144. } else {
  145. selectData.value.startTime = ''
  146. selectData.value.endTime = ''
  147. }
  148. const data = {
  149. ...getObj.value,
  150. "beanSystemRechargeInfo": {
  151. ...selectData.value,
  152. sortField: sortField.value,
  153. sortOrder: sortOrder.value,
  154. },
  155. }
  156. console.log('请求参数:', data);
  157. const result = await API({
  158. url: '/beanRecharge/selectBySystem',
  159. data: data
  160. })
  161. if (result.code == 200) {
  162. tableData.value = result.data.list
  163. total.value = result.data.total
  164. } else {
  165. ElMessage.error(result.message)
  166. }
  167. } catch (error) {
  168. console.log('搜索失败', error);
  169. }
  170. }
  171. //排序字段
  172. //处理表格排序事件
  173. const sortField = ref('')
  174. const sortOrder = ref('')
  175. const handleSortChange = (column) => {
  176. console.log('排序字段:', column.prop)
  177. console.log('排序方式:', column.order)
  178. // 直接使用允许的排序字段列表进行过滤
  179. const allowedFields = ['money', 'freeBean', 'rechargeTime', 'createTime', 'permanentBean'];
  180. if (allowedFields.includes(column.prop)) {
  181. sortField.value = column.prop;
  182. }
  183. sortOrder.value = column.order === 'ascending' ? 'ASC' : 'DESC';
  184. console.log('传递给后端的排序字段:', sortField.value)
  185. console.log('传递给后端的排序方式:', sortOrder.value)
  186. get();
  187. }
  188. //========================分页===========================
  189. // 搜索对象
  190. const total = ref(0)
  191. const getObj = ref({
  192. pageNum: 1,
  193. pageSize: 20
  194. })
  195. const handlePageSizeChange = (value) => {
  196. getObj.value.pageSize = value
  197. get()
  198. }
  199. const handleCurrentChange = (value) => {
  200. getObj.value.pageNum = value
  201. get()
  202. }
  203. //==========================导出=======================
  204. const exportExcel = async () => {
  205. const params = {
  206. ...getObj.value,
  207. "beanSystemRechargeInfo": {
  208. ...selectData.value,
  209. sortField: sortField.value,
  210. sortOrder: sortOrder.value,
  211. },
  212. }
  213. try {
  214. const res = await API({ url: '/export/exportBean', data: params })
  215. console.log('系统充值导出的参数为:', params);
  216. if (res.code === 200) {
  217. ElMessage.success('导出成功')
  218. } else {
  219. ElMessage.error(res.message || '导出失败,请稍后重试')
  220. }
  221. } catch (error) {
  222. console.log('请求失败', error)
  223. ElMessage.error('导出失败,请稍后重试')
  224. }
  225. }
  226. const exportListVisible = ref(false)
  227. // 打开导出列表弹窗
  228. const openExportList = () => {
  229. getExportList()
  230. exportListVisible.value = true
  231. }
  232. // 导出列表数据
  233. const exportList = ref([])
  234. // 导出列表加载状态
  235. const exportListLoading = ref(false)
  236. // 获取导出列表
  237. const getExportList = async () => {
  238. exportListLoading.value = true
  239. try {
  240. const result = await API({ url: '/export/export' })
  241. if (result.code === 200) {
  242. const filteredData = result.data.filter(item => {
  243. return item.type === 9;
  244. });
  245. exportList.value = filteredData
  246. } else {
  247. ElMessage.error(result.msg || '获取导出列表失败')
  248. }
  249. } catch (error) {
  250. console.error('获取导出列表出错:', error)
  251. ElMessage.error('获取导出列表失败,请稍后重试')
  252. } finally {
  253. exportListLoading.value = false
  254. }
  255. }
  256. // 下载导出文件
  257. const downloadExportFile = (item) => {
  258. if (item.state === 2) {
  259. const link = document.createElement('a')
  260. link.href = item.url
  261. link.download = item.fileName
  262. link.click()
  263. } else {
  264. ElMessage.warning('文件还在导出中,请稍后再试')
  265. }
  266. }
  267. //根据状态返回对应的标签类型
  268. const getTagType = (state) => {
  269. switch (state) {
  270. case 0:
  271. return 'info';
  272. case 1:
  273. return 'primary';
  274. case 2:
  275. return 'success';
  276. case 3:
  277. return 'danger';
  278. default:
  279. return 'info';
  280. }
  281. }
  282. //根据状态返回对应的标签文案
  283. const getTagText = (state) => {
  284. switch (state) {
  285. case 0:
  286. return '待执行';
  287. case 1:
  288. return '执行中';
  289. case 2:
  290. return '执行完成';
  291. case 3:
  292. return '执行出错';
  293. default:
  294. return '未知状态';
  295. }
  296. }
  297. onMounted(async function () {
  298. await get()
  299. await getArea()
  300. await getTotalBeans()
  301. })
  302. </script>
  303. <template>
  304. <el-row>
  305. <el-col>
  306. <el-card style="margin-bottom: 20px;margin-top: 10px">
  307. <el-row style="margin-bottom: 10px">
  308. <el-col :span="3">
  309. <div class="head-card-element">
  310. <el-text class="mx-1" size="large">精网号</el-text>
  311. <el-input v-model="selectData.jwcode" placeholder="请输入精网号" style="width: 115px" clearable />
  312. </div>
  313. </el-col>
  314. <el-col :span="4">
  315. <div class="head-card-element">
  316. <el-text class="mx-1" size="large">所属地区</el-text>
  317. <el-select v-model="selectData.market" placeholder="请选择所属地区" clearable style="width:150px">
  318. <el-option v-for="item in market" :key="item" :label="item" :value="item" />
  319. </el-select>
  320. </div>
  321. </el-col>
  322. <el-col :span="17">
  323. <div class="head-card-element">
  324. <el-text class="mx-1" size="large">充值时间</el-text>
  325. <el-date-picker v-model="getTime" type="datetimerange" range-separator=""
  326. start-placeholder="起始时间" end-placeholder="结束时间" style="width: 350px"
  327. @change="handleDatePickerChange" :default-time="defaultTime"/>
  328. <el-button @click="getToday()" style="margin-left: 10px"
  329. :type="activeTimeRange === 'today' ? 'primary' : ''">
  330. </el-button>
  331. <el-button @click="getYesterday()" style="margin-left: 10px"
  332. :type="activeTimeRange === 'yesterday' ? 'primary' : ''">
  333. </el-button>
  334. <el-button @click="get7Days()" style="margin-left: 10px"
  335. :type="activeTimeRange === '7days' ? 'primary' : ''"> 近7天
  336. </el-button>
  337. <el-button type="success" @click="reset()">重置</el-button>
  338. <el-button type="primary" @click="search()">查询</el-button>
  339. <el-button type="primary" style="width: 80px;" @click="exportExcel()">导出Excel</el-button>
  340. <el-button type="primary" style="width: 95px;" @click="openExportList">查看导出列表</el-button>
  341. </div>
  342. </el-col>
  343. </el-row>
  344. <el-row>
  345. </el-row>
  346. </el-card>
  347. </el-col>
  348. </el-row>
  349. <el-row>
  350. <el-col>
  351. <el-card>
  352. <div class="bean-info">
  353. <!-- 汉字用 <strong> 加粗动态数据用 <span> 包一层单独改色 -->
  354. 金豆总数{{ beanNum }}
  355. , 充值金豆数{{ permanentBeans }}
  356. , 免费金豆数{{ freeBean }}
  357. </div>
  358. <!-- 设置表格容器的高度和滚动样式 -->
  359. <div style="height: 520px; overflow-y: auto;margin-top: 10px;">
  360. <el-table :data="tableData" style="width: 100%" height="520px" @sort-change="handleSortChange">
  361. <el-table-column type="id" prop="id" label="ID" min-width="80px" fixed="left"></el-table-column>
  362. <el-table-column fixed="left" prop="name" label="姓名" min-width="100" />
  363. <el-table-column fixed="left" prop="jwcode" label="精网号" min-width="110px" />
  364. <el-table-column prop="market" label="所属地区" min-width="100px" />
  365. <el-table-column prop="permanentBean" label="永久金豆" sortable="custom" min-width="110px" />
  366. <el-table-column prop="freeBean" label="免费金豆" sortable="custom" min-width="110px" />
  367. <el-table-column prop="remark" label="备注" min-width="150px" show-overflow-tooltip />
  368. <el-table-column prop="rechargeTime" label="充值时间" min-width="200px">
  369. <template #default="scope">
  370. {{ moment(scope.row.rechargeTime).format('YYYY-MM-DD HH:mm:ss') }}
  371. </template>
  372. </el-table-column>
  373. </el-table>
  374. </div>
  375. <!-- 分页 -->
  376. <div class="pagination" style="margin-top: 20px">
  377. <el-pagination background :page-size="getObj.pageSize" :page-sizes="[5, 10, 20, 50, 100]"
  378. layout="total, sizes, prev, pager, next, jumper" :total="total"
  379. @size-change="handlePageSizeChange" @current-change="handleCurrentChange"></el-pagination>
  380. </div>
  381. </el-card>
  382. </el-col>
  383. </el-row>
  384. <!-- 导出弹窗 -->
  385. <el-dialog v-model="exportListVisible" title="导出列表" width="80%">
  386. <el-table :data="exportList" style="width: 100% ;height: 60vh;" :loading="exportListLoading">
  387. <el-table-column prop="fileName" label="文件名" />
  388. <el-table-column prop="state" label="状态">
  389. <template #default="scope">
  390. <el-tag :type="getTagType(scope.row.state)" :effect="scope.row.state === 3 ? 'light' : 'plain'">
  391. {{ getTagText(scope.row.state) }}
  392. </el-tag>
  393. </template>
  394. </el-table-column>
  395. <el-table-column prop="createTime" label="创建时间">
  396. <template #default="scope">
  397. {{ moment(scope.row.createTime).format('YYYY-MM-DD HH:mm:ss') }}
  398. </template>
  399. </el-table-column>
  400. <el-table-column label="操作">
  401. <template #default="scope">
  402. <el-button type="primary" size="small" @click="downloadExportFile(scope.row)"
  403. :disabled="scope.row.state !== 2">
  404. 下载
  405. </el-button>
  406. </template>
  407. </el-table-column>
  408. </el-table>
  409. <template #footer>
  410. <div class="dialog-footer">
  411. <el-button text @click="exportListVisible = false">关闭</el-button>
  412. </div>
  413. </template>
  414. </el-dialog>
  415. </template>
  416. <style scoped></style>