|
@@ -0,0 +1,383 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <div class="list-view">
|
|
|
|
|
+ <page-title> </page-title>
|
|
|
|
|
+ <div class="filters-container">
|
|
|
|
|
+ <el-input
|
|
|
|
|
+ placeholder="搜索..."
|
|
|
|
|
+ v-model="search"
|
|
|
|
|
+ clearable
|
|
|
|
|
+ class="filter-item search"
|
|
|
|
|
+ @keyup.enter.native="getData"
|
|
|
|
|
+ >
|
|
|
|
|
+ <el-button @click="getData" slot="append" icon="el-icon-search"> </el-button>
|
|
|
|
|
+ </el-input>
|
|
|
|
|
+ <el-popover class="filter-item" placement="bottom" width="350" trigger="click" v-model="showSettlePop">
|
|
|
|
|
+ <el-date-picker
|
|
|
|
|
+ type="daterange"
|
|
|
|
|
+ value-format="yyyy-MM-dd"
|
|
|
|
|
+ v-model="date"
|
|
|
|
|
+ start-placeholder="开始日期"
|
|
|
|
|
+ end-placeholder="结束日期"
|
|
|
|
|
+ :disabled="settleing"
|
|
|
|
|
+ ></el-date-picker>
|
|
|
|
|
+ <el-button
|
|
|
|
|
+ style="float: right; margin-top: 10px"
|
|
|
|
|
+ size="mini"
|
|
|
|
|
+ type="primary"
|
|
|
|
|
+ @click="settle"
|
|
|
|
|
+ :loading="settleing"
|
|
|
|
|
+ >
|
|
|
|
|
+ 确认
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ <el-button @click="showSettlePop = false" style="float: right; margin: 10px 10px 0 0" size="mini">
|
|
|
|
|
+ 取消
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ <el-button slot="reference" size="mini" type="primary">结算</el-button>
|
|
|
|
|
+ </el-popover>
|
|
|
|
|
+ <el-button class="filter-item" type="primary" @click="exportWithdraw" :loading="downloading" size="mini">
|
|
|
|
|
+ 全部提现并导出Excel
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ <el-button class="filter-item" type="primary" @click="(showHisotryDialog = true), getHistory()" size="mini">
|
|
|
|
|
+ 历史记录
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ <el-button class="filter-item" type="primary" @click="showImportDialog = true" size="mini">
|
|
|
|
|
+ 导入结果
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <el-table
|
|
|
|
|
+ :data="tableData"
|
|
|
|
|
+ row-key="id"
|
|
|
|
|
+ ref="table"
|
|
|
|
|
+ header-row-class-name="table-header-row"
|
|
|
|
|
+ header-cell-class-name="table-header-cell"
|
|
|
|
|
+ row-class-name="table-row"
|
|
|
|
|
+ cell-class-name="table-cell"
|
|
|
|
|
+ :height="tableHeight"
|
|
|
|
|
+ v-loading="fetchingData"
|
|
|
|
|
+ >
|
|
|
|
|
+ <el-table-column prop="userId" label="用户ID"></el-table-column>
|
|
|
|
|
+ <el-table-column prop="balance" label="余额"></el-table-column>
|
|
|
|
|
+ <el-table-column width="100">
|
|
|
|
|
+ <template v-slot="{ row }">
|
|
|
|
|
+ <el-button size="mini" type="primary" @click="showRecords(row.userId)">查看记录</el-button>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ </el-table>
|
|
|
|
|
+ <div class="pagination-wrapper">
|
|
|
|
|
+ <el-pagination
|
|
|
|
|
+ background
|
|
|
|
|
+ @size-change="onSizeChange"
|
|
|
|
|
+ @current-change="onCurrentChange"
|
|
|
|
|
+ :current-page="page"
|
|
|
|
|
+ :page-sizes="[10, 20, 30, 40, 50]"
|
|
|
|
|
+ :page-size="pageSize"
|
|
|
|
|
+ layout="total, sizes, prev, pager, next, jumper"
|
|
|
|
|
+ :total="totalElements"
|
|
|
|
|
+ >
|
|
|
|
|
+ </el-pagination>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <el-dialog :visible.sync="showSettleDialog" title="选择日期" width="500">
|
|
|
|
|
+ <el-date-picker
|
|
|
|
|
+ type="daterange"
|
|
|
|
|
+ value-format="yyyy-MM-dd"
|
|
|
|
|
+ v-model="date"
|
|
|
|
|
+ start-placeholder="开始日期"
|
|
|
|
|
+ end-placeholder="结束日期"
|
|
|
|
|
+ ></el-date-picker>
|
|
|
|
|
+ <div slot="footer">
|
|
|
|
|
+ <el-button size="mini" @click="showSettleDialog = false" :disabled="settleing">取消</el-button>
|
|
|
|
|
+ <el-button size="mini" @click="settle" :loading="settleing" type="primary">确认</el-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </el-dialog>
|
|
|
|
|
+
|
|
|
|
|
+ <el-dialog :visible.sync="showImportDialog" title="导入结果">
|
|
|
|
|
+ <el-form>
|
|
|
|
|
+ <el-form-item label="提现导出文件">
|
|
|
|
|
+ <input @change="change('withdrawFile', $event)" type="file" />
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item label="提现结果文件">
|
|
|
|
|
+ <input @change="change('settleFile', $event)" type="file" />
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ </el-form>
|
|
|
|
|
+ <div slot="footer">
|
|
|
|
|
+ <el-button @click="showImportDialog = false" size="mini" :disabled="importFailLoading">取消</el-button>
|
|
|
|
|
+ <el-button @click="importFail" size="mini" type="primary" :loading="importFailLoading">导入</el-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </el-dialog>
|
|
|
|
|
+
|
|
|
|
|
+ <el-dialog :visible.sync="showRecordDialog" title="余额记录" width="600">
|
|
|
|
|
+ <el-table :data="record.list" height="calc(100vh - 500px)" v-loading="record.loading">
|
|
|
|
|
+ <el-table-column prop="createdAt" label="时间"></el-table-column>
|
|
|
|
|
+ <el-table-column prop="amount" label="金额">
|
|
|
|
|
+ <template v-slot="{ row }">
|
|
|
|
|
+ <span :style="{ color: row.amount >= 0 ? '#f56c6c' : '#67c23a' }">
|
|
|
|
|
+ {{ row.amount >= 0 ? '+' : '' }}{{ row.amount }}
|
|
|
|
|
+ </span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column prop="balance" label="余额"></el-table-column>
|
|
|
|
|
+ <el-table-column prop="lastBalance" label="上次余额"></el-table-column>
|
|
|
|
|
+ <el-table-column prop="type" label="类型" :formatter="balanceTypeFormatter"></el-table-column>
|
|
|
|
|
+ </el-table>
|
|
|
|
|
+ <el-pagination
|
|
|
|
|
+ style="margin-top: 10px"
|
|
|
|
|
+ background
|
|
|
|
|
+ @size-change="onSizeChange($event, 'record')"
|
|
|
|
|
+ @current-change="onCurrentChange($event, 'record')"
|
|
|
|
|
+ :current-page="record.page"
|
|
|
|
|
+ :page-sizes="[10, 20, 30, 40, 50]"
|
|
|
|
|
+ :page-size="record.pageSize"
|
|
|
|
|
+ layout="total, sizes, prev, pager, next, jumper"
|
|
|
|
|
+ :total="record.totalElements"
|
|
|
|
|
+ ></el-pagination>
|
|
|
|
|
+ </el-dialog>
|
|
|
|
|
+
|
|
|
|
|
+ <el-dialog :visible.sync="showHisotryDialog" title="历史记录" width="500">
|
|
|
|
|
+ <el-table :data="history.list" height="calc(100vh - 500px)" v-loading="history.loading">
|
|
|
|
|
+ <el-table-column prop="createdAt" label="时间"></el-table-column>
|
|
|
|
|
+ <el-table-column prop="lastBalance" label="操作" width="100">
|
|
|
|
|
+ <template v-slot="{ row }">
|
|
|
|
|
+ <el-button @click="download(row)" type="text">下载</el-button>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ </el-table>
|
|
|
|
|
+ <el-pagination
|
|
|
|
|
+ style="margin-top: 10px"
|
|
|
|
|
+ background
|
|
|
|
|
+ @size-change="onSizeChange($event, 'history')"
|
|
|
|
|
+ @current-change="onCurrentChange($event, 'history')"
|
|
|
|
|
+ :current-page="record.page"
|
|
|
|
|
+ :page-sizes="[10, 20, 30, 40, 50]"
|
|
|
|
|
+ :page-size="history.pageSize"
|
|
|
|
|
+ layout="total, sizes, prev, pager, next, jumper"
|
|
|
|
|
+ :total="history.totalElements"
|
|
|
|
|
+ ></el-pagination>
|
|
|
|
|
+ </el-dialog>
|
|
|
|
|
+ </div>
|
|
|
|
|
+</template>
|
|
|
|
|
+<script>
|
|
|
|
|
+import { mapState } from 'vuex';
|
|
|
|
|
+import pageableTable from '@/mixins/pageableTable';
|
|
|
|
|
+import { getDay, addDays, format } from 'date-fns';
|
|
|
|
|
+export default {
|
|
|
|
|
+ name: 'UserBalance',
|
|
|
|
|
+ mixins: [pageableTable],
|
|
|
|
|
+ data() {
|
|
|
|
|
+ return {
|
|
|
|
|
+ multipleMode: false,
|
|
|
|
|
+ search: '',
|
|
|
|
|
+ url: '/userBalance/all',
|
|
|
|
|
+ downloading: false,
|
|
|
|
|
+ typeOptions: [
|
|
|
|
|
+ { label: '默认', value: 'DEFAULT' },
|
|
|
|
|
+ { label: '盲盒', value: 'BLIND_BOX' },
|
|
|
|
|
+ { label: '拍卖', value: 'AUCTION' },
|
|
|
|
|
+ { label: '展厅', value: 'SHOWROOM' }
|
|
|
|
|
+ ],
|
|
|
|
|
+ sourceOptions: [
|
|
|
|
|
+ { label: '官方', value: 'OFFICIAL' },
|
|
|
|
|
+ { label: '用户铸造', value: 'USER' },
|
|
|
|
|
+ { label: '转让', value: 'TRANSFER' }
|
|
|
|
|
+ ],
|
|
|
|
|
+ balanceTypeOptions: [
|
|
|
|
|
+ { label: '提现', value: 'WITHDRAW' },
|
|
|
|
|
+ { label: '藏品出售', value: 'SELL' },
|
|
|
|
|
+ { label: '失败退回', value: 'RETURN' }
|
|
|
|
|
+ ],
|
|
|
|
|
+ sortStr: 'balance,desc',
|
|
|
|
|
+ date: null,
|
|
|
|
|
+ showSettleDialog: false,
|
|
|
|
|
+ showSettlePop: false,
|
|
|
|
|
+ settleing: false,
|
|
|
|
|
+ showImportDialog: false,
|
|
|
|
|
+ withdrawFile: null,
|
|
|
|
|
+ settleFile: null,
|
|
|
|
|
+ importFailLoading: false,
|
|
|
|
|
+ showRecordDialog: false,
|
|
|
|
|
+ record: {
|
|
|
|
|
+ list: [],
|
|
|
|
|
+ userId: null,
|
|
|
|
|
+ page: 1,
|
|
|
|
|
+ pageSize: 20,
|
|
|
|
|
+ totalElements: 0,
|
|
|
|
|
+ loading: false
|
|
|
|
|
+ },
|
|
|
|
|
+ showHisotryDialog: false,
|
|
|
|
|
+ history: {
|
|
|
|
|
+ list: [],
|
|
|
|
|
+ userId: null,
|
|
|
|
|
+ page: 1,
|
|
|
|
|
+ pageSize: 20,
|
|
|
|
|
+ totalElements: 0,
|
|
|
|
|
+ loading: false
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+ },
|
|
|
|
|
+ computed: {
|
|
|
|
|
+ selection() {
|
|
|
|
|
+ return this.$refs.table.selection.map(i => i.id);
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ created() {
|
|
|
|
|
+ let week = getDay(new Date());
|
|
|
|
|
+ if (week === 1) {
|
|
|
|
|
+ this.date = [format(addDays(new Date(), -3), 'yyyy-MM-dd'), format(addDays(new Date(), -1), 'yyyy-MM-dd')];
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.date = [format(addDays(new Date(), -1), 'yyyy-MM-dd'), format(addDays(new Date(), -1), 'yyyy-MM-dd')];
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ methods: {
|
|
|
|
|
+ balanceTypeFormatter(row, column, cellValue, index) {
|
|
|
|
|
+ return (this.balanceTypeOptions.find(i => i.value === cellValue) || {}).label;
|
|
|
|
|
+ },
|
|
|
|
|
+ beforeGetData() {
|
|
|
|
|
+ return {
|
|
|
|
|
+ query: {
|
|
|
|
|
+ userId: this.search
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+ },
|
|
|
|
|
+ settle() {
|
|
|
|
|
+ if (!(this.date && this.date.length === 2)) {
|
|
|
|
|
+ this.$message.error('请选择日期');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ this.settleing = true;
|
|
|
|
|
+ this.$http
|
|
|
|
|
+ .post('/userBalance/settle', { start: this.date[0], end: this.date[1] })
|
|
|
|
|
+ .then(res => {
|
|
|
|
|
+ this.settleing = false;
|
|
|
|
|
+ this.showSettleDialog = false;
|
|
|
|
|
+ this.showSettlePop = false;
|
|
|
|
|
+ this.$message.success('成功');
|
|
|
|
|
+ this.getData();
|
|
|
|
|
+ })
|
|
|
|
|
+ .catch(e => {
|
|
|
|
|
+ this.settleing = false;
|
|
|
|
|
+ this.showSettleDialog = false;
|
|
|
|
|
+ this.showSettlePop = false;
|
|
|
|
|
+ this.$message.error(e.error || '失败');
|
|
|
|
|
+ });
|
|
|
|
|
+ },
|
|
|
|
|
+ exportWithdraw() {
|
|
|
|
|
+ this.downloading = true;
|
|
|
|
|
+ this.$http
|
|
|
|
|
+ .post('/userBalance/exportWithdraw')
|
|
|
|
|
+ .then(res => {
|
|
|
|
|
+ this.downloading = false;
|
|
|
|
|
+ window.open(res.url, '_blank');
|
|
|
|
|
+ this.getData();
|
|
|
|
|
+ })
|
|
|
|
|
+ .catch(e => {
|
|
|
|
|
+ console.log(e);
|
|
|
|
|
+ this.downloading = false;
|
|
|
|
|
+ this.$message.error(e.error);
|
|
|
|
|
+ });
|
|
|
|
|
+ },
|
|
|
|
|
+ change(file, e) {
|
|
|
|
|
+ if (e.target.files && e.target.files[0]) {
|
|
|
|
|
+ this[file] = e.target.files[0];
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ importFail() {
|
|
|
|
|
+ if (!this.settleFile) {
|
|
|
|
|
+ this.$message.error('请选择提现结果文件');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!this.withdrawFile) {
|
|
|
|
|
+ this.$message.error('请选择提现导出文件');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ this.importFailLoading = true;
|
|
|
|
|
+ let form = new FormData();
|
|
|
|
|
+ form.append('withdrawList', this.withdrawFile);
|
|
|
|
|
+ form.append('failList', this.settleFile);
|
|
|
|
|
+ this.$axios
|
|
|
|
|
+ .post('/userBalance/importFail', form)
|
|
|
|
|
+ .then(res => {
|
|
|
|
|
+ this.importFailLoading = false;
|
|
|
|
|
+ this.showImportDialog = false;
|
|
|
|
|
+ this.$message.success('成功');
|
|
|
|
|
+ this.getData();
|
|
|
|
|
+ })
|
|
|
|
|
+ .catch(e => {
|
|
|
|
|
+ this.importFailLoading = false;
|
|
|
|
|
+ this.$message.error(e.error || '失败');
|
|
|
|
|
+ });
|
|
|
|
|
+ },
|
|
|
|
|
+ showRecords(userId) {
|
|
|
|
|
+ this.userId = userId;
|
|
|
|
|
+ this.record.list = [];
|
|
|
|
|
+ this.showRecordDialog = true;
|
|
|
|
|
+ this.page = 1;
|
|
|
|
|
+ this.getRecords();
|
|
|
|
|
+ },
|
|
|
|
|
+ getRecords() {
|
|
|
|
|
+ this.record.loading = true;
|
|
|
|
|
+ this.$http
|
|
|
|
|
+ .post(
|
|
|
|
|
+ '/userBalance/records',
|
|
|
|
|
+ {
|
|
|
|
|
+ query: { userId: this.userId },
|
|
|
|
|
+ page: this.record.page - 1,
|
|
|
|
|
+ size: this.record.pageSize,
|
|
|
|
|
+ sort: 'id,desc'
|
|
|
|
|
+ },
|
|
|
|
|
+ { body: 'json' }
|
|
|
|
|
+ )
|
|
|
|
|
+ .then(res => {
|
|
|
|
|
+ this.record.loading = false;
|
|
|
|
|
+ this.record.list = res.content;
|
|
|
|
|
+ this.record.totalElements = Number(res.totalElements);
|
|
|
|
|
+ })
|
|
|
|
|
+ .catch(e => {
|
|
|
|
|
+ this.record.loading = false;
|
|
|
|
|
+ });
|
|
|
|
|
+ },
|
|
|
|
|
+ onSizeChange(e, type) {
|
|
|
|
|
+ this[type].page = 1;
|
|
|
|
|
+ this[type].pageSize = e;
|
|
|
|
|
+ if (type === 'record') {
|
|
|
|
|
+ this.getRecords();
|
|
|
|
|
+ } else if (type === 'history') {
|
|
|
|
|
+ this.getHistory();
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ onCurrentChange(e) {
|
|
|
|
|
+ this[type].page = e;
|
|
|
|
|
+ if (type === 'record') {
|
|
|
|
|
+ this.getRecords();
|
|
|
|
|
+ } else if (type === 'history') {
|
|
|
|
|
+ this.getHistory();
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ getHistory() {
|
|
|
|
|
+ this.history.loading = true;
|
|
|
|
|
+ this.$http
|
|
|
|
|
+ .post(
|
|
|
|
|
+ '/userBalance/exportHistory',
|
|
|
|
|
+ {
|
|
|
|
|
+ page: this.history.page - 1,
|
|
|
|
|
+ size: this.history.pageSize,
|
|
|
|
|
+ sort: 'id,desc'
|
|
|
|
|
+ },
|
|
|
|
|
+ { body: 'json' }
|
|
|
|
|
+ )
|
|
|
|
|
+ .then(res => {
|
|
|
|
|
+ this.history.loading = false;
|
|
|
|
|
+ this.history.list = res.content;
|
|
|
|
|
+ this.history.totalElements = Number(res.totalElements);
|
|
|
|
|
+ })
|
|
|
|
|
+ .catch(e => {
|
|
|
|
|
+ this.history.loading = false;
|
|
|
|
|
+ });
|
|
|
|
|
+ },
|
|
|
|
|
+ download(row) {
|
|
|
|
|
+ window.open(row.url, '_blank');
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+</script>
|
|
|
|
|
+<style lang="less" scoped>
|
|
|
|
|
+</style>
|