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.

528 lines
16 KiB

4 days ago
4 days ago
4 days ago
4 days ago
4 days ago
4 days ago
4 days ago
3 weeks ago
3 weeks ago
4 days ago
4 days ago
4 days ago
3 weeks ago
4 days ago
4 days ago
4 days ago
4 days ago
4 days ago
3 weeks ago
3 weeks ago
4 days ago
4 days ago
3 weeks ago
4 days ago
3 weeks ago
4 days ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
4 days ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
4 days ago
3 weeks ago
3 weeks ago
3 weeks ago
  1. <template>
  2. <el-row>
  3. <el-col>
  4. <div>
  5. <el-card style="margin-bottom: 5px">
  6. <el-row style="margin-bottom: 5px">
  7. <el-col :span="6">
  8. <el-text size="large">精网号</el-text>
  9. <el-input v-model="searchForm.jwcode" placeholder="请输入精网号" style="width: 240px" clearable />
  10. </el-col>
  11. <el-col :span="6">
  12. <el-text size="large">商品名</el-text>
  13. <el-select v-model="searchForm.goodsName" placeholder="请输入商品名" style="width: 240px" clearable>
  14. <el-option v-for="item in refundGoodsOptions" :key="item" :label="item" :value="item"> </el-option>
  15. </el-select>
  16. </el-col>
  17. <el-col :span="6">
  18. <el-text size="large">退款方式</el-text>
  19. <el-select v-model="searchForm.refundModel" placeholder="请选择" style="width: 240px" clearable>
  20. <el-option label="全部退款" value="0" />
  21. <el-option label="部分退款" value="1" />
  22. </el-select>
  23. </el-col>
  24. <el-col :span="6">
  25. <el-text size="large">所属地区</el-text>
  26. <el-select v-model="searchForm.market" placeholder="请选择" style="width: 240px" clearable>
  27. <el-option v-for="item in marketOptions" :key="item" :label="item" :value="item" />
  28. </el-select>
  29. </el-col>
  30. </el-row>
  31. <el-row>
  32. <el-col :span="12">
  33. <div class="time-controls">
  34. <div class="time-group">
  35. <el-text size="large">提交时间</el-text>
  36. <el-date-picker v-model="dateRange" type="datetimerange" range-separator="" start-placeholder="开始时间"
  37. end-placeholder="结束时间" style="width: 400px" />
  38. <el-button @click="getToday()" style="margin-left: 10px"></el-button>
  39. <el-button @click="getYesterday()" style="margin-left: 10px"></el-button>
  40. <el-button @click="get7Days()" style="margin-left: 10px">近7天</el-button>
  41. </div>
  42. </div>
  43. </el-col>
  44. <el-col :span="6">
  45. <el-button type="success" @click="resetSearch">重置</el-button>
  46. <el-button type="primary" @click="handleSearch">查询</el-button>
  47. </el-col>
  48. </el-row>
  49. </el-card>
  50. </div>
  51. </el-col>
  52. </el-row>
  53. <el-card>
  54. <el-tabs v-model="activeName" type="card" @tab-click="handleClick">
  55. <el-tab-pane label="待审核" name="wait"></el-tab-pane>
  56. <el-tab-pane label="已通过" name="pass"></el-tab-pane>
  57. <el-tab-pane label="已驳回" name="reject"></el-tab-pane>
  58. </el-tabs>
  59. <div>
  60. 总条数{{ stats.totalNum }}&nbsp;&nbsp;&nbsp;&nbsp;
  61. 退款总金币数{{ (stats.permanentGolds + stats.freeGolds + stats.taskGolds).toFixed(2) }}金币&nbsp;&nbsp;&nbsp;&nbsp;
  62. 永久金币{{ stats.permanentGolds.toFixed(2) }}金币&nbsp;&nbsp;&nbsp;&nbsp;
  63. 免费金币{{ stats.freeGolds.toFixed(2) }}金币&nbsp;&nbsp;&nbsp;&nbsp;
  64. 任务金币{{ stats.taskGolds.toFixed(2) }}金币
  65. </div>
  66. <el-table :data="tableData" height="540px">
  67. <el-table-column type="index" label="序号" width="60" />
  68. <el-table-column prop="name" label="姓名" width="120" />
  69. <el-table-column prop="jwcode" label="精网号" width="120" />
  70. <el-table-column prop="market" label="所属地区" width="120" />
  71. <el-table-column prop="refundType" label="退款类型" width="120" />
  72. <el-table-column prop="refundModel" label="退款方式" width="120">
  73. <template #default="{ row }">
  74. {{ row.refundModel === 0 ? '全部退款' : '部分退款' }}
  75. </template>
  76. </el-table-column>
  77. <el-table-column prop="goodsName" label="退款商品" width="120" show-overflow-tooltip />
  78. <el-table-column prop="sumGold" label="退款金额" width="120" sortable="custom">
  79. <template #default="{ row }">
  80. {{ row.sumGold / 100 }}
  81. </template>
  82. </el-table-column>
  83. <el-table-column prop="permanentGold" label="永久金币" width="120" sortable="custom">
  84. <template #default="{ row }">
  85. {{ row.permanentGold / 100 }}
  86. </template>
  87. </el-table-column>
  88. <el-table-column prop="freeGold" label="免费金币" width="120" sortable="custom">
  89. <template #default="{ row }">
  90. {{ (row.freeJune + row.freeDecember) / 100}}
  91. </template>
  92. </el-table-column>
  93. <el-table-column prop="taskGold" label="任务金币" width="120" sortable="custom">
  94. <template #default="{ row }">
  95. {{ row.taskGold / 100 }}
  96. </template>
  97. </el-table-column>
  98. <el-table-column prop="remark" label="备注" width="150" show-overflow-tooltip /><!-- 当内容过长被隐藏时显示 tooltip -->
  99. <el-table-column prop="adminName" label="提交人" width="120" />
  100. <el-table-column v-if="checkTab === 'rejected'" prop="rejectReason" label="驳回理由" width="150"
  101. show-overflow-tooltip />
  102. <el-table-column v-if="checkTab !== 'pending'" prop="auditName" label="审核人" width="120" />
  103. <el-table-column prop="createTime" label="提交时间" width="180" sortable="custom">
  104. <template #default="{ row }">
  105. {{ moment(row.createTime).format('YYYY-MM-DD HH:mm:ss') }}
  106. </template>
  107. </el-table-column>
  108. <el-table-column v-if="checkTab !== 'pending'" prop="auditTime" label="审核时间" width="180" sortable="custom">
  109. <template #default="{ row }">
  110. {{ row.auditTime ? moment(row.auditTime).format('YYYY-MM-DD HH:mm:ss') : '--' }}
  111. </template>
  112. </el-table-column>
  113. <el-table-column v-if="checkTab === 'pending'" fixed="right" prop="operation" label="操作" width="150px">
  114. <template #default="scope">
  115. <div class="operation">
  116. <el-popconfirm title="确定要通过此条记录吗?" @confirm="handleApprove(scope.row)">
  117. <template #reference>
  118. <el-button :disabled="scope.row.auditStatus === 1 || scope.row.auditStatus === 2" type="primary" text>
  119. 通过
  120. </el-button>
  121. </template>
  122. </el-popconfirm>
  123. <el-button :disabled="scope.row.auditStatus === 1 || scope.row.auditStatus === 2" type="primary" text
  124. @click="showRejectDialog(scope.row)">
  125. 驳回
  126. </el-button>
  127. </div>
  128. </template>
  129. </el-table-column>
  130. </el-table>
  131. <el-pagination class="pagination" v-model:current-page="pagination.pageNum" v-model:page-size="pagination.pageSize"
  132. layout="total, sizes, prev, pager, next, jumper" :total="pagination.total" @size-change="handlePageSizeChange"
  133. @current-change="handleCurrentChange"></el-pagination>
  134. </el-card>
  135. <el-dialog v-model="rejectDialogVisible" title="驳回理由" width="500px">
  136. <el-form>
  137. <el-form-item label="驳回理由">
  138. <el-input v-model="rejectReason" type="textarea" :rows="4" placeholder="请输入驳回理由" maxlength="200"
  139. show-word-limit />
  140. </el-form-item>
  141. </el-form>
  142. <template #footer>
  143. <span class="dialog-footer">
  144. <el-button @click="rejectDialogVisible = false">取消</el-button>
  145. <el-button type="primary" @click="handleReject">确定</el-button>
  146. </span>
  147. </template>
  148. </el-dialog>
  149. </template>
  150. <script setup>
  151. import { onMounted, reactive, ref } from 'vue'
  152. import { ElMessage } from 'element-plus'
  153. import API from '@/util/http'
  154. import moment from 'moment'
  155. const scopeValue = ref(null) // 当前行
  156. const rejectDialogVisible = ref(false) // 驳回对话框显示状态
  157. const rejectReason = ref('') // 驳回理由
  158. // 状态常量
  159. const STATUS = {
  160. PENDING: 0, // 待审核
  161. APPROVED: 1, // 通过
  162. REJECTED: 2 // 驳回
  163. }
  164. // 搜索表单数据
  165. const searchForm = ref({
  166. jwcode: '',
  167. refundModel: '',
  168. goodsName: '',
  169. market: '',
  170. startTime: '',
  171. endTime: '',
  172. auditStatus: '0',
  173. })
  174. const checkTab = ref('pending') // 能否不用STATUS常量,0是待审批,1是已通过,2是驳回,参数status需要Integer
  175. const dateRange = ref([])
  176. const pagination = ref({
  177. pageNum: 1,
  178. pageSize: 50,
  179. total: 0
  180. })
  181. const tableData = ref([])
  182. const marketOptions = ref([])
  183. const refundGoodsOptions = ref([])
  184. const adminInfo = ref({})
  185. // 统计合计数
  186. const stats = ref({
  187. totalNum: 0,
  188. totalCoins: 0,
  189. permanentGolds: 0,
  190. freeGolds: 0,
  191. taskGolds: 0
  192. })
  193. // 驳回弹出框
  194. const rejectVisible = ref(false)
  195. // 驳回对象
  196. const rejectObj = ref({})
  197. // 通过对象
  198. const passObj = ref({})
  199. // 标签页默认是待审批
  200. const activeName = ref('wait')
  201. // 表单验证ref
  202. const Ref = ref(null)
  203. // 新增排序字段和排序方式
  204. const sortField = ref('')
  205. const sortOrder = ref('')
  206. // 表单验证
  207. const rules = reactive({
  208. reason: [{ required: true, message: '请输入驳回理由', trigger: 'blur' }]
  209. })
  210. // 获取用户信息
  211. // const getAdminInfo = async () => {
  212. // try {
  213. // const res = await API({ url: '' })
  214. // adminInfo.value = res
  215. // if (res.market !== '总部') {
  216. // searchForm.value.market = res.market
  217. // }
  218. // } catch (error) {
  219. // console.error('获取用户信息失败', error)
  220. // }
  221. // }
  222. const handlePageSizeChange = function (val) {
  223. pagination.value.pageSize = val
  224. get()
  225. console.log('aaaaaaaaaaaaaaaaaa这是pageSize改变调用')
  226. }
  227. const handleCurrentChange = function (val) {
  228. pagination.value.pageNum = val
  229. get()
  230. console.log('aaaaaaaaaaaaaaa这是pageNum改变调用')
  231. }
  232. // 显示驳回对话框
  233. const showRejectDialog = (row) => {
  234. scopeValue.value = row
  235. rejectReason.value = ''
  236. rejectDialogVisible.value = true
  237. }
  238. // 查地区
  239. const getmarkets = async () => {
  240. try {
  241. const result = await API({ url: 'general/market' })
  242. marketOptions.value = result.data || []
  243. } catch (error) {
  244. console.error('获取地区列表失败', error)
  245. }
  246. }
  247. // 查商品名
  248. const getRefundGoods = async () => {
  249. try {
  250. const res = await API({ url: '/general/goods' })
  251. refundGoodsOptions.value = res.data || []
  252. } catch (error) {
  253. console.error('获取商品列表失败', error)
  254. }
  255. }
  256. // 搜索方法
  257. const get = async function (val) {
  258. try {
  259. if (typeof val === 'number') {
  260. pagination.value.pageNum = val
  261. }
  262. if (dateRange.value && dateRange.value.length === 2) {
  263. searchForm.value.startTime = moment(dateRange.value[0]).format('YYYY-MM-DD HH:mm:ss')
  264. searchForm.value.endTime = moment(dateRange.value[1]).format('YYYY-MM-DD HH:mm:ss')
  265. } else {
  266. searchForm.value.startTime = ''
  267. searchForm.value.endTime = ''
  268. }
  269. const params = {
  270. pageNum: pagination.value.pageNum,
  271. pageSize: pagination.value.pageSize,
  272. refundAudit: {
  273. ...searchForm.value
  274. }
  275. }
  276. console.log('看看传给后端的参数:', params)
  277. const res = await API({ url: '/audit/selectRefund', data: params })
  278. tableData.value = res.list || []
  279. pagination.value.total = res.total || 0
  280. console.log('查全部的total', pagination.value.total,res.total)
  281. } catch (error) {
  282. console.error('获取数据失败', error)
  283. }
  284. }
  285. // 通过
  286. const handleApprove = async (row) => {
  287. try {
  288. const params = {
  289. orderCode: row.orderCode,
  290. auditId: row.auditId,
  291. action: 1,// action的1是通过,2是驳回
  292. rejectReason: ''
  293. }
  294. await API({ url: '/audit/audit', data: params })// 试一下能不能发
  295. ElMessage.success('审核通过成功')
  296. get()
  297. getStats()
  298. console.log('aaaaaaaaaa这是通过调用')
  299. } catch (error) {
  300. console.error('审核通过失败', error)
  301. ElMessage.error('操作失败')
  302. }
  303. }
  304. // 处理驳回操作
  305. const handleReject = async () => {
  306. if (!rejectReason.value.trim()) {
  307. ElMessage.warning('请输入驳回理由')
  308. return
  309. }
  310. try {
  311. const params = {
  312. orderCode: scopeValue.value.orderCode,
  313. auditId: scopeValue.value.auditId,
  314. action: 2,
  315. rejectReason: rejectReason.value
  316. }
  317. await API({ url: '/audit/audit', data: params })
  318. ElMessage.success('驳回成功')
  319. rejectDialogVisible.value = false
  320. get()
  321. getStats()
  322. console.log('aaaaaaaaaa这是驳回调用')
  323. } catch (error) {
  324. console.error('驳回失败', error)
  325. ElMessage.error('操作失败')
  326. }
  327. }
  328. const getStats = async () => {
  329. try {
  330. const params = {
  331. pageNum: pagination.value.pageNum,
  332. pageSize: pagination.value.pageSize,
  333. refundAudit: {
  334. ...searchForm.value
  335. }
  336. }
  337. const res = await API({
  338. url: '/audit/sumRefundGold',
  339. data: params
  340. })
  341. stats.value.totalNum = res.totalNum
  342. stats.value.permanentGolds = res.permanentGolds / 100
  343. stats.value.freeGolds = res.freeGolds / 100
  344. stats.value.taskGolds = res.taskGolds / 100
  345. console.log('see see stats和搜索对象', stats.value,params)
  346. } catch (error) {
  347. console.log('请求失败', error)
  348. }
  349. }
  350. // 搜索
  351. const handleSearch = function () {
  352. // pagination.value.pageNum = 1
  353. get()
  354. getStats()
  355. console.log('aaaaaaaaaa这是搜索按钮调用')
  356. }
  357. // 重置
  358. const resetSearch = function () {
  359. searchForm.value = {
  360. jwcode: '',
  361. refundType: '',
  362. goodsName: '',
  363. market: adminInfo.value.market === '总部' ? '' : adminInfo.value.market,
  364. startTime: '',
  365. endTime: ''
  366. }
  367. dateRange.value = []
  368. }
  369. // 今天
  370. const getToday = function () {
  371. const today = new Date()
  372. const startTime = new Date(
  373. today.getFullYear(),
  374. today.getMonth(),
  375. today.getDate()
  376. )
  377. const endTime = new Date(
  378. today.getFullYear(),
  379. today.getMonth(),
  380. today.getDate() + 1
  381. )
  382. dateRange.value = [startTime, endTime]
  383. console.log('dateRange', dateRange.value)
  384. get()
  385. getStats()
  386. console.log('aaaaaaaaaa这是今天调用')
  387. }
  388. // 昨天
  389. const getYesterday = function () {
  390. const yesterday = new Date()
  391. yesterday.setDate(yesterday.getDate() - 1)
  392. const startTime = new Date(
  393. yesterday.getFullYear(),
  394. yesterday.getMonth(),
  395. yesterday.getDate()
  396. )
  397. const endTime = new Date(
  398. yesterday.getFullYear(),
  399. yesterday.getMonth(),
  400. yesterday.getDate() + 1
  401. )
  402. dateRange.value = [startTime, endTime]
  403. console.log('dateRange', dateRange.value)
  404. get()
  405. getStats()
  406. console.log('aaaaaaaaaa这是昨天调用')
  407. }
  408. // 近7天
  409. const get7Days = function () {
  410. const today = new Date()
  411. const startTime = new Date(
  412. today.getFullYear(),
  413. today.getMonth(),
  414. today.getDate() - 6
  415. )
  416. const endTime = new Date(
  417. today.getFullYear(),
  418. today.getMonth(),
  419. today.getDate() + 1
  420. )
  421. dateRange.value = [startTime, endTime]
  422. console.log('dateRange', dateRange.value)
  423. get()
  424. getStats()
  425. console.log('aaaaaaaaaa这是近七天调用')
  426. }
  427. // 切换标签页
  428. const handleClick = function (tab, event) {
  429. activeName.value = tab.props.name
  430. if (tab.props.name === 'wait') {
  431. adminWait()
  432. } else if (tab.props.name === 'pass') {
  433. adminPass()
  434. } else if (tab.props.name === 'reject') {
  435. adminReject()
  436. }
  437. }
  438. // 当前状态
  439. const getCurrentStatus = () => {
  440. switch (activeName.value) {
  441. case 'wait':
  442. return STATUS.PENDING
  443. case 'pass':
  444. return STATUS.APPROVED
  445. case 'reject':
  446. return STATUS.REJECTED
  447. default:
  448. return ''
  449. }
  450. }
  451. // 待审核充值明细
  452. const adminWait = async function () {
  453. checkTab.value = 'pending'
  454. searchForm.value.auditStatus = STATUS.PENDING
  455. // pagination.value.pageNum = 1
  456. await get()
  457. await getStats()
  458. console.log('aaaaaaaaaaaaaaaaa看看checkTab,这是点击待审核调用', checkTab.value)
  459. }
  460. // 已通过充值明细
  461. const adminPass = async function () {
  462. checkTab.value = 'pass'
  463. searchForm.value.auditStatus = STATUS.APPROVED
  464. // pagination.value.pageNum = 1
  465. await get()
  466. await getStats()
  467. console.log('aaaaaaaaaaaaaaaaaaaaa看看checkTab,这是点击已通过调用', checkTab.value)
  468. }
  469. // 已驳回充值明细
  470. const adminReject = async function () {
  471. checkTab.value = 'reject'
  472. searchForm.value.auditStatus = STATUS.REJECTED
  473. // pagination.value.pageNum = 1
  474. await get()
  475. await getStats()
  476. console.log('aaaaaaaaaaaaaaaaaa看看checkTab,这是点击已驳回调用', checkTab.value)
  477. }
  478. onMounted(async () => {
  479. //await getAdminInfo()// 用户信息要挂吗
  480. getRefundGoods()
  481. getmarkets()
  482. await get()
  483. await getStats()
  484. console.log('aaaaaaaaaa这是挂载后调用')
  485. })
  486. </script>
  487. <style scoped>
  488. .pagination {
  489. display: flex;
  490. }
  491. .operation {
  492. display: flex;
  493. }
  494. .time-controls {
  495. display: flex;
  496. align-items: center;
  497. }
  498. .time-group {
  499. display: flex;
  500. align-items: center;
  501. gap: 10px;
  502. }
  503. </style>