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.

714 lines
19 KiB

  1. <script setup>
  2. import {computed, onMounted, ref} from 'vue'
  3. import {dayjs, ElMessage} from 'element-plus'
  4. import request from '@/util/http'
  5. // 之后整理一下
  6. /*
  7. ====================工具方法==============================
  8. */
  9. // 时间格式化
  10. const formatTime = (val) => val ? dayjs(val).format('YYYY-MM-DD HH:mm:ss') : ''
  11. /*
  12. ====================数据=================================
  13. */
  14. //这是获取用户信息的接口
  15. const adminData = ref({})
  16. // 充值明细表格
  17. const tableData = ref([])
  18. // 搜索consumeUser 表单
  19. const consumeUser = ref({
  20. jwcode: null,
  21. payPlatform: "",
  22. market: "",
  23. startTime: '',
  24. endTime: '',
  25. goodsName: '',
  26. })
  27. // 搜索对象
  28. const getObj = ref({
  29. pageNum: 1,
  30. pageSize: 50
  31. })
  32. //分页总条目
  33. const total = ref(100)
  34. // 搜索对象时间
  35. const getTime = ref({
  36. startTime: '',
  37. endTime: ''
  38. })
  39. // 搜索活动列表
  40. const activity = ref([])
  41. // 搜索地区列表
  42. const market = ref([])
  43. // 新增排序字段和排序方式
  44. const sortField = ref('')
  45. const sortOrder = ref('')
  46. // 消费平台选项
  47. const consumePlatform = [
  48. {
  49. value: '金币系统',
  50. label: '金币系统'
  51. },
  52. {
  53. value: 'Homily Chart',
  54. label: 'Homily Chart'
  55. },
  56. {
  57. value: 'Homily Link',
  58. label: 'Homily Link'
  59. },
  60. {
  61. value: 'ERP系统',
  62. label: 'ERP系统'
  63. }
  64. ]
  65. // 合计数的显示数据
  66. const tableDataTotal = ref({})
  67. const permanentGold = ref(0)
  68. const freeGold = ref(0)
  69. const taskGold = ref(0)
  70. const totalGold = ref(0)
  71. // 定义响应式变量存储金币合计数
  72. const permanentGolds = ref(0)
  73. const freeGolds = ref(0)
  74. const taskGolds = ref(0)
  75. // 查询商品的接口的表单
  76. const goods = ref([])
  77. const totalGoldSearch = ref({
  78. payPlatform: "",
  79. market: "",
  80. startTime: "",
  81. endTime: "",
  82. goodsName: ""
  83. })
  84. /*
  85. ====================方法=================================
  86. */
  87. // 获取登录用户信息
  88. const getAdminData = async function () {
  89. try {
  90. const result = await request({
  91. url: '/admin/userinfo',
  92. data: {}
  93. })
  94. adminData.value = result
  95. console.log('请求成功', result)
  96. console.log('用户信息', adminData.value)
  97. } catch (error) {
  98. console.log('请求失败', error)
  99. }
  100. }
  101. const ConsumeSelectBy = async function (val) {
  102. try {
  103. // 搜索参数页码赋值
  104. if (typeof val === 'number') {
  105. getObj.value.pageNum = val
  106. }
  107. // 搜索参数时间赋值
  108. if (getTime.value != null) {
  109. if (getTime.value.startTime != '' && getTime.value.endTime != '') {
  110. consumeUser.value.startTime = formatTime(getTime.value[0])
  111. consumeUser.value.endTime = formatTime(getTime.value[1])
  112. }
  113. } else {
  114. consumeUser.value.startTime = ''
  115. consumeUser.value.endTime = ''
  116. }
  117. consumeUser.value.sortField = sortField.value
  118. consumeUser.value.sortOrder = sortOrder.value
  119. console.log('搜索参数_时间', consumeUser.value.startTime)
  120. console.log('搜索参数1', getObj.value)
  121. console.log('搜索参数2', consumeUser.value)
  122. // 发送POST请求
  123. const result = await request({
  124. url: '/consume/selectBy',
  125. data: {
  126. pageNum: getObj.value.pageNum,
  127. pageSize: getObj.value.pageSize,
  128. consumeUser: {
  129. ...consumeUser.value,
  130. sortField: sortField.value,
  131. sortOrder: sortOrder.value
  132. }
  133. }
  134. })
  135. console.log('请求成功2', sortField)
  136. // 合计数的接口
  137. // 复制一份 detail.value 并移除排序字段和排序方式
  138. const detailWithoutSort = {...consumeUser.value}
  139. delete detailWithoutSort.sortField
  140. delete detailWithoutSort.sortOrder
  141. // 赋值
  142. totalGoldSearch.value.startTime = consumeUser.value.startTime
  143. totalGoldSearch.value.endTime = consumeUser.value.endTime
  144. totalGoldSearch.value.payPlatform = consumeUser.value.payPlatform
  145. totalGoldSearch.value.market = consumeUser.value.market
  146. totalGoldSearch.value.goodsName = consumeUser.value.goodsName
  147. //
  148. const resultTotalGold = await request({
  149. // url: '/consume/statsGold',
  150. url: '/consume/statsGold',
  151. data: totalGoldSearch.value
  152. })
  153. console.log("总计", resultTotalGold)
  154. if (resultTotalGold.code === 200 && resultTotalGold.data) {
  155. const data = resultTotalGold.data
  156. console.log('获取到的金币数据:', data)
  157. permanentGolds.value = Number(data.permanentGolds) || 0
  158. freeGolds.value = Number(data.freeGolds) || 0
  159. taskGolds.value = Number(data.taskGolds) || 0
  160. }
  161. // 存储表格数据
  162. tableData.value = result.data.list
  163. tableDataTotal.value = resultTotalGold.data
  164. if (resultTotalGold.data == null) {
  165. console.log('请求成功2', resultTotalGold)
  166. // 这是啥东西啊
  167. tableDataTotal.value = resultTotalGold.data
  168. }
  169. const sumGoldList = tableData.value.map(item => item.sumGold);
  170. console.log("sumGold", sumGoldList); // 输出包含所有 sumGold 值的数组
  171. console.log('@@@@@@@@@@tableDataT', tableDataTotal.value.list)
  172. // totalGold.value = tableData.value.sum
  173. // // 修改为保留两位小数
  174. // permanentGold.value = parseFloat(
  175. // (tableDataTotal.value.list.sumGold / 100).toFixed(2)
  176. // )
  177. // freeGold.value = parseFloat(
  178. // (tableDataTotal.value.sumFcion / 100).toFixed(2)
  179. // )
  180. // taskGold.value = parseFloat(
  181. // (tableDataTotal.value.sumTcion / 100).toFixed(2)
  182. // )
  183. // totalGold.value = parseFloat(
  184. // (tableDataTotal.value.sumcion / 100).toFixed(2)
  185. // )
  186. console.log('tableData', tableData.value)
  187. // 存储分页总数
  188. total.value = result.data.total
  189. console.log('total', total.value)
  190. } catch (error) {
  191. console.log('请求失败', error)
  192. // 在这里可以处理错误逻辑,比如显示错误提示等
  193. }
  194. }
  195. // 搜索
  196. const search = function () {
  197. getObj.value.pageNum = 1
  198. ConsumeSelectBy()
  199. }
  200. // 重置
  201. const reset = function () {
  202. console.log('兄弟,你点了重置')
  203. consumeUser.value.goodsName = ''
  204. consumeUser.value.market = ''
  205. consumeUser.value.payPlatform = ''
  206. consumeUser.value.startTime = ''
  207. consumeUser.value.endTime = ''
  208. sortField.value = ''
  209. sortOrder.value = ''
  210. getTime.value = {}
  211. // 点完重置后,重新请求数据
  212. ConsumeSelectBy()
  213. console.log('consumeUser', consumeUser.value)
  214. }
  215. // 今天
  216. const getToday = function () {
  217. const today = new Date()
  218. const startTime = new Date(
  219. today.getFullYear(),
  220. today.getMonth(),
  221. today.getDate()
  222. )
  223. const endTime = new Date(
  224. today.getFullYear(),
  225. today.getMonth(),
  226. today.getDate() + 1
  227. )
  228. getTime.value = [startTime, endTime]
  229. console.log('getTime', getTime.value)
  230. ConsumeSelectBy()
  231. }
  232. // 昨天
  233. const getYesterday = function () {
  234. const yesterday = new Date()
  235. yesterday.setDate(yesterday.getDate() - 1)
  236. const startTime = new Date(
  237. yesterday.getFullYear(),
  238. yesterday.getMonth(),
  239. yesterday.getDate()
  240. )
  241. const endTime = new Date(
  242. yesterday.getFullYear(),
  243. yesterday.getMonth(),
  244. yesterday.getDate() + 1
  245. )
  246. getTime.value = [startTime, endTime]
  247. console.log('getTime', getTime.value)
  248. ConsumeSelectBy()
  249. }
  250. // 近7天
  251. const get7Days = function () {
  252. const today = new Date()
  253. const startTime = new Date(
  254. today.getFullYear(),
  255. today.getMonth(),
  256. today.getDate() - 6
  257. )
  258. const endTime = new Date(
  259. today.getFullYear(),
  260. today.getMonth(),
  261. today.getDate() + 1
  262. )
  263. getTime.value = [startTime, endTime]
  264. console.log('getTime', getTime.value)
  265. ConsumeSelectBy()
  266. }
  267. // 获取商品列表
  268. const getGoods = async function () {
  269. try {
  270. // 发送POST请求
  271. const result = await request({
  272. url: '/general/goods',
  273. data: {}
  274. })
  275. // 将响应结果存储到响应式数据中
  276. console.log('请求成功product', result)
  277. // 存储全部数据
  278. goods.value = result.data
  279. console.log('goods 数据', goods.value) // 修改日志输出
  280. } catch (error) {
  281. console.log('请求失败', error)
  282. // 在这里可以处理错误逻辑,比如显示错误提示等
  283. }
  284. }
  285. // 获取地区列表的方法
  286. const getMarket = async function () {
  287. try {
  288. // 发送请求获取地区列表
  289. const result = await request({
  290. // url: '/general/market',
  291. url: '/general/market', // todo 换成实际接口地址
  292. data: {}
  293. })
  294. console.log('请求地区列表成功', result)
  295. // 存储地区数据
  296. market.value = result.data
  297. console.log('地区数据', market.value)
  298. } catch (error) {
  299. console.log('请求地区列表失败', error)
  300. ElMessage({
  301. type: 'error',
  302. message: '获取地区列表失败,请稍后重试'
  303. })
  304. }
  305. }
  306. // 处理排序事件
  307. const handleSortChange = (column) => {
  308. console.log('排序字段:', column.prop)
  309. console.log('排序方式:', column.order)
  310. if (column.prop === 'permanentGold') {
  311. sortField.value = 'permanentGold'
  312. } else if (column.prop === 'taskGold') {
  313. sortField.value = 'taskGold'
  314. } else if (column.prop === 'freeGold') {
  315. sortField.value = 'freeGold'
  316. } else if (column.prop === 'createTime') {
  317. sortField.value = 'createTime'
  318. }
  319. sortOrder.value = column.order === 'ascending' ? 'DESC' : 'ASC'
  320. ConsumeSelectBy()
  321. }
  322. const handlePageSizeChange = function (val) {
  323. getObj.value.pageSize = val
  324. ConsumeSelectBy()
  325. }
  326. const handleCurrentChange = function (val) {
  327. getObj.value.pageNum = val
  328. ConsumeSelectBy()
  329. }
  330. // 验证跳转输入框的数字是否合法
  331. const checkNumber = function () {
  332. if (typeof parseInt(getObj.value.pageNum) === 'number') {
  333. console.log('总共有多少页' + Math.ceil(total.value / getObj.value.pageSize))
  334. if (
  335. getObj.value.pageNum > 0 &&
  336. getObj.value.pageNum <= Math.ceil(total.value / getObj.value.pageSize)
  337. ) {
  338. getObj.value.pageNum = parseInt(getObj.value.pageNum)
  339. console.log('输入的数字合法')
  340. ConsumeSelectBy()
  341. } else {
  342. //提示
  343. ElMessage({
  344. type: 'error',
  345. message: '请检查输入内容'
  346. })
  347. }
  348. } else {
  349. //提示
  350. ElMessage({
  351. type: 'error',
  352. message: '请检查输入内容'
  353. })
  354. }
  355. }
  356. /*
  357. ====================计算属性=================================
  358. */
  359. // 计算总金币数
  360. const sumGold = computed(() => permanentGolds.value + freeGolds.value + taskGolds.value)
  361. /*
  362. ====================监听=================================
  363. */
  364. /*
  365. ====================挂载=================================
  366. */
  367. onMounted(async function () {
  368. await getAdminData()
  369. await ConsumeSelectBy()
  370. // getActivity();
  371. await getMarket()
  372. await getGoods()
  373. })
  374. </script>
  375. <template>
  376. <el-row>
  377. <el-col>
  378. <el-card style="margin-bottom: 20px;margin-top:10px">
  379. <el-row style="margin-bottom: 10px">
  380. <el-col :span="6">
  381. <div class="head-card-element">
  382. <el-text class="mx-1" size="large">商品名称</el-text>
  383. <el-select
  384. v-model="consumeUser.goodsName"
  385. placeholder="请选择商品名称"
  386. size="large"
  387. style="width: 180px"
  388. clearable
  389. >
  390. <!-- 修改 v-for 绑定逻辑 -->
  391. <el-option
  392. v-for="(item, index) in goods"
  393. :key="index"
  394. :label="item"
  395. :value="item"
  396. />
  397. </el-select>
  398. </div>
  399. </el-col>
  400. <el-col :span="6">
  401. <div class="head-card-element">
  402. <el-text class="mx-1" size="large">所属地区</el-text>
  403. <el-select
  404. v-model="consumeUser.market"
  405. placeholder="请选择所属地区"
  406. size="large"
  407. style="width: 180px"
  408. clearable
  409. >
  410. <el-option
  411. v-for="(item, index) in market"
  412. :key="index"
  413. :label="item"
  414. :value="item"
  415. />
  416. </el-select>
  417. </div>
  418. </el-col>
  419. <el-col :span="6">
  420. <div class="head-card-element">
  421. <el-text class="mx-1" size="large">消耗平台</el-text>
  422. <el-select
  423. v-model="consumeUser.payPlatform"
  424. placeholder="请选择消耗平台"
  425. size="large"
  426. style="width: 180px"
  427. clearable
  428. >
  429. <el-option
  430. v-for="item in consumePlatform"
  431. :key="item.value"
  432. :label="item.label"
  433. :value="item.value"
  434. />
  435. </el-select>
  436. </div>
  437. </el-col>
  438. <!-- <el-col :span="8">
  439. <div class="head-card-element">
  440. <el-text class="mx-1" size="large">消费类型</el-text>
  441. <el-select
  442. v-model="consumeUser.consumeType"
  443. placeholder="请选择消费类型"
  444. size="large"
  445. style="width: 240px"
  446. clearable
  447. >
  448. <el-option
  449. v-for="item in consumeType"
  450. :key="item"
  451. :label="item.label"
  452. :value="item.value"
  453. />
  454. </el-select>
  455. </div>
  456. </el-col> -->
  457. </el-row>
  458. <el-row>
  459. <el-col :span="21">
  460. <div class="head-card-element">
  461. <el-text class="mx-1" size="large">消费时间</el-text>
  462. <el-date-picker
  463. v-model="getTime"
  464. type="datetimerange"
  465. range-separator="至"
  466. start-placeholder="起始时间"
  467. end-placeholder="结束时间"
  468. />
  469. <el-button style="margin-left: 10px" @click="getToday()"
  470. >
  471. </el-button
  472. >
  473. <el-button @click="getYesterday()"></el-button>
  474. <el-button @click="get7Days()">近7天</el-button>
  475. <!-- </div>
  476. </el-col>
  477. <el-col :span="3">
  478. <div class="head-card-btn"> -->
  479. <el-button type="success" @click="reset()">重置</el-button>
  480. <el-button type="primary" @click="search()">查询</el-button>
  481. <el-button type="primary" @click="exportExcel()">导出excel</el-button>
  482. </div>
  483. </el-col>
  484. </el-row>
  485. </el-card>
  486. </el-col>
  487. </el-row>
  488. <el-row>
  489. <el-col>
  490. <el-card>
  491. <div>
  492. 消耗金额{{ Math.abs(sumGold) / 100 }}新币永久金币{{ Math.abs(permanentGolds) / 100 }}免费金币{{
  493. Math.abs(freeGolds) / 100
  494. }}任务金币{{ Math.abs(taskGolds) / 100 }}
  495. </div>
  496. <!-- 设置表格容器的高度和滚动样式 -->
  497. <div style="height: 576px; overflow-y: auto">
  498. <el-table
  499. :data="tableData"
  500. style="width: 100%"
  501. height="576px"
  502. @sort-change="handleSortChange"
  503. >
  504. <el-table-column
  505. type="index"
  506. label="序号"
  507. width="100px"
  508. fixed="left"
  509. >
  510. <template #default="scope">
  511. <span>{{
  512. scope.$index + 1 + (getObj.pageNum - 1) * getObj.pageSize
  513. }}</span>
  514. </template>
  515. </el-table-column>
  516. <!-- 固定姓名列 -->
  517. <el-table-column
  518. prop="name"
  519. label="姓名"
  520. width="150px"
  521. fixed="left"
  522. />
  523. <!-- 固定精网号列 -->
  524. <el-table-column
  525. prop="jwcode"
  526. label="精网号"
  527. width="110px"
  528. fixed="left"
  529. />
  530. <el-table-column prop="market" label="所属地区" width="110px"/>
  531. <el-table-column prop="goodsName" label="商品" width="160px" show-overflow-tooltip/>
  532. <el-table-column
  533. prop="payPlatform"
  534. label="消费平台"
  535. width="120px"
  536. >
  537. <template #default="scope">
  538. <!-- 使用非严格相等比较 -->
  539. {{ scope.row.payPlatform }}
  540. <!-- <span scope.row.consumePlatform == 1">Homily Chart</span>-->
  541. </template>
  542. </el-table-column>
  543. <!-- <el-table-column
  544. prop="consumeType"
  545. label="消费类型"
  546. width="120px"
  547. /> -->
  548. <el-table-column
  549. prop="sumGold"
  550. label="消费金币总数"
  551. width="120px"
  552. >
  553. <template #default="scope">
  554. {{
  555. (scope.row.taskGold +
  556. scope.row.freeGold +
  557. scope.row.permanentGold) / 100
  558. }}
  559. </template>
  560. </el-table-column>
  561. <el-table-column
  562. prop="permanentGold"
  563. label="永久金币"
  564. sortable="“custom”"
  565. width="110px"
  566. >
  567. <template #default="scope">
  568. {{ scope.row.permanentGold / 100 }}
  569. </template>
  570. </el-table-column>
  571. <el-table-column
  572. prop="freeGold"
  573. label="免费金币"
  574. sortable="“custom”"
  575. width="110px"
  576. >
  577. <template #default="scope">
  578. {{ scope.row.freeGold / 100 }}
  579. </template>
  580. </el-table-column>
  581. <el-table-column
  582. prop="taskGold"
  583. label="任务金币"
  584. sortable="“custom”"
  585. width="110px"
  586. >
  587. <template #default="scope">
  588. {{ scope.row.taskGold / 100 }}
  589. </template>
  590. </el-table-column>
  591. <el-table-column
  592. prop="remark"
  593. label="备注"
  594. width="200px"
  595. show-overflow-tooltip
  596. />
  597. <el-table-column prop="adminName" label="提交人" width="110px"/>
  598. <el-table-column
  599. prop="createTime"
  600. label="消费时间"
  601. sortable="“custom”"
  602. width="180px"
  603. />
  604. </el-table>
  605. </div>
  606. <!-- 分页 -->
  607. <div class="pagination">
  608. <el-pagination
  609. background
  610. :page-size="getObj.pageSize"
  611. :page-sizes="[5, 10, 20, 50, 100]"
  612. layout="total, sizes, prev, pager, next, jumper"
  613. :total="total"
  614. @size-change="handlePageSizeChange"
  615. @current-change="handleCurrentChange"
  616. ></el-pagination>
  617. </div>
  618. </el-card>
  619. </el-col>
  620. </el-row>
  621. </template>
  622. <style scoped>
  623. .status {
  624. display: flex;
  625. }
  626. .head-card {
  627. display: flex;
  628. }
  629. .head-card-element {
  630. margin-right: 20px;
  631. }
  632. .head-card-btn {
  633. margin-left: auto;
  634. }
  635. .pagination {
  636. display: flex;
  637. margin-top: 20px;
  638. }
  639. </style>