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.

771 lines
25 KiB

2 months ago
2 months ago
2 months ago
2 months ago
1 month 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
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
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
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
  1. <script setup>
  2. import { ref, reactive, onMounted } from 'vue'
  3. import { ElMessage, ElMessageBox } from 'element-plus'
  4. import request from '@/util/http.js'
  5. import dayjs from 'dayjs'
  6. import { useI18n } from 'vue-i18n'
  7. import { Moneyfunds, refundOnline } from '@/api/cash/financialAccount.js'
  8. import { useAdminStore } from '@/store/index.js'
  9. import { storeToRefs } from 'pinia'
  10. import _ from 'lodash';
  11. const adminStore = useAdminStore()
  12. const { adminData } = storeToRefs(adminStore)
  13. const { t } = useI18n()
  14. const paytypeList = [
  15. t('cash.payMethods.stripe'),
  16. t('cash.payMethods.paymentAsia'),
  17. t('cash.payMethods.ipay88'),
  18. t('cash.payMethods.bankTransfer'),
  19. t('cash.payMethods.card'),
  20. t('cash.payMethods.cash'),
  21. t('cash.payMethods.check'),
  22. t('cash.payMethods.grabpay'),
  23. t('cash.payMethods.nets'),
  24. t('cash.payMethods.transfer'),
  25. t('cash.payMethods.paypal'),
  26. ]
  27. const payPlatformOptions = ref([...paytypeList])
  28. const statusOptions = [
  29. { label: '已到账', value: 4 },
  30. { label: '已退款', value: 6 }
  31. ]
  32. // 地区树
  33. const marketOptions = ref([])
  34. // 查询参数
  35. const queryParams = reactive({
  36. jwcode: '',
  37. markets: [], // 下拉多选
  38. timeRange: [], // [startTime, endTime]
  39. payType: '',
  40. orderCode: '',
  41. statuses: [],
  42. pageNum: 1,
  43. pageSize: 20
  44. })
  45. const total = ref(0)
  46. const tableData = ref([])
  47. const loading = ref(false)
  48. // 转换树形结构(参考 coinConsumeDetail.vue)
  49. const transformTree = (nodes) => {
  50. const allChildren = nodes.flatMap(node => node.children || []);
  51. return allChildren.map(child => {
  52. const grandchildren = child.children && child.children.length
  53. ? transformTree([child])
  54. : null;
  55. return {
  56. value: child.id,
  57. label: child.name,
  58. children: grandchildren
  59. };
  60. });
  61. };
  62. // 获取地区数据
  63. const getMarket = async () => {
  64. try {
  65. const result = await request({ url: '/market/selectMarket' });
  66. if (result && result.data) {
  67. marketOptions.value = transformTree(result.data)
  68. }
  69. } catch (error) {
  70. console.error('获取地区失败', error)
  71. }
  72. }
  73. // 查询列表
  74. const fetchData = async () => {
  75. loading.value = true
  76. try {
  77. // 构建请求参数
  78. const params = {
  79. pageNum: queryParams.pageNum,
  80. pageSize: queryParams.pageSize,
  81. fundsDTO: {
  82. jwcode: queryParams.jwcode,
  83. markets: queryParams.markets,
  84. startTime: queryParams.timeRange?.[0] ? dayjs(queryParams.timeRange[0]).format('YYYY-MM-DD HH:mm:ss') : '',
  85. endTime: queryParams.timeRange?.[1] ? dayjs(queryParams.timeRange[1]).format('YYYY-MM-DD HH:mm:ss') : '',
  86. payType: queryParams.payType,
  87. orderCode: queryParams.orderCode,
  88. statuses: queryParams.statuses,
  89. }
  90. }
  91. console.log('查询参数:', params)
  92. const res = await Moneyfunds(params)
  93. if (res.code == 200) {
  94. tableData.value = res.data.list || []
  95. total.value = res.data.total || 0
  96. loading.value = false
  97. } else {
  98. ElMessage.error(res.msg || '获取数据失败')
  99. loading.value = false
  100. }
  101. } catch (error) {
  102. console.error(error)
  103. loading.value = false
  104. ElMessage.error('获取数据失败')
  105. }
  106. }
  107. const handleSearch = () => {
  108. queryParams.pageNum = 1
  109. fetchData()
  110. }
  111. const handleReset = () => {
  112. queryParams.jwcode = ''
  113. queryParams.markets = []
  114. queryParams.timeRange = null
  115. queryParams.payType = ''
  116. queryParams.orderCode = ''
  117. queryParams.statuses = []
  118. handleSearch()
  119. }
  120. const handlePageSizeChange = (val) => {
  121. queryParams.pageSize = val
  122. fetchData()
  123. }
  124. const handleCurrentChange = (val) => {
  125. queryParams.pageNum = val
  126. fetchData()
  127. }
  128. // 退款操作
  129. const openRefundConfirm = (row) => {
  130. textContent.value = t('common.willRefundOrder') + '?'
  131. refundConfirmDialog.value = true
  132. refundFormData.value = {
  133. ...row,
  134. oldpermanentGold: row.permanentGold,//退款永久金币
  135. oldfreeGold: row.freeGold,//退款免费金币
  136. permanentGold: null,
  137. freeGold: null,
  138. }
  139. console.log(row);
  140. }
  141. const openRefundDialog = () => {
  142. refundDialog.value = true
  143. closeConfirmRefund()
  144. }
  145. const closeConfirmRefund = () => {
  146. refundConfirmDialog.value = false
  147. textContent.value = ''
  148. }
  149. const refundConfirmDialog = ref(false)
  150. const textContent = ref('')
  151. const refundDialog = ref(false)
  152. const refundFormData = ref({})
  153. const handleRefund = async () => {
  154. try {
  155. if (refundFormData.value.refundModel == 1) {
  156. refundFormData.value.permanentGold = refundFormData.value.oldpermanentGold
  157. refundFormData.value.freeGold = refundFormData.value.oldfreeGold
  158. }
  159. let params = {
  160. jwcode: refundFormData.value.jwcode,
  161. name: refundFormData.value.name,
  162. market: refundFormData.value.marketName,
  163. submitterMarket: adminData.value.markets,
  164. remark: refundFormData.value.remark,
  165. originalOrderId: refundFormData.value.id,
  166. refundReason: refundFormData.value.refundReason,
  167. refundModel: refundFormData.value.refundModel,
  168. orderCode: refundFormData.value.orderCode,
  169. submitterId: adminData.value.id,
  170. submitterMarket: adminData.value.markets,
  171. permanentGold: (refundFormData.value.permanentGold) * 100 || 0,
  172. handlingCharge: refundFormData.value.handlingCharge == null ? null : refundFormData.value.handlingCharge * 100,
  173. freeGold: (refundFormData.value.freeGold) * 100 || 0,
  174. }
  175. console.log('这是退款参数:', params);
  176. const res = await refundOnline(params)
  177. if (res.code == 200) {
  178. refundDialog.value = false
  179. fetchData()
  180. } else {
  181. ElMessage.error(res.msg || '退款失败')
  182. }
  183. } catch (error) {
  184. console.error(error)
  185. }
  186. }
  187. // ==================== 导出相关逻辑 ====================
  188. const exportListVisible = ref(false)
  189. const exportList = ref([])
  190. const exportListLoading = ref(false)
  191. // 导出Excel
  192. const handleExport = async () => {
  193. try {
  194. const params = {
  195. pageNum: queryParams.pageNum,
  196. pageSize: queryParams.pageSize,
  197. fundsDTO: {
  198. jwcode: queryParams.jwcode,
  199. markets: queryParams.markets,
  200. startTime: queryParams.timeRange?.[0] ? dayjs(queryParams.timeRange[0]).format('YYYY-MM-DD HH:mm:ss') : '',
  201. endTime: queryParams.timeRange?.[1] ? dayjs(queryParams.timeRange[1]).format('YYYY-MM-DD HH:mm:ss') : '',
  202. payType: queryParams.payType,
  203. orderCode: queryParams.orderCode,
  204. statuses: queryParams.statuses,
  205. }
  206. }
  207. // TODO: 确认导出接口 URL
  208. const res = await request({ url: '/export/exportCash', data: params })
  209. if (res.code == 200) {
  210. console.log('导出参数', params)
  211. ElMessage.success(t('elmessage.exportSuccess'))
  212. }
  213. } catch (error) {
  214. console.error(error)
  215. ElMessage.error('导出失败')
  216. }
  217. }
  218. // 打开导出列表弹窗
  219. const openExportList = () => {
  220. getExportList()
  221. exportListVisible.value = true
  222. }
  223. // 获取导出列表
  224. const getExportList = async () => {
  225. exportListLoading.value = true
  226. try {
  227. const result = await request({ url: '/export/export' })
  228. if (result.code === 200) {
  229. const filteredData = result.data.filter(item => item.type == 13);
  230. exportList.value = filteredData || []
  231. } else {
  232. ElMessage.error(result.msg || t('elmessage.getExportListError'))
  233. }
  234. } catch (error) {
  235. console.error('获取导出列表出错:', error)
  236. ElMessage.error(t('elmessage.getExportListError'))
  237. } finally {
  238. exportListLoading.value = false
  239. }
  240. }
  241. // 下载导出文件
  242. const downloadExportFile = (item) => {
  243. if (item.state === 2) {
  244. const link = document.createElement('a')
  245. link.href = item.url
  246. link.download = item.fileName
  247. link.click()
  248. } else {
  249. ElMessage.warning(t('elmessage.exportingInProgress'))
  250. }
  251. }
  252. // 根据状态返回对应的标签类型
  253. const getTagType = (state) => {
  254. switch (state) {
  255. case 0: return 'info';
  256. case 1: return 'primary';
  257. case 2: return 'success';
  258. case 3: return 'danger';
  259. default: return 'info';
  260. }
  261. }
  262. // 根据状态返回对应的标签文案
  263. const getTagText = (state) => {
  264. switch (state) {
  265. case 0: return t('elmessage.pendingExecution');
  266. case 1: return t('elmessage.executing');
  267. case 2: return t('elmessage.executed');
  268. case 3: return t('elmessage.errorExecution');
  269. default: return t('elmessage.unknownStatus');
  270. }
  271. }
  272. const throttledsubmitRefund = _.throttle(handleRefund, 5000, {
  273. trailing: false
  274. })
  275. onMounted(() => {
  276. getMarket()
  277. fetchData()
  278. })
  279. </script>
  280. <template>
  281. <div class="cash-flow-container">
  282. <!-- 搜索区域 -->
  283. <el-card class="search-card">
  284. <div class="search-bar">
  285. <!-- 第一行 -->
  286. <div class="search-row">
  287. <div class="search-item">
  288. <span class="label">精网号</span>
  289. <el-input v-model="queryParams.jwcode" placeholder="请输入精网号" clearable />
  290. </div>
  291. <div class="search-item">
  292. <span class="label">所属地区</span>
  293. <!-- 下拉多选使用 el-cascader 匹配地区树结构 -->
  294. <el-cascader v-model="queryParams.markets" :options="marketOptions"
  295. :props="{ multiple: true, emitPath: false }" collapse-tags collapse-tags-tooltip placeholder="请选择地区"
  296. clearable style="width: 220px;" />
  297. </div>
  298. <div class="search-item">
  299. <span class="label">支付平台</span>
  300. <el-select v-model="queryParams.payType" placeholder="请选择" clearable>
  301. <el-option v-for="item in payPlatformOptions" :key="item" :label="item" :value="item" />
  302. </el-select>
  303. </div>
  304. <div class="search-item">
  305. <span class="label">状态</span>
  306. <el-select v-model="queryParams.statuses[0]" placeholder="请选择" clearable>
  307. <el-option v-for="item in statusOptions" :key="item.value" :label="item.label" :value="item.value" />
  308. </el-select>
  309. </div>
  310. <div class="search-item">
  311. <span class="label">订单号</span>
  312. <el-input v-model="queryParams.orderCode" placeholder="请输入订单号" clearable />
  313. </div>
  314. <div class="search-item" style="width: auto;">
  315. <span class="label">付款时间</span>
  316. <el-date-picker v-model="queryParams.timeRange" type="datetimerange" range-separator=""
  317. start-placeholder="开始时间" end-placeholder="结束时间"
  318. :default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]" style="width: 350px;" />
  319. </div>
  320. <div class="search-btn-group">
  321. <el-button type="primary" @click="handleSearch">{{ t('common.search') }}</el-button>
  322. <el-button type="primary" @click="handleExport">{{ t('common.exportExcel') }}</el-button>
  323. <el-button type="primary" @click="openExportList">{{ t('common.viewExportList') }}</el-button>
  324. <el-button type="success" @click="handleReset">{{ t('common.reset') }}</el-button>
  325. </div>
  326. </div>
  327. </div>
  328. </el-card>
  329. <!-- 表格区域 -->
  330. <el-card class="table-card">
  331. <el-table :data="tableData" v-loading="loading" style="width: 100%; flex: 1;"
  332. :cell-style="{ textAlign: 'center' }"
  333. :header-cell-style="{ background: '#F3FAFE', color: '#333', textAlign: 'center' }">
  334. <el-table-column type="index" label="序号" width="60" align="center" fixed="left" />
  335. <el-table-column prop="jwcode" label="精网号" width="120" fixed="left" />
  336. <el-table-column prop="name" label="姓名" width="150" show-overflow-tooltip />
  337. <el-table-column prop="marketName" label="所属地区" width="120" show-overflow-tooltip />
  338. <el-table-column prop="orderCode" label="系统交易号" width="280" show-overflow-tooltip />
  339. <el-table-column prop="paymentAmount" label="付款金额" width="150" align="right">
  340. <!-- <template #default="{ row }">
  341. {{ row.paymentAmount }} {{ row.paymentCurrency }}
  342. </template> -->
  343. </el-table-column>
  344. <el-table-column prop="paymentCurrencyName" label="付款币种" width="120" show-overflow-tooltip />
  345. <el-table-column prop="receivedAmount" label="到账金额" width="150" align="right">
  346. <!-- <template #default="{ row }">
  347. {{ row.receivedAmount }} {{ row.receivedCurrency }}
  348. </template> -->
  349. </el-table-column>
  350. <el-table-column prop="receivedCurrencyName" label="到账币种" width="120" show-overflow-tooltip />
  351. <el-table-column prop="handlingCharge" label="手续费" width="100" align="right" />
  352. <el-table-column prop="payType" label="支付方式" width="120" align="center" />
  353. <el-table-column prop="payTime" label="付款时间" width="180" align="center" />
  354. <el-table-column prop="status" label="状态" width="100" align="center" fixed="right">
  355. <template #default="{ row }">
  356. <el-tag :type="row.status === 4 ? 'success' : 'warning'" effect="plain">
  357. {{ row.status === 4 ? '已到账' : '已退款' }}
  358. </el-tag>
  359. </template>
  360. </el-table-column>
  361. <el-table-column label="操作" width="100" fixed="right" align="center">
  362. <template #default="{ row }">
  363. <el-button v-if="row.orderCode.slice(0, 4) == 'GOLD'" type="danger" link size="small"
  364. @click="openRefundConfirm(row)">
  365. 退款
  366. </el-button>
  367. </template>
  368. </el-table-column>
  369. </el-table>
  370. <!-- 分页 -->
  371. <div class="pagination-container">
  372. <el-pagination background layout="total, sizes, prev, pager, next, jumper" :total="total"
  373. :current-page="queryParams.pageNum" :page-size="queryParams.pageSize" :page-sizes="[10, 20, 50, 100]"
  374. @size-change="handlePageSizeChange" @current-change="handleCurrentChange" />
  375. </div>
  376. </el-card>
  377. <!-- 导出列表弹窗 -->
  378. <el-dialog v-model="exportListVisible" :title="t('common_export.exportList')" width="80%">
  379. <el-table :data="exportList" style="width: 100% ;height: 60vh;" :loading="exportListLoading">
  380. <el-table-column prop="fileName" :label="t('common_export.fileName')" />
  381. <el-table-column prop="state" :label="t('common_export.status')">
  382. <template #default="scope">
  383. <el-tag :type="getTagType(scope.row.state)" :effect="scope.row.state === 3 ? 'light' : 'plain'">
  384. {{ getTagText(scope.row.state) }}
  385. </el-tag>
  386. </template>
  387. </el-table-column>
  388. <el-table-column prop="createTime" :label="t('common_export.createTime')">
  389. <template #default="scope">
  390. {{ dayjs(scope.row.createTime).format('YYYY-MM-DD HH:mm:ss') }}
  391. </template>
  392. </el-table-column>
  393. <el-table-column :label="t('common_export.operation')">
  394. <template #default="scope">
  395. <el-button type="primary" size="small" @click="downloadExportFile(scope.row)"
  396. :disabled="scope.row.state !== 2">
  397. {{ t('common_export.download') }}
  398. </el-button>
  399. </template>
  400. </el-table-column>
  401. </el-table>
  402. <template #footer>
  403. <div class="dialog-footer">
  404. <el-button text @click="exportListVisible = false">{{ t('common_export.close') }}</el-button>
  405. </div>
  406. </template>
  407. </el-dialog>
  408. <div class="recallDialog" v-show="refundConfirmDialog">
  409. <div class="close">
  410. <button @click="closeConfirmRefund" class="Btn">{{ t('common.close') }}</button>
  411. </div>
  412. <div class="text">
  413. <text class="txt">{{ textContent }}</text>
  414. </div>
  415. <div class="cancle">
  416. <button @click="closeConfirmRefund" class="Btn">{{ t('common.cancel') }}</button>
  417. </div>
  418. <div class="confirm">
  419. <button @click="openRefundDialog" class="Btn">{{ t('common.confirm') }}</button>
  420. </div>
  421. </div>
  422. <el-dialog v-model="refundDialog" :title="t('common_add.refund')" class="refundDialog" overflow draggable
  423. style="width: 40vw;" :before-close="closeRefundForm">
  424. <div style="display: flex;">
  425. <div class="left">
  426. <div class="add-item">
  427. <el-text style="width:4vw;">{{ t('common_add.jwcode') }}</el-text>
  428. <el-input v-model="refundFormData.jwcode" style="width:10vw;" disabled />
  429. </div>
  430. <div class="add-item">
  431. <el-text style="width:4vw;">{{ t('common_add.customerName') }}</el-text>
  432. <el-input v-model="refundFormData.name" style="width:10vw;" disabled />
  433. </div>
  434. <div class="add-item">
  435. <el-text style="width:4vw;">{{ t('common_add.market') }}</el-text>
  436. <el-input v-model="refundFormData.marketName" style="width:10vw;" disabled />
  437. </div>
  438. <div class="add-item">
  439. <el-text style="width:4vw;">{{ t('common_add.activity') }}</el-text>
  440. <el-input v-model="refundFormData.activity" style="width:10vw;" disabled />
  441. </div>
  442. <div class="add-item">
  443. <el-text style="width:4vw;">{{ t('common_add.productName') }}</el-text>
  444. <el-input v-model="refundFormData.goodsName" style="width:10vw;" disabled />
  445. </div>
  446. <div style="display: flex; margin-bottom: 10px;">
  447. <div style=" display: flex; align-items: center;justify-content: center; ">
  448. <span style="color: #999999; white-space: nowrap;">{{ t('common_add.permanentGold')
  449. }}</span>
  450. <el-input style="padding-right: 10px; height: 30px; width: 70px;"
  451. v-model="refundFormData.oldpermanentGold" disabled />
  452. </div>
  453. <div style=" display: flex; align-items: center;justify-content: center; ">
  454. <span style="color: #999999; white-space: nowrap;">{{ t('common_add.freeGold') }}</span>
  455. <el-input style="padding-right: 10px; height: 30px; width: 70px;" v-model="refundFormData.oldfreeGold"
  456. disabled />
  457. </div>
  458. </div>
  459. <div class="add-item">
  460. <el-text style="width:4vw;">{{ t('common_add.payCurrency') }}</el-text>
  461. <el-input v-model="refundFormData.paymentCurrency" style="width:10vw;" disabled />
  462. </div>
  463. <div class="add-item">
  464. <el-text style="width:4vw;">{{ t('common_add.payAmount') }}</el-text>
  465. <el-input v-model="refundFormData.paymentAmount" style="width:10vw;" disabled />
  466. </div>
  467. <div class="add-item">
  468. <el-text style="width:4vw;">{{ t('common_add.payMethod') }}</el-text>
  469. <el-input v-model="refundFormData.payType" style="width:10vw;" disabled />
  470. </div>
  471. <div class="add-item">
  472. <el-text style="width:4vw;">{{ t('common_add.payTime') }}</el-text>
  473. <el-date-picker v-model="refundFormData.payTime" type="datetime" style="width:10vw;" disabled />
  474. </div>
  475. <div class="add-item">
  476. <el-text style="width:4vw;" size="small">{{ t('common_add.transferVoucher') }}</el-text>
  477. <el-form-item :rules="{ required: true, message: t('common_add.uploadPhoto'), trigger: 'change' }">
  478. <el-upload ref="uploadRef" :auto-upload="false" list-type="picture-card" :show-file-list="false">
  479. <template #default>
  480. <img v-if="refundFormData.voucher" :src="refundFormData.voucher"
  481. style="width: 100%; height: 100%; object-fit: cover;">
  482. <el-icon v-else>
  483. <Plus />
  484. </el-icon>
  485. </template>
  486. </el-upload>
  487. </el-form-item>
  488. </div>
  489. <div class="add-item">
  490. <el-text style="width:4vw;">{{ t('common_add.remark') }}</el-text>
  491. <el-input v-model="refundFormData.remark" style="width:10vw;" :rows="2" type="textarea" maxLength="100"
  492. disabled show-word-limit />
  493. </div>
  494. </div>
  495. <div class="right">
  496. <div class="add-item">
  497. <el-text style="width:4vw;">{{ t('common_add.refundModel') }}</el-text>
  498. <el-radio-group v-model="refundFormData.refundModel">
  499. <el-radio value="0">{{ t('common_add.refundModelAll') }}</el-radio>
  500. <el-radio value="1">{{ t('common_add.refundModelPart') }}</el-radio>
  501. </el-radio-group>
  502. </div>
  503. <div v-show="refundFormData.refundModel == '1'" style="display: flex; margin-bottom: 10px;">
  504. <div style=" display: flex; align-items: center;justify-content: center; ">
  505. <span style="color: #999999; white-space: nowrap;">{{ t('common_add.permanentGold')
  506. }}</span>
  507. <el-input style="padding-right: 10px; height: 30px; width: 70px;"
  508. v-model="refundFormData.permanentGold" />
  509. </div>
  510. <div style=" display: flex; align-items: center;justify-content: center; ">
  511. <span style="color: #999999; white-space: nowrap;">{{ t('common_add.freeGold') }}</span>
  512. <el-input style="padding-right: 10px; height: 30px; width: 70px;" v-model="refundFormData.freeGold" />
  513. </div>
  514. </div>
  515. <div class="add-item">
  516. <el-text style="width:4vw;">{{ t('common_add.refundReason') }}</el-text>
  517. <el-input v-model="refundFormData.refundReason" style="width:10vw;" :rows="5" maxlength="150"
  518. show-word-limit type="textarea" />
  519. </div>
  520. <div>{{ t('common_add.tip') }}</div>
  521. <div style="display:flex;justify-content: center;margin-top: 5vh;">
  522. <el-button type="default" @click="resetRefund">{{ t('common.reset') }}</el-button>
  523. <el-button type="primary" @click="throttledsubmitRefund">{{ t('common.submit') }}</el-button>
  524. </div>
  525. </div>
  526. </div>
  527. </el-dialog>
  528. </div>
  529. </template>
  530. <style scoped lang="scss">
  531. .cash-flow-container {
  532. display: flex;
  533. flex-direction: column;
  534. height: 100%;
  535. }
  536. .search-card {
  537. margin-bottom: 10px;
  538. background: #F3FAFE; // 浅蓝背景
  539. border: none;
  540. :deep(.el-card__body) {
  541. padding: 15px;
  542. }
  543. }
  544. .search-bar {
  545. display: flex;
  546. flex-direction: column;
  547. gap: 15px;
  548. }
  549. .search-row {
  550. display: flex;
  551. flex-wrap: wrap;
  552. gap: 20px;
  553. align-items: center;
  554. }
  555. .search-item {
  556. display: flex;
  557. align-items: center;
  558. .label {
  559. font-size: 15px; // 参考 coinConsumeDetail 的 .text size="large"
  560. color: #000; // 或 #606266
  561. white-space: nowrap;
  562. margin-right: 8px;
  563. min-width: 60px;
  564. text-align: right;
  565. }
  566. .el-input,
  567. .el-select {
  568. width: 200px;
  569. }
  570. }
  571. .search-btn-group {
  572. margin-left: 20px; // 靠右对齐
  573. display: flex;
  574. gap: 10px;
  575. }
  576. .table-card {
  577. background: #E7F4FD;
  578. flex: 1;
  579. border: none;
  580. display: flex;
  581. flex-direction: column;
  582. :deep(.el-card__body) {
  583. padding: 20px;
  584. flex: 1;
  585. display: flex;
  586. flex-direction: column;
  587. overflow: hidden;
  588. }
  589. }
  590. .pagination-container {
  591. margin-top: 15px;
  592. display: flex;
  593. justify-content: flex-start;
  594. }
  595. // 表格样式覆盖 (参考 coinConsumeDetail)
  596. :deep(.el-table__header-wrapper),
  597. :deep(.el-table__body-wrapper),
  598. :deep(.el-table__cell),
  599. :deep(.el-table__body td) {
  600. background-color: #F3FAFE !important;
  601. }
  602. :deep(.el-table__row:hover > .el-table__cell) {
  603. background-color: #E5EBFE !important;
  604. }
  605. .refundDialog {
  606. .left {
  607. width: 50%;
  608. height: 70vh;
  609. min-height: 700px;
  610. padding: 0 2vw;
  611. .add-item {
  612. display: flex;
  613. align-items: center;
  614. margin-bottom: 1vh;
  615. }
  616. .image {
  617. width: 4vw !important;
  618. height: 4vw !important;
  619. }
  620. }
  621. .right {
  622. width: 50%;
  623. height: 50vh;
  624. .add-item {
  625. display: flex;
  626. align-items: center;
  627. margin-bottom: 1vh;
  628. }
  629. }
  630. }
  631. .recallDialog {
  632. //撤回弹窗提示
  633. height: 392px;
  634. width: 700px;
  635. background-image: url('/src/assets/receive-recall.png');
  636. position: fixed; // 固定定位,相对于浏览器窗口
  637. top: 50%; // 距离顶部50%
  638. left: 50%; // 距离左侧50%
  639. transform: translate(-50%, -50%); // 向左、向上平移自身宽高的50%,实现居中
  640. z-index: 1000; // 确保在其他元素上层显示
  641. .close {
  642. position: absolute;
  643. left: 625px;
  644. top: 20px;
  645. height: 38px;
  646. width: 38px;
  647. opacity: 0;
  648. .Btn {
  649. height: 100%;
  650. width: 100%;
  651. border-radius: 10px;
  652. }
  653. }
  654. .text {
  655. position: absolute;
  656. left: 185px;
  657. top: 190px;
  658. height: 67px;
  659. width: 500px;
  660. .txt {
  661. height: 100%;
  662. width: 100%;
  663. color: #001a42;
  664. font-family: "PingFang SC";
  665. font-size: 48px;
  666. font-style: normal;
  667. font-weight: 900;
  668. line-height: normal;
  669. }
  670. }
  671. .cancle {
  672. position: absolute;
  673. left: 185px;
  674. top: 304px;
  675. height: 55px;
  676. width: 150px;
  677. opacity: 0;
  678. .Btn {
  679. height: 100%;
  680. width: 100%;
  681. border-radius: 20px;
  682. }
  683. }
  684. .confirm {
  685. position: absolute;
  686. left: 375px;
  687. top: 304px;
  688. height: 55px;
  689. width: 150px;
  690. opacity: 0;
  691. .Btn {
  692. height: 100%;
  693. width: 100%;
  694. border-radius: 20px;
  695. }
  696. }
  697. }
  698. </style>