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.

588 lines
17 KiB

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