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.

758 lines
24 KiB

2 months ago
2 months ago
2 months ago
3 months ago
5 months ago
3 months ago
6 months ago
6 months ago
5 months ago
6 months ago
5 months ago
2 months ago
2 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
2 months ago
5 months ago
5 months ago
6 months ago
2 months ago
5 months ago
5 months ago
6 months ago
5 months ago
5 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
5 months ago
2 months ago
6 months ago
5 months ago
6 months ago
6 months ago
6 months ago
6 months ago
5 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
2 months ago
6 months ago
2 months ago
6 months ago
6 months ago
  1. <template>
  2. <el-card class="card1" style="margin-bottom: 0.5vh;">
  3. <el-col style="margin-bottom: 1vh">
  4. <div class="select">
  5. <div class="selectRow">
  6. <el-text class="text" size="large">精网号</el-text>
  7. <el-input class="selectContent" v-model="searchForm.jwcode" placeholder="请输入精网号" clearable />
  8. </div>
  9. <div class="selectRow">
  10. <el-text class="text" size="large">商品名称</el-text>
  11. <el-select class="selectContent" v-model="searchForm.goodsName" placeholder="请输入商品名称" clearable>
  12. <el-option v-for="item in refundGoodsOptions" :key="item" :label="item" :value="item"></el-option>
  13. </el-select>
  14. </div>
  15. <div class="selectRow">
  16. <el-text class="text" size="large">退款类型</el-text>
  17. <el-select class="selectContent" v-model="searchForm.refundType" placeholder="请选择退款类型" clearable>
  18. <el-option label="商品退款" value="商品退款" />
  19. <el-option label="金币退款" value="金币退款" />
  20. </el-select>
  21. </div>
  22. <div class="selectRow">
  23. <el-text class="text" size="large">所属地区</el-text>
  24. <el-cascader class="selectContent" style="width: 12vw;" v-model="selectedMarketPath" :options="market"
  25. placeholder="请选择所属地区" clearable @change="handleMarketChange" />
  26. </div>
  27. </div>
  28. </el-col>
  29. <el-col>
  30. <div class="select">
  31. <div class="selectRow" style="width: 36vw;">
  32. <el-text class="text" size="large">
  33. {{ activeName === 'wait' ? '提交时间:' : '审核时间:' }}
  34. </el-text>
  35. <el-date-picker class="selectContent" v-model="dateRange" type="datetimerange" range-separator=""
  36. start-placeholder="起始时间" end-placeholder="结束时间" style="margin-right:1vw;width:25vw"
  37. @change="handleDatePickerChange" :default-time="defaultTime" :disabled-date="disabledDate" />
  38. <div v-if="false">
  39. <el-button @click="getToday()" :type="activeTimeRange === 'today' ? 'primary' : ''"></el-button>
  40. <el-button @click="getYesterday()" :type="activeTimeRange === 'yesterday' ? 'primary' : ''"></el-button>
  41. <el-button @click="get7Days()" :type="activeTimeRange === '7days' ? 'primary' : ''">近7天</el-button>
  42. </div>
  43. </div>
  44. <div class="selectRow" style="justify-content: flex-start;">
  45. <el-button @click="handleSearch" type="primary">查询</el-button>
  46. <el-button @click="resetSearch" type="success">重置</el-button>
  47. </div>
  48. </div>
  49. </el-col>
  50. </el-card>
  51. <el-card class="card2">
  52. <div class="custom-button-group">
  53. <el-button v-if="hasrefundWait && hasrefundWaitShow" :type="activeName === 'wait' ? 'primary' : 'default'"
  54. @click="handleButtonClick('wait')" class="custom-tab-button">
  55. 待审核
  56. </el-button>
  57. <el-button v-if="hasrefundThrough" :type="activeName === 'pass' ? 'primary' : 'default'"
  58. @click="handleButtonClick('pass')" class="custom-tab-button">
  59. 已通过
  60. </el-button>
  61. <el-button v-if="hasrefundReject" :type="activeName === 'reject' ? 'primary' : 'default'"
  62. @click="handleButtonClick('reject')" class="custom-tab-button">
  63. 已驳回
  64. </el-button>
  65. </div>
  66. <div class="goldStatistics">
  67. 退款总金币数{{
  68. format3((stats.permanentGolds + stats.freeGolds + stats.taskGolds).toFixed(2))
  69. }}金币&nbsp;&nbsp;&nbsp;&nbsp;
  70. 永久金币{{ format3(stats.permanentGolds.toFixed(2)) }}金币&nbsp;&nbsp;&nbsp;&nbsp;
  71. 免费金币{{ format3(stats.freeGolds.toFixed(2)) }}金币&nbsp;&nbsp;&nbsp;&nbsp;
  72. 任务金币{{ format3(stats.taskGolds.toFixed(2)) }}金币
  73. </div>
  74. <el-table :data="tableData" style="height:54vh;width:82vw" @sort-change="handleSortChange">
  75. <el-table-column type="index" label="序号" width="60" />
  76. <el-table-column prop="name" label="姓名" width="120" show-overflow-tooltip />
  77. <el-table-column prop="jwcode" label="精网号" width="120" />
  78. <el-table-column prop="market" label="所属地区" width="120" />
  79. <el-table-column prop="orderCode" label="订单号" width="260px" show-overflow-tooltip />
  80. <el-table-column prop="refundType" label="退款类型" width="120" />
  81. <el-table-column prop="refundModel" label="退款方式" width="120">
  82. <template #default="{ row }">
  83. {{ row.refundModel === 0 ? '全部退款' : '部分退款' }}
  84. </template>
  85. </el-table-column>
  86. <el-table-column prop="goodsName" label="退款商品" width="120" show-overflow-tooltip />
  87. <el-table-column prop="sumGold" label="退款金币总数" width="160" sortable="custom">
  88. <template #default="{ row }">
  89. {{ row.sumGold / 100 }}
  90. </template>
  91. </el-table-column>
  92. <el-table-column prop="permanentGold" label="永久金币" width="120" sortable="custom">
  93. <template #default="{ row }">
  94. {{ row.permanentGold / 100 }}
  95. </template>
  96. </el-table-column>
  97. <el-table-column prop="freeGold" label="免费金币" width="120" sortable="custom">
  98. <template #default="{ row }">
  99. {{ (row.freeJune + row.freeDecember) / 100 }}
  100. </template>
  101. </el-table-column>
  102. <el-table-column prop="taskGold" label="任务金币" width="120" sortable="custom">
  103. <template #default="{ row }">
  104. {{ row.taskGold / 100 }}
  105. </template>
  106. </el-table-column>
  107. <el-table-column prop="remark" label="备注" width="150" show-overflow-tooltip />
  108. <el-table-column prop="adminName" label="提交人" width="120" />
  109. <el-table-column v-if="checkTab === 'reject'" prop="rejectReason" label="驳回理由" width="150"
  110. show-overflow-tooltip />
  111. <el-table-column v-if="checkTab !== 'pending'" prop="auditName" label="审核人" width="120" />
  112. <el-table-column prop="createTime" label="提交时间" width="180" sortable="custom">
  113. <template #default="{ row }">
  114. {{
  115. checkTab === 'pending'
  116. ? moment(row.auditTime).format('YYYY-MM-DD HH:mm:ss')
  117. : moment(row.createTime).format('YYYY-MM-DD HH:mm:ss')
  118. }}
  119. </template>
  120. </el-table-column>
  121. <el-table-column v-if="checkTab !== 'pending'" prop="auditTime" label="审核时间" width="180">
  122. <template #default="{ row }">
  123. {{ row.auditTime ? moment(row.auditTime).format('YYYY-MM-DD HH:mm:ss') : '--' }}
  124. </template>
  125. </el-table-column>
  126. <el-table-column v-if="checkTab === 'pending' && (hasrefundWaitThough || hasrefundWaitReject) && hasrefundWaitShow"
  127. fixed="right" prop="operation" label="操作" width="150px">
  128. <template #default="scope">
  129. <div class="operation">
  130. <el-popconfirm title="确定要通过此条记录吗?" @confirm="handleApprove(scope.row)">
  131. <template #reference>
  132. <el-link :underline="false" class="pass-btn" v-if="hasrefundWaitThough"
  133. :disabled="clicked || cancelClicked" type="primary">
  134. 通过
  135. </el-link>
  136. </template>
  137. <template #actions="{ confirm, cancel }">
  138. <el-button size="small" @click="cancel">取消</el-button>
  139. <el-button type="primary" size="small" :disabled="clicked" @click="confirm">
  140. 确认
  141. </el-button>
  142. </template>
  143. </el-popconfirm>
  144. <el-link :underline="false" class="reject-btn" v-if="hasrefundWaitReject"
  145. :disabled="clicked || cancelClicked" type="primary" @click="showRejectDialog(scope.row)">
  146. 驳回
  147. </el-link>
  148. </div>
  149. </template>
  150. </el-table-column>
  151. </el-table>
  152. <el-pagination class="pagination" v-model:current-page="pagination.pageNum" v-model:page-size="pagination.pageSize"
  153. layout="total, sizes, prev, pager, next, jumper" :total="pagination.total" @size-change="handlePageSizeChange"
  154. @current-change="handleCurrentChange"></el-pagination>
  155. </el-card>
  156. <el-dialog v-model="rejectDialogVisible" title="驳回理由" width="500px">
  157. <el-form>
  158. <el-form-item label="驳回理由" required>
  159. <el-input v-model="rejectReason" type="textarea" :rows="4" placeholder="请输入驳回理由" maxlength="200"
  160. show-word-limit />
  161. </el-form-item>
  162. </el-form>
  163. <template #footer>
  164. <span class="dialog-footer">
  165. <el-button @click="rejectDialogVisible = false">取消</el-button>
  166. <el-button type="primary" @click="handleReject">确定</el-button>
  167. </span>
  168. </template>
  169. </el-dialog>
  170. </template>
  171. <script setup>
  172. import { onMounted, reactive, ref } from 'vue'
  173. import { ElMessage } from 'element-plus'
  174. import API from '@/util/http.js'
  175. import moment from 'moment'
  176. import { useAdminStore } from "@/store/index.js";
  177. import { storeToRefs } from "pinia";
  178. import dayjs from "dayjs";
  179. import { permissionMapping, hasMenuPermission } from "@/utils/menuTreePermission.js"
  180. const adminStore = useAdminStore();
  181. const { adminData, menuTree } = storeToRefs(adminStore);
  182. const defaultTime = [
  183. new Date(2000, 1, 1, 0, 0, 0),
  184. new Date(2000, 2, 1, 23, 59, 59),
  185. ]
  186. // 当前激活的时间按钮
  187. const activeTimeRange = ref('')
  188. const scopeValue = ref(null) // 当前行
  189. const rejectDialogVisible = ref(false)
  190. const rejectReason = ref('')
  191. // 状态常量
  192. const STATUS = {
  193. PENDING: 0, // 待审核
  194. APPROVED: 1, // 通过
  195. REJECTED: 2 // 驳回
  196. }
  197. //无法选择的时间
  198. const disabledDate = (time) => {
  199. const limitDate = new Date(2025, 0, 1);
  200. return time.getTime() < limitDate.getTime();
  201. }
  202. // 搜索表单数据
  203. const searchForm = ref({
  204. jwcode: '',
  205. refundModel: '',
  206. goodsName: '',
  207. market: "",
  208. startTime: '',
  209. endTime: '',
  210. auditStatus: '0'
  211. })
  212. const checkTab = ref('pending') // 能否不用STATUS常量,0是待审批,1是已通过,2是驳回,参数status需要Integer
  213. const dateRange = ref([])
  214. const pagination = ref({
  215. pageNum: 1,
  216. pageSize: 50,
  217. total: 0
  218. })
  219. const tableData = ref([])
  220. const marketOptions = ref([])
  221. const refundGoodsOptions = ref([])
  222. const adminInfo = ref({})
  223. // 统计合计数
  224. const stats = ref({
  225. totalNum: 0,
  226. totalCoins: 0,
  227. permanentGolds: 0,
  228. freeGolds: 0,
  229. taskGolds: 0
  230. })
  231. const rejectVisible = ref(false)
  232. const rejectObj = ref({})
  233. const passObj = ref({})
  234. // 标签页默认是待审批
  235. const activeName = ref('wait')
  236. const sortField = ref('')
  237. const sortOrder = ref('')
  238. const market = ref("")
  239. //退款操作权限
  240. const hasrefundThrough = ref(false) // 退款审核已通过
  241. const hasrefundReject = ref(false) // 退款审核已驳回
  242. const hasrefundWait = ref(false) // 退款审核待审核
  243. const hasrefundWaitShow = ref(false) // 退款审核待审核查看
  244. const hasrefundWaitThough = ref(false) // 退款审核通过
  245. const hasrefundWaitReject = ref(false) // 退款审核驳回
  246. // 初始化权限状态
  247. const initPermissions = async () => {
  248. if (!menuTree.value || !menuTree.value.length) return;
  249. // 退款相关权限
  250. hasrefundThrough.value = hasMenuPermission(menuTree.value, permissionMapping.refundThrough);
  251. hasrefundReject.value = hasMenuPermission(menuTree.value, permissionMapping.refundReject);
  252. hasrefundWait.value = hasMenuPermission(menuTree.value, permissionMapping.refundWait);
  253. hasrefundWaitShow.value = hasMenuPermission(menuTree.value, permissionMapping.refundWaitShow);
  254. hasrefundWaitThough.value = hasMenuPermission(menuTree.value, permissionMapping.refundWaitThough);
  255. hasrefundWaitReject.value = hasMenuPermission(menuTree.value, permissionMapping.refundWaitReject);
  256. console.log('退款权限赋值完成');
  257. };
  258. // 处理排序事件
  259. const handleSortChange = (column) => {
  260. if (column.prop === 'sumGold') {
  261. sortField.value = 'sum_gold'
  262. } else if (column.prop === 'permanentGold') {
  263. sortField.value = 'permanent_gold'
  264. } else if (column.prop === 'freeGold') {
  265. sortField.value = 'freeGold'
  266. } else if (column.prop === 'taskGold') {
  267. sortField.value = 'task_gold'
  268. } else if (column.prop === 'createTime') {
  269. sortField.value = 'create_time'
  270. } else if (column.prop === 'auditTime') {
  271. sortField.value = 'audit_time'
  272. } else {
  273. sortField.value = ''
  274. }
  275. sortOrder.value = column.order === 'ascending' ? 'asc' : 'desc'
  276. console.log('排序字段:', sortField.value)
  277. console.log('排序方式:', sortOrder.value)
  278. get()
  279. }
  280. // 显示驳回对话框
  281. const showRejectDialog = (row) => {
  282. if (!hasrefundWaitReject) {
  283. ElMessage.error('暂无权限')
  284. return
  285. }
  286. scopeValue.value = row
  287. rejectReason.value = ''
  288. rejectDialogVisible.value = true
  289. }
  290. // 查商品名
  291. const getRefundGoods = async () => {
  292. try {
  293. const res = await API({ url: '/general/goods' })
  294. refundGoodsOptions.value = res.data || []
  295. } catch (error) {
  296. console.error('获取商品列表失败', error)
  297. }
  298. }
  299. // 搜索方法
  300. const get = async function (val) {
  301. if (!hasrefundWaitShow) {
  302. ElMessage.error('暂无权限')
  303. return
  304. }
  305. try {
  306. if (typeof val === 'number') {
  307. pagination.value.pageNum = val
  308. }
  309. if (dateRange.value && dateRange.value.length === 2) {
  310. searchForm.value.startTime = moment(dateRange.value[0]).format('YYYY-MM-DD HH:mm:ss')
  311. searchForm.value.endTime = moment(dateRange.value[1]).format('YYYY-MM-DD HH:mm:ss')
  312. } else {
  313. searchForm.value.startTime = ''
  314. searchForm.value.endTime = ''
  315. }
  316. // if (searchForm.value.market === '总部' || searchForm.value.market === '研发部') {
  317. // searchForm.value.market = '';
  318. // }
  319. const params = {
  320. pageNum: pagination.value.pageNum,
  321. pageSize: pagination.value.pageSize,
  322. refundAudit: {
  323. ...searchForm.value,
  324. sortField: sortField.value,
  325. sortOrder: sortOrder.value
  326. }
  327. }
  328. console.log('看看传给后端的参数:', params)
  329. // 校验精网号(数字格式)
  330. if (searchForm.value.jwcode) {
  331. // 纯数字
  332. const numberRegex = /^\d{1,9}$/;
  333. // 检查是否不是数字
  334. if (!numberRegex.test(searchForm.value.jwcode)) {
  335. ElMessage.error('请检查精网号格式')
  336. // 上面提示过了
  337. return
  338. }
  339. }
  340. const res = await API({ url: '/audit/selectRefund', data: params })
  341. tableData.value = res.list || []
  342. pagination.value.total = res.total || 0
  343. console.log('查全部的total', pagination.value.total, res.total)
  344. } catch (error) {
  345. console.error('获取数据失败', error)
  346. }
  347. }
  348. const clicked = ref(false);
  349. // 通过
  350. const handleApprove = async (row) => {
  351. if (!hasrefundWaitThough) {
  352. ElMessage.error('暂无权限')
  353. return
  354. }
  355. clicked.value = true
  356. try {
  357. const params = {
  358. orderCode: row.orderCode,
  359. auditId: adminData.value.id,
  360. action: 1,// action的1是通过,2是驳回
  361. rejectReason: ''
  362. }
  363. await API({ url: '/audit/audit', data: params })
  364. ElMessage.success('审核通过成功')
  365. await get()
  366. clicked.value = false
  367. await getStats()
  368. } catch (error) {
  369. console.error('审核通过失败', error)
  370. ElMessage.error('操作失败')
  371. }
  372. }
  373. //控制驳回确认按钮禁用状态
  374. const cancelClicked = ref(false)
  375. // 处理驳回操作
  376. const handleReject = async () => {
  377. if (!hasrefundWaitReject) {
  378. ElMessage.error('暂无权限')
  379. return
  380. }
  381. cancelClicked.value = true
  382. if (!rejectReason.value.trim()) {
  383. ElMessage.warning('请输入驳回理由')
  384. return
  385. }
  386. try {
  387. const params = {
  388. orderCode: scopeValue.value.orderCode,
  389. auditId: adminData.value.id,
  390. action: 2,
  391. rejectReason: rejectReason.value
  392. }
  393. await API({ url: '/audit/audit', data: params })
  394. ElMessage.success('驳回成功')
  395. rejectDialogVisible.value = false
  396. await get()
  397. cancelClicked.value = false
  398. await getStats()
  399. console.log('看看驳回参数', params)
  400. } catch (error) {
  401. console.error('驳回失败', error)
  402. ElMessage.error('操作失败')
  403. }
  404. }
  405. const getStats = async () => {
  406. if (!hasrefundWaitShow) {
  407. return
  408. }
  409. try {
  410. const params = {
  411. pageNum: pagination.value.pageNum,
  412. pageSize: pagination.value.pageSize,
  413. refundAudit: {
  414. ...searchForm.value
  415. }
  416. }
  417. if (searchForm.value.jwcode) {
  418. // 纯数字
  419. const numberRegex = /^\d{1,9}$/;
  420. // 检查是否不是数字
  421. if (!numberRegex.test(searchForm.value.jwcode)) {
  422. // ElMessage.error('精网号必须为数字格式')
  423. // 上面提示过了
  424. return
  425. }
  426. }
  427. const res = await API({
  428. url: '/audit/sumRefundGold',
  429. data: params
  430. })
  431. stats.value.totalNum = res.totalNum
  432. stats.value.permanentGolds = res.permanentGolds / 100
  433. stats.value.freeGolds = res.freeGolds / 100
  434. stats.value.taskGolds = res.taskGolds / 100
  435. console.log('see see stats和搜索对象', stats.value, params)
  436. } catch (error) {
  437. console.log('请求失败', error)
  438. }
  439. }
  440. // 搜索
  441. const handleSearch = function () {
  442. trimJwCode()
  443. get()
  444. getStats()
  445. }
  446. // 重置
  447. const resetSearch = function () {
  448. const auditStatus = searchForm.value.auditStatus;
  449. searchForm.value = {
  450. jwcode: '',
  451. refundType: '',
  452. goodsName: '',
  453. market: "",
  454. startTime: '',
  455. endTime: '',
  456. sortField: '',
  457. sortOrder: '',
  458. auditStatus: auditStatus
  459. }
  460. dateRange.value = []
  461. activeTimeRange.value = '' // 清除激活状态
  462. selectedMarketPath.value = []
  463. get()
  464. getStats()
  465. }
  466. // 今天
  467. const getToday = function () {
  468. const today = dayjs()
  469. const startTime = today.startOf('day').format('YYYY-MM-DD HH:mm:ss')
  470. const endTime = today.endOf('day').format('YYYY-MM-DD HH:mm:ss')
  471. dateRange.value = [startTime, endTime]
  472. console.log('dateRange', dateRange.value)
  473. activeTimeRange.value = 'today'
  474. get()
  475. getStats()
  476. }
  477. // 昨天
  478. const getYesterday = function () {
  479. const today = dayjs()
  480. const startTime = today.subtract(1, 'day').startOf('day').format('YYYY-MM-DD HH:mm:ss')
  481. const endTime = today.subtract(1, 'day').endOf('day').format('YYYY-MM-DD HH:mm:ss')
  482. dateRange.value = [startTime, endTime]
  483. console.log('dateRange', dateRange.value)
  484. activeTimeRange.value = 'yesterday'
  485. get()
  486. getStats()
  487. }
  488. // 近7天
  489. const get7Days = function () {
  490. const today = dayjs()
  491. const startTime = today.subtract(6, 'day').startOf('day').format('YYYY-MM-DD HH:mm:ss')
  492. const endTime = today.endOf('day').format('YYYY-MM-DD HH:mm:ss')
  493. dateRange.value = [startTime, endTime]
  494. console.log('dateRange', dateRange.value)
  495. activeTimeRange.value = '7days'
  496. get()
  497. getStats()
  498. }
  499. const handleButtonClick = function (name) {
  500. activeName.value = name
  501. if (name === 'wait') {
  502. if (!hasrefundWait) {
  503. ElMessage.error('暂无权限')
  504. return
  505. }
  506. if (hasrefundWaitShow) {
  507. adminWait()
  508. }
  509. } else if (name === 'pass') {
  510. if (!hasrefundThrough) {
  511. ElMessage.error('暂无权限')
  512. return
  513. }
  514. adminPass()
  515. } else if (name === 'reject') {
  516. if (!hasrefundReject) {
  517. ElMessage.error('暂无权限')
  518. return
  519. }
  520. adminReject()
  521. }
  522. }
  523. // const handleClick = function (tab, event) {
  524. // activeName.value = tab.props.name
  525. // if (tab.props.name === 'wait') {
  526. // console.log(hasrefundWait.value);
  527. // if (!hasrefundWait) {
  528. // ElMessage.error('暂无权限')
  529. // return
  530. // }
  531. // adminWait()
  532. // } else if (tab.props.name === 'pass') {
  533. // if (!hasrefundThrough.value) {
  534. // ElMessage.error('暂无权限')
  535. // return
  536. // }
  537. // adminPass()
  538. // } else if (tab.props.name === 'reject') {
  539. // if (!hasrefundReject) {
  540. // ElMessage.error('暂无权限')
  541. // return
  542. // }
  543. // adminReject()
  544. // }
  545. // }
  546. // 待审核
  547. const adminWait = async function () {
  548. checkTab.value = 'pending'
  549. searchForm.value.auditStatus = STATUS.PENDING
  550. await get()
  551. await getStats()
  552. }
  553. // 已通过
  554. const adminPass = async function () {
  555. checkTab.value = 'pass'
  556. searchForm.value.auditStatus = STATUS.APPROVED
  557. await get()
  558. await getStats()
  559. }
  560. // 已驳回
  561. const adminReject = async function () {
  562. checkTab.value = 'reject'
  563. searchForm.value.auditStatus = STATUS.REJECTED
  564. await get()
  565. await getStats()
  566. }
  567. const selectedMarketPath = ref("")
  568. const handleMarketChange = (value) => {
  569. if (value && value.length > 0) {
  570. searchForm.value.market = value[value.length - 1]
  571. } else {
  572. searchForm.value.market = ''
  573. }
  574. }
  575. // 获取地区,修改为级联下拉框
  576. const getMarket = async function () {
  577. try {
  578. const result = await API({
  579. url: '/market/selectMarket',
  580. })
  581. console.log('请求成功', result)
  582. // 递归转换树形结构为级联选择器需要的格式(跳过第一级节点)
  583. const transformTree = (nodes) => {
  584. // 直接处理第一级节点的子节点
  585. const allChildren = nodes.flatMap(node => node.children || []);
  586. return allChildren.map(child => {
  587. const grandchildren = child.children && child.children.length
  588. ? transformTree([child]) // 递归处理子节点
  589. : null;
  590. return {
  591. value: child.name,
  592. label: child.name,
  593. children: grandchildren
  594. };
  595. });
  596. };
  597. market.value = transformTree(result.data)
  598. console.log('转换后的地区树==============', market.value)
  599. } catch (error) {
  600. console.log('请求失败', error)
  601. }
  602. }
  603. const trimJwCode = () => {
  604. if (searchForm.value.jwcode) {
  605. searchForm.value.jwcode = searchForm.value.jwcode.replace(/\s/g, '');
  606. }
  607. }
  608. // 日期选择器变化时清除按钮激活状态
  609. const handleDatePickerChange = () => {
  610. activeTimeRange.value = ''
  611. }
  612. const format3 = (num) => {
  613. // 每三位添加逗号
  614. return num.toLocaleString('en-US')
  615. }
  616. // 表单验证
  617. const rules = reactive({
  618. reason: [{ required: true, message: '请输入驳回理由', trigger: 'blur' }]
  619. })
  620. const handlePageSizeChange = function (val) {
  621. pagination.value.pageSize = val
  622. get()
  623. }
  624. const handleCurrentChange = function (val) {
  625. pagination.value.pageNum = val
  626. get()
  627. }
  628. onMounted(async () => {
  629. await initPermissions()
  630. if (hasrefundWaitShow.value) {
  631. searchForm.value.auditStatus = '0'
  632. } else if (hasrefundThrough.value) {
  633. searchForm.value.auditStatus = '1'
  634. } else if (hasrefundReject) {
  635. searchForm.value.auditStatus = '2'
  636. }
  637. getRefundGoods()
  638. await getMarket()
  639. await get()
  640. await getStats()
  641. })
  642. </script>
  643. <style scoped lang="scss">
  644. .pagination {
  645. display: flex;
  646. margin-top: 0.5vh;
  647. }
  648. .operation {
  649. display: flex;
  650. }
  651. // 搜索的卡片样式
  652. .card1 {
  653. background: #F3FAFE;
  654. }
  655. // 表单的卡片样式
  656. .card2 {
  657. background: #E7F4FD;
  658. }
  659. // 新币总数等等
  660. .goldStatistics {
  661. margin-left: 1vw;
  662. margin-bottom: 1vh;
  663. color: #000000;
  664. font-family: "PingFang SC";
  665. font-size: 16px;
  666. font-style: normal;
  667. font-weight: 700;
  668. line-height: 20px;
  669. }
  670. // 表头背景等
  671. :deep(.el-table__header-wrapper),
  672. :deep(.el-table__body-wrapper),
  673. :deep(.el-table__cell),
  674. /* 表格 */
  675. :deep(.el-table__body td) {
  676. background-color: #F3FAFE !important;
  677. }
  678. /* 表头 */
  679. :deep(.el-table__header th) {
  680. background-color: #F3FAFE !important;
  681. }
  682. /* 鼠标悬停 */
  683. :deep(.el-table__row:hover > .el-table__cell) {
  684. background-color: #E5EBFE !important;
  685. }
  686. /* 自定义按钮组布局 */
  687. .custom-button-group {
  688. display: flex;
  689. margin-bottom: 16px;
  690. }
  691. /* 自定义激活状态样式 - 使用正确的Element Plus类选择器 */
  692. :deep(.el-button.custom-tab-button.el-button--primary) {
  693. background-color: #2741DE !important;
  694. border-color: #2741DE !important;
  695. color: #F3FAFE !important;
  696. }
  697. /* 鼠标悬停效果 */
  698. :deep(.el-button.custom-tab-button:hover:not(.is-disabled)) {
  699. opacity: 0.8;
  700. }
  701. .select {
  702. display: flex;
  703. .selectRow {
  704. width: 17vw;
  705. display: flex;
  706. align-items: center;
  707. justify-content: center;
  708. padding: 0 0.5vw;
  709. .text {
  710. width: 5vw;
  711. font-size: 15px;
  712. }
  713. .selectContent {
  714. flex: 1;
  715. }
  716. }
  717. }
  718. </style>